Wie eine einzelne Transaktion das Ethereum-Netzwerk in Verwirrung stürzte

Skulptur eines gespaltenen Hasen. Bild von Tim Green via flickr.com. Lizenz: Creative Commons

Gestern gab es einen Konsens-Fehler in Ethereum: Das Netzwerk war sich nicht länger einig, welche Blöcke gültig sind. Das stiftete viel Verwirrung, verursachte aber keine Verluste. Man könnte sagen: Der Worst Case ist eingetreten – war aber doch recht harmlos.

Für die Ethereum-Szene war gestern ein aufregender Tag. Sie erlebte einen jener Momente, in denen der Worst Case eintritt: Es beginnt mit Verwirrung, weil etwas passiert, das nicht passieren darf. Dann legt sich der Nebel, man sieht, was wirklich los ist, und viele klugen Köpfe müssen hellwach sein, um den Schaden aus der Welt zu bringen.

Als einer der ersten fiel dem Blockexplorer Blockchair auf, das etwas nicht stimmte. Er twitterte:

Zu deutsch: Wir haben ein Problem mit Ethereum. Es sieht aus, als sei es zu einem Chainsplit gekommen, und einige Knoten sind auf der Minderheitenchain stecken geblieben.

Ein Chainsplit, also eine Spaltung der Kette, ist ziemlich genau das, was einer Blockchain nicht passieren sollte. Sie verliert den Konsens über die Historie; die einen Nodes denken, das sei passiert, und die anderen, jenes. Dabei gibt es die Blockchain genau darum: um zu verhindern, dass sich Nodes in einem dezentralen Netzwerk uneinig über die Vergangenheit sind.

Das klingt also nach einem ziemlich üblen, extrem ernsten Problem.

Nikita Zhavoronkov, der Blockchair betreibt, erklärt kurz darauf den Error:

Der Node von Blockchair hat einen Block abgelehnt, weil der „Merkle-Root“, zu deutsch, die Wurzel des Hashbaums, nicht valide ist. Diese Wurzel ist quasi ein Destillat des Blocks, den die Miner an die Blockchain anhängen. Sie erlaubt es allen Knoten, zu prüfen, ob der Block gültig ist. Wenn die Prüfung scheitert, lehnen sie den Block ab. Das ist eine vollkommen richtige Reaktion.

Nicht richtig ist es aber, wenn die einen Knoten, so wie der von Blockchair, einen Block ablehnen, die anderen ihn aber akzeptieren.

Der Bug zieht weite Kreise durchs ganze Ökosystem

Péter Szilágy, einer der führenden Leitentwickler von Ethereum, empfiehlt Nikita, die Software des Nodes, Geth, zu aktualisieren. Nikita meint zwar zuerst, dass der Backup-Node von Blockchair dieselbe Version benutzt, wie der andere, ohne das Problem zu haben. Er vermutet daher ein globales Problem, auch da Infura und andere Knoten down sind. Nachdem er Geth aktualisiert hat, funktioniert Blockchair allerdings wieder.

Tatsächlich tauchten kurz danach Berichte auf, dass Börsen, die Infura benutzen, Auszahlungen von Ether und ERC-Token ausgesetzt haben. Infura ist eine Art Infrastrukturanbieter bei Ethereum: Ein Netzwerk von Knoten, die eine API bereitstellen, über die andere in Echtzeit zuverlässige Informationen von der Ethereum-Blockchain bekommen.

Böse Zungen behaupten, Ethereum laufe zentralisiert auf den Servern von Infura, was nicht ganz unberechtigt ist, wenn man sich anschaut, wen Infura zu seinen Kunden zählt: UniSwap, Compound, Maker, um nur ein paar zu nennen; zudem verbindet sich die beliebte Wallet MetaMask standardmäßig mit Infura. Der Fehler gestern zeigte nun, WIE abhängig Ethereum von Infura ist. Nicht nur Wallets und dApps benutzen die API, sondern auch einige Börsen, etwa Binance, Bithumb, Upbit and Crypto.com – alles kleine kleinen, unbedeutenden Handelsplätz, sondern große Plattformen, die an manchen Tagen Milliarden von Dollar an Volumen umsetzen.

Infura bestätigte, ein Problem zu haben, und vermeldete auf der Status-Seite den ersten „Major Outage“, also den ersten großen Ausfall, überhaupt.

Aber was war passiert? Ein Hack? Ein Bug? Weshalb waren die Knoten von Infura auf der falschen Blockchain gelandet?

Der komplexe Grund, weshalb der Konsens-Fehler seit rund einem Jahr geschlummert hat

Die Erkärung ist ziemlich komplizierter. Leider. Péter Szilágy erklärt in einem Post-Mortem-Post, was genau geschehen ist: Schon die im November 2019 veröffentlichte Version von Geth, 1.9.7, hat einen Konsens-Bug eingeführt, indem sie EIP-211 unter bestimmten, sehr speziellen Bedingungen verletzte.

Jeder Konsens-Bug kann einen Split der Blockchain verursachen; dieser aber scheint eher esoterisch gewesen zu sein, da er weder zum Chainsplit führte noch jemandem zeitnah auffiel. Erst ein Dreivierteljahr später, im Juli 2020, entdeckte ein Entwickler den Fehler. Der wurde daraufhin mit Geth 1.9.17 heimlich behoben.

Die Ethereum-Entwickler hatten also schon im Juli 2020 das eingeführt, was man gemeinhin eine „Hardfork“ nennt: Eine Änderung der Regeln mit einer neuen Version, so dass diese unter Umständen nicht mehr mit der alten Version kompatibel ist. Anders als viele meinen, führt eine Hardfork aber nicht sofort zum Split, sondern erst dann, wenn das entsprechende Ereignis eintritt – welches im Fall des EIP-211-Bugs so esoterisch ist, dass ich nicht mal im Ansatz verstehe, worum es überhaupt geht (wer will, möge sich selbst über EUP-211 informieren).

Wie auch immer: Geth 1.9.17, veröffentlich im Juli, war in einem bestimmten Aspekt nicht länger kompatibel mit den vorhergegangenen Versionen von Geth. Péter Szilágy drückt es so aus: Die Geth-Entwickler haben versehentlich einen Bug eingeführt und ihn nun behoben. Wenn man einen Bug keine „Konsens-Änderung“ nenne, sei auch der Fix keine.

Allerdings haben nicht alle Knoten das Update zu 1.9.17 mitgemacht. Etwa Blockchair. Oder auch Infura, wie der API-Anbieter erklärt: Man habe Geth 1.9.9 und 1.9.13 für einige „interne Systeme“ benutzt.

Gestern Morgen nun geschah es: Eine Transaktion hat das Konsens-Problem getriggert. Die Transaktion hat das vermutlich absichtlich gemacht, wurde also nur geschrieben, um den Fehler auszunutzen. Zumindest legt Szilágys Post das nahe, auch wenn man nicht weiß, wer dies weshalb getan hat.

Die Folge war, dass ein Knoten von Blockchair einen Block ablehnte, da dieser nach den Konsensregeln von Geth < 1.9.17 ungültig war. Auch die Knoten der „internen Systeme“ von Infura hörten auf, die Blöcke zu synchronisieren. Die Cloud-Architektur von Infura ist so komplex, dass das gesamte System zwar an sich live blieb, aber die API, von der so viele Plattformen abhängen, herunterfuhr.

Wenige Stunden später hatte Infura die Knoten aktualisiert und die Blockchain wieder synchronisiert. Auch Blockchair war wieder auf dem neuesten Stand. Die Börsen und Plattformen, die Infura benutzten, nahmen wieder Kontakt zur Ethereum-Blockchain auf.

Alles wurde schnell und professionell geregelt. Doch was bleibt von dem Bug?

Wenn alle alles richtig machen kann man nichts besser machen

Aus nichts lernt man so gut wie aus Fehlern und Unglücksfällen. Das trifft auch auf diesen Bug zu.

Zunächst einmal finden die Beteiligten, dass sie alles richtig gemacht haben, was eine geradezu verzweifelte und resignierende Unterwerfung unter die komplexe Wirklichkeit ist. Péter Szilágy erklärt ausführlich und reflektiert, weshalb man den Bug heimlich gefixt habe, weshalb das Vorgehen (lange) funktioniert habe, und dass die Entwickler anderer Kryptowährungen es ebenso handhaben. In einem dezentralen Netzwerk brauchen Updates Zeit. Daher gibt es keine Alternative zu einem heimlichen Fix eines schlimmen Bugs.

Auch Infura hat gute Gründe, alte Versionen von Geth parallel laufen zu lassen: Um zu verhindern, dass neu eingeführte Änderungen oder Bugs – kleine Bugs – die Infura-Cloud stören, sind die Entwickler mittlerweile sehr vorsichtig und gründlich mit Upgrades. Neue Versionen werden ausführlich getestet und an die hauseigene, auf Cloud-Performance getrimmte Version angepasst. Natürlich führt man Konsens-ändernde Updates zeitiger ein, doch das Team von Geth habe Infura nicht informiert, dass Version 1.9.17 ein solches Update enthalte – was auch richtig so sei: „Wir haben zwar einen guten Draht zum Geth-Team, haben aber niemals erwartet, irgendeine besondere Behandlung oder Zugang zu Insiderinformationen zu genießen. Keine Börse, kein Miner, kein API-Provider sollte anders behandelt werden als ein einzelner Betreiber eines Knotens.“

Es wurde also alles richtig gemacht – und zwar von allen. Der Vorfall hat weder einen Schuldigen noch einen Fehler. Es gibt so gut wie nichts, was man tun kann, um ihn in Zukunft zu verhindern. Man kann nur (noch) wacher und aufmerksamer sein.

Weniger zentralisiert als gefürchtet

Es bleibt aber mehr als Resignation. Viel mehr. Im Grunde gibt der Bug auch einen Anlass zu unerhörtem Optimismus.

Denn erstens ist der Worst Case geschehen – ein Hacker konnte absichtlich die Ethereum-Chain spalten – und es ging – überhaupt nichts zu Bruch. Keine Tasse, kein Teller ist zersprungen, kein Bruchstück eines Ethers oder eines Tokens ging verloren. Einige Börsen und einige Plattformen haben für einige Stunden den Kontakt zur Blockchain verloren, Metamask hat partiell nicht richtig funktioniert. Das war’s. Es ist nicht so, dass man das jeden Tag haben will – aber auch nicht so, dass die Welt oder auch nur ein Acker untergeht.

Zweitens ist die Sache mit der Zentralisierung wohl doch nicht so schlimm wie gedacht. Geth, die führende Implementierung von Ethereum, hat einen Bug eingeführt. Wenn man sagt, der Code sei das Protokoll, wie es bei Bitcoin zum Teil gesagt wird, wo es nur eine einzige Implementierung gibt, würde das bedeuten, dass die Entwickler keinen Bug verbrochen, sondern das Konsens-Protokoll verändert haben. So wäre es in einem zentralisierten System. Doch es war für die Geth-Entwickler keine Sekunde lang eine Frage, dass sie ihre Software an den Konsens der anderen Knoten anzupassen haben. Das, was „Konsens“ ist, entscheidet weiterhin nicht ein Team von Entwicklern, egal wie wichtig ihre Software ist.

Auch eine übermächtige Cloud-Infrastruktur wie Infura bestimmt nicht den Konsens. Ein Teil von Infura hat aufgehört, dieselbe Sicht auf die Vergangenheit zu haben wie der Rest des Netzwerks. Doch an keiner Stelle war es überhaupt eine Frage, wer sich irrt und wer nicht. Es war jederzeit glasklar, dass Infura etwas falsch verstanden hat und die anderen Recht haben.

Selbst wenn die Personen hinter Geth und Infura die Absicht hätten, den Konsens zu ändern – es wäre gar nicht möglich. Das Ethereum-System hat zu viele Checks und Balances, zu viele Parteien, die mitsprechen können: Die Miner, die die Blöcke an die Blockchains anhängen, die Entwickler der verschiedenen Implementierungen, die Betreiber von Blockexplorer, die vielen Börsen, die Ethereum listen, die Ethereum Foundation und noch viele mehr.

Es ist schwierig, könnte man sagen, etwas dezentral zu machen. Aber es ist ebenso schwierig, wenn nicht unmöglich, ein System wieder zu zentralisieren, sobald es einmal wirklich dezentral war.

Über Christoph Bergmann (1902 Beiträge)
Das Bitcoinblog wird von Bitcoin.de gesponsort, ist inhaltlich aber unabhängig und gibt die Meinung des Redakteurs Christoph Bergmann wieder. Christoph hat vor kurzem ein Buch geschrieben: Bitcoin: Die verrückte Geschichte vom Aufstieg eines neuen Geldes. Das Buch stellt Bitcoin in seiner ganzen Pracht dar. Ihr könnt es direkt auf der Webseite Bitcoin-Buch.org bestellen - natürlich auch mit Bitcoin - oder auch per Amazon. Natürlich freuen wir uns auch über Spenden in Bitcoin, Bitcoin Cash oder Bitcoin SV an die folgende Adresse: 1BergmanNpFqZwALMRe8GHJqGhtEFD3xMw. Wer will, kann uns auch Hier mit Lightning spenden. Tipps für Stories sind an christoph.bergmann@mailbox.org immer erwünscht. Wer dies privat machen möchte, sollte meinen PGP-Schlüssel verwenden.

2 Kommentare zu Wie eine einzelne Transaktion das Ethereum-Netzwerk in Verwirrung stürzte

  1. Was würde bei ETH2.0 passieren, wenn man als Validator am Staken ist und sich durch noch fehlerhafte, „alte“ Software auf die nicht konsensfähige Chain gerät? Wer dort Blöcke validiert gilt doch dann als betrügerisch und wird auf der finalen Chain bestraft (geslasht), oder sehe ich das falsch?

    Es wäre dann also wichtig, die stets aktuelle Software für den Validator zu nutzen und zu hoffen, dass diese keine üblen Lücken wie DoS oder Remote Code Execution enthält.

  2. Ein Chainsplit bringt immer Risiken, es könnte zu Double Spend Attacken gekommen sein, aber tatsächlich ist dies bei einer Hard Fork leider nicht gänzlich vermeidbar, weil nie alle Teilnehmer rechtzeitig updaten. Deswegen haben viele Börsen auch sofort die Wallets für Ein-/Auszahlungen eingefroren, um sich keinem Risiko auszusetzen.
    Selbst bei den geplanten Hard Forks alle 6-12 Monate bei Monero verpeilen es einige immer noch, mittlerweile gibt es zum Glück eine ziemlich abgesicherten Auto-Update Mechanismus, dem der User zwar noch zustimmen muss/kann, aber so gut wie ausgeschlossen ist, dass er von jemandem externen kompromittiert wird. Wo früher alle 6 Monate fix ein Hard Fork stattgefunden hat, ist man mittlerweile dazu übergegangen, diese nur noch bei wichtigen Protokolländerungen durchzuführen, etwa alle 9-12 Monate und möglichst früh anzukündigen, um allen Teilnehmern ein rechtzeitiges Update zu ermöglichen.

    Es wurde also alles richtig gemacht – und zwar von allen. Der Vorfall hat weder einen Schuldigen noch einen Fehler. Es gibt so gut wie nichts, was man tun kann, um ihn in Zukunft zu verhindern. Man kann nur (noch) wacher und aufmerksamer sein.

    Ob alles richtig gemacht wurde, muss jeder für sich entscheiden. Ich denke, man hätte das Update schon pushen sollen, mit dem Hinweis auf einen potenziellen Konsens-Bug, womöglich zuerst die großen Nodes.

    Bei Monero bzw. von Cryptonote gab es vor einiger Zeit einen Double Spending Bug, der zum Glück von den Entwicklern gefunden wurde, bevor ihn jemand ausgenutzt hat. Aber auch damals wurde er in Konspiration gefixt und in einen geplanten Hard-Fork mit eingebaut, der Pull Request selbst wurde als dDoS Schutz verkauft und niemand hat den wahren Grund mitbekommen, denn man hätte den Exploit selbst bei Monero auf der Blockchain nachweisen können, da Key Images doppelt genutzt würden. Als das Protokollupgrade durch war, hat man im Geheimen alle Cryptonote Coins informiert, worauf z.B. die Bytecoin Entwickler üppig zugelangt haben, bevor sie den Fix implementiert haben… Erst einen Monat später wurde der Bug veröffentlicht, etliche „Entwickler“ von Cryptonote Forks haben ihren Code trotzdem nicht gefixt, obwohl er als Copy&Paste vorlag.

    Auch bei der letzten Monero Hard Fork, die deutliche Optimierungen gebracht hat, kam es zu einer Art Chainsplit, der zwar nicht tragisch war, aber dadurch zustande kam, dass ab einer gewissen Blockhöhe der Konsens geändert wurde, allerdings eine Transaktion im tx-Pool (mempool) den alten Konsens hatte und von allen Nodes, die online waren auch bereits validiert wurde. Ein Miner hat sie nach der definierten Block Höhe in einen Block gepackt und alle Nodes, die die Transaktion kannten, akzeptierten diesen Block auch als valide, alle anderen, die gerade offline waren, konnten nicht synchronisieren, da der Block nach neuem Konsens nicht mehr valide war. Wurde zwar binnen 24 Stunden gefixt, aber trotzdem nicht schön.

    Insgesamt ist das Handling von Bugs immer eine schwierige Abwägung, vor allem wenn auch andere Projekte davon betroffen sind. Ich hätte bei Ethereum wahrscheinlich den Weg gewählt, die wichtigsten Nodes / Anbieter / Börsen mindestens eine Woche vor einer Full Disclosure zu informieren und hätte den Hard Fork nicht riskiert sondern proaktiv veröffentlicht, aber auch unter den Erstinformierten könnten sich schwarze Schafe befinden, die das ausnutzen…

Schreiben Sie einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Wechseln )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Wechseln )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Wechseln )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Wechseln )

Verbinde mit %s