NEU: Helius übernimmt Light Protocol
Konsens auf Solana
Blog/Grundlagen

Konsens auf Solana

Forschung und DatenRyan Chern auf X
23 Min. Lesezeit

Praktische Erkenntnisse

  • Die Rolle von Proof-of-History (PoH) bei der Synchronisierung: PoH ist kein Konsensalgorithmus, sondern ein Werkzeug, das der Konsensmechanismus von Solana zur Synchronisierung nutzt. Ebenso ist Proof-of-Stake (PoS) kein Konsens, sondern ein Sybil-Schutz.
  • Abstimmungstransaktionen sind für den Konsens erforderlich: Abstimmungen innerhalb von Blöcken sind keine überflüssigen Transaktionen, die TPS-Metriken künstlich aufblähen. Würden Abstimmungen nur per Gossip verbreitet (informelle Peer-to-Peer-Kommunikation), könnten Validatoren den Zustand des Towers und seiner Abstimmungen unterschiedlich wahrnehmen.
  • Solana hat zwei primäre Bestätigungsregeln: eine für die kurzfristige Fork-Auswahl (optimistische Bestätigung) und eine für den vollständigen PoS-Konsens zur Finalität (finalisiert/verwurzelt). Clients und Nutzer können diese Bestätigungsregeln je nach gewünschten Sicherheitseigenschaften und individueller UX-Auswahl anwenden. Das spiegeln die beiden Verbindlichkeitsstufen „bestätigt“ und „finalisiert“ wider.
  • Zensurrisiken verstehen: Validatoren und Entwickler sollten mögliche Zensurangriffe kennen, bei denen ein Validator versucht, die Reihenfolge der Blockproduktion zu stören. Dazu gehört, die Mechanik solcher Angriffe sowie die Rolle von Rechenleistung und Stake bei ihrer Ausführung zu verstehen.
  • Künftige Protokoll-Upgrades stehen bevor: Validatoren und Entwickler sollten sich aktiv auf anstehende Änderungen am Konsensmechanismus von Solana vorbereiten, etwa asynchrone Ausführung und programmatisches Slashing.

Einführung

Da die Aktivität auf Solana zunimmt, werden verschiedene Schichten des Stacks in bisher unbekanntem Ausmaß getestet. Über „heiße“ Themen wie lokale Gebührenmärkte wurde viel geschrieben und diskutiert. Der Konsens auf Solana wurde dagegen lange übersehen. Die steigende Aktivität und das wachsende Interesse verlangen jedoch, dass die Community den Konsens gründlich versteht, da sowohl die Anreize für böswillige Angriffe als auch die Gewinne aus möglichen Exploits steigen.

Der Konsens gehört zu den wichtigsten Aspekten von Solana, die die gesamte Community verstehen sollte. Er bestimmt, wie sich Tausende Validatoren auf eine kanonische Reihenfolge von Transaktionen einigen.

Konsens wird in verteilten Systemen seit vielen Jahren erforscht. Das Problem der byzantinischen Generäle von Lamport, Shostak und Pease wurde Anfang der 1980er-Jahre veröffentlicht. Konsensalgorithmen wie RAFT werden in Web2 schon lange eingesetzt. In der Kryptowelt sind die meisten Konsensalgorithmen unterschiedliche Implementierungen des BFT-Konsenses, darunter Gasper (Ethereum), Tendermint (Cosmos), MonadBFT (Monad), HotShot (Espresso) und Narwhal/Tusk (Sui). 

Dieser Artikel versucht nicht, den Konsensmechanismus von Solana (TowerBFT) formal zu beweisen. Stattdessen erklärt er Entwicklern und der breiteren Community, wie der Konsens auf Solana funktioniert. Bisher existiert dieses Wissen vor allem in den Köpfen der Mitwirkenden von Solana Labs und Firedancer. Außerdem behandeln wir einige Abwägungen und Einschränkungen.

Kurze Einführung in den Konsens

Ein Konsensprotokoll soll eine Einigung über Transaktionen und ihre relative Reihenfolge innerhalb eines Blocks ermöglichen. Es gibt zwei Haupttypen von Konsensprotokollen, mit denen sich Validatoren in einem Netzwerk auf die kanonische Reihenfolge der Transaktionen einigen:

  • Longest-Chain-Protokolle: Diese Protokolle, etwa der Nakamoto-Konsens von Bitcoin, erklären die Chain für kanonisch, deren Aufbau den größten Rechenaufwand erfordert hat. Das korreliert häufig mit der Chain mit den meisten Blöcken. Präziser ist jedoch die Chain gemeint, die den größten kumulierten Arbeitsaufwand beziehungsweise die größte Rechenleistung verkörpert.
  • BFT-Protokolle: Die meisten PoS-Protokolle implementieren eine Variante eines BFT-Konsensalgorithmus. Diese Protokolle, etwa pBFT, basieren auf Schwellenwerten für Lebendigkeit und Sicherheit. Konsistenz und Verfügbarkeit sind zwei Garantien des CAP-Theorems. Es besagt, dass ein verteilter Datenspeicher nur zwei der folgenden drei Garantien bieten kann: Konsistenz, Verfügbarkeit und Partitionstoleranz.

Sowohl Longest-Chain- als auch BFT-Konsensprotokolle leiten ihre Sicherheit aus den jeweiligen Bestätigungsregeln ab. Sicherheit, bestehend aus Safety und Lebendigkeit, ergibt sich aus einer bestimmten Bestätigungsregel und ist keine Eigenschaft einer Chain. Nach der Definition der Ethereum Foundation ist eine Bestätigungsregel „ein von Nodes ausgeführter Algorithmus, der ausgibt, ob ein bestimmter Block bestätigt ist. Ist das der Fall, wird unter bestimmten Annahmen – vor allem zur Netzwerksynchronität und zum Anteil des ehrlichen Stakes – garantiert, dass dieser Block niemals reorganisiert wird.“

Letztlich beruht alles auf sozialem Konsens. Definiert wird er von Menschen, die Client-Code schreiben und über bestimmte Bestätigungsregeln ausdrücken, was Sicherheit ausmacht.

Proof-of-Stake erweitert das BFT-Modell um zusätzliche Schichten und verlangt von Teilnehmern, eigenen Stake einzusetzen. Sie werden für das Einhalten bestimmter Regeln belohnt, können bei nachgewiesenem Fehlverhalten, etwa doppeltem Signieren, aber mit Slashing bestraft werden. Das wird als zurechenbare Safety bezeichnet. Dadurch kann das Protokoll böswillige Nodes identifizieren und bestrafen, ohne ehrliche Nodes durch externe Effekte zu belasten. Es ersetzt nicht den grundlegenden Sicherheitsmechanismus von BFT-Konsensprotokollen: Damit das Netzwerk nicht zum Stillstand kommt, muss weniger als ein Drittel der Nodes unehrlich sein. Um die Validierung falscher Transaktionen zu verhindern, müssen weniger als zwei Drittel unehrlich sein. Das Stake-basierte System sanktioniert Handlungen, die die Effizienz des Netzwerks stören oder beeinträchtigen könnten.

In einem solchen BFT-Netzwerk gibt es zwei kritische Schwellenwerte:

  1. 1/3: Machen unehrliche Nodes mindestens ein Drittel der Gesamtmenge aus, kann das Netzwerk „anhalten“. In diesem Szenario könnten diese Nodes die Teilnahme einfach verweigern. Der Rest könnte dann nicht die für den Konsens erforderliche Zweidrittel-Supermehrheit erreichen. Das Netzwerk erzeugt folglich keine falschen Transaktionen, sondern überhaupt keine Transaktionen mehr. Eine verbreitete, wenn auch grobe Metrik ist der Nakamoto-Koeffizient. Er gibt die Mindestanzahl an Nodes an, die erforderlich ist, um die Lebendigkeit zu beeinträchtigen und die Blockproduktion anzuhalten.
  2. 2/3: Stellen unehrliche Nodes mindestens zwei Drittel der Gesamtmenge, können sie sich absprechen und beliebige Transaktionen validieren. Das ist der schlimmste Fall: Das Netzwerk funktioniert nicht mehr korrekt und verarbeitet stattdessen Transaktionen nach den Vorgaben der unehrlichen Supermehrheit. Kontrolliert eine gegnerische Partei mehr als 67 % des Stakes, könnte sie eine ehrliche Node isolieren, etwa die Node einer großen Börse wie Binance. Dazu könnte sie sich mit einem Rechenzentrum absprechen und den Netzwerkverkehr der Node einschränken. Die böswillige Partei könnte diese isolierte Node dann einen von ihr erstellten Block finalisieren lassen und gleichzeitig einen widersprüchlichen Block an den Rest des Netzwerks verteilen. Ein solcher Angriff nutzt die eingeschränkte Sicht der isolierten Node aus. Dadurch können Double-Spending-Angriffe entstehen, weil der Rest des Netzwerks und die isolierte Node unterschiedliche Ansichten des On-Chain-Zustands haben.

Ein ähnlicher Angriff ist auch mit einem geringeren Stake von mehr als 33 % möglich. Dafür wäre jedoch eine Netzwerkpartition statt einer bloßen Isolation erforderlich. In diesem Fall kann der byzantinische Stakeholder die Netzwerkpartition ausnutzen, um verschiedene Teile des Netzwerks mit widersprüchlichen Informationen zu manipulieren. Auch hier drohen Double Spending und andere Safety-Verletzungen.

Eine größere Zahl von Nodes erschwert es in der Regel jeder Partei, einen erheblichen Anteil zu korrumpieren und diese Schwellenwerte zu erreichen – geografische Trennung vorausgesetzt. Der Wunsch nach einem größeren Netzwerk steht jedoch oft im Konflikt mit der Effizienz. Mehr Nodes können den Konsens wegen des höheren Datenübertragungsaufwands verlangsamen, da die Verbreitung von Abstimmungen mehr Zeit beansprucht. Einige Protokolle begrenzen deshalb die maximale Zahl der Nodes.

Proof-of-History (PoH)

Während Proof-of-Stake (PoS) den Konsens in einem Netzwerk gewährleistet, integriert Solana Proof-of-History (PoH) in seinen PoS-Konsensmechanismus. Das ermöglicht die Synchronisierung für eine kontinuierliche Blockproduktion. Solana überspringt dabei Slots mit langsamen oder nicht reagierenden Slot-Leadern, ohne auf eine synchronisierte Konsensrunde zu warten. PoH weist nicht den exakten Zeitpunkt eines Ereignisses nach, sondern die Reihenfolge und die zwischen Ereignissen verstrichene Zeit.

Entgegen einer verbreiteten Annahme ist Proof-of-History (PoH) selbst kein Konsensmechanismus oder -algorithmus. Obwohl die aktuelle Implementierung des Konsenses Aspekte von PoH nutzt, könnte man PoH theoretisch entfernen und einige kleinere Änderungen an der Implementierung vornehmen, ohne den Konsensbetrieb von Solana zu verhindern.

Im Kern ist PoH ein einfacher Hashing-Algorithmus, der einer Verifiable Delay Function (VDF) ähnelt, aber technisch keine VDF ist. Solana implementiert ihn mit einer sequenziellen, urbildresistenten Hash-Funktion (SHA-256), die kontinuierlich läuft und die Ausgabe einer Iteration als Eingabe für die nächste verwendet. Diese Berechnung läuft auf einem einzelnen Kern jedes Validators.

Die Sequenz wird zwar sequenziell und in einem einzelnen Thread erzeugt, ihre Ausgabe kann jedoch parallel verifiziert werden. Das ermöglicht eine effiziente Prüfung auf Mehrkernsystemen. Für die Hashing-Geschwindigkeit gibt es zwar eine Obergrenze, doch bessere Hardware kann zusätzliche Leistungsvorteile bieten.

Betrachten wir ein Beispiel mit vier Validatoren im Solana-Netzwerk: Validator A, B, C und D. In diesem Beispiel könnte der Leader-Zeitplan die Reihenfolge A - B - C - D für die Blockproduktion vorgeben. Validator A beginnt damit, einen Block zu erzeugen. Dafür nutzt Validator A den PoH-Mechanismus. Dabei wird die SHA-256-Hash-Funktion iterativ ausgeführt und bildet eine Zeitskala aus „Ticks“. Dieser Hashing-Prozess erzeugt einen eindeutigen und überprüfbaren Nachweis der verstrichenen Zeit. So bildet der Block von Validator A den korrekten Zeitverlauf ab. Sobald Validator A seinen Block abgeschlossen hat, erzeugt Validator B den nächsten Block, gefolgt von Validator C.

Angenommen, Validator C versucht, die Reihenfolge zu stören, indem er außerhalb seines Slots einen Block ausgibt. Er will direkt auf Validator A folgen und Validator B umgehen. Um überzeugend den Platz von Validator B einzunehmen, müsste Validator C die PoH-Hash-Sequenz reproduzieren, die Validator B erzeugt hätte. Er müsste also eine Hash-Sequenz generieren, die der Zeit entspricht, die Validator B für die Blockproduktion benötigt hätte. Die Hashing-Leistung eines einzelnen Kerns hat eine physische Obergrenze. Deshalb wissen wir, dass eine bestimmte Zeit verstrichen ist, da ein Computer in einem gegebenen Zeitintervall nur eine begrenzte Zahl von Hashes erzeugen kann.

Validator C kann versuchen, Validator B im Leader-Zeitplan zu zensieren. Dazu erzeugt er, ausgehend vom Ende eines vorherigen legitimen Blocks – dem Block von Validator A –, eine Chain leerer Blöcke ohne Transaktionen. Um B erfolgreich zu zensieren, muss C zwei Bedingungen erfüllen. Erstens benötigt C genügend Rechenleistung, um die leere PoH-Chain zu berechnen. Zweitens muss C seinen Block schnell genug an eine ausreichende Zahl von Nodes mit Stake verteilen, damit sie ihn während seines eigenen vorgesehenen Slots akzeptieren und B dadurch effektiv zensiert wird. Dank Turbine gelingt dies einem Validator mit hohem Stake-Gewicht schneller, da Turbine den Informationsfluss nach dem Stake-Gewicht der Validatoren priorisiert.

Dieses Angriffsszenario ist möglich, doch das Zeitfenster für eine erfolgreiche Zensur ist begrenzt. Die angreifende Node benötigt erhebliche Rechenressourcen für das SHA-256-Hashing und einen beträchtlichen Stake, da die Zahl der erzeugbaren Blöcke proportional zu ihrem Stake ist.

C muss das Netzwerk nicht nur schneller als Node A erreichen, sondern auch den Hash mit hoher Geschwindigkeit erzeugen. Dieser Angriff zielt vor allem auf ein Szenario, in dem ein Validator mit einem zugewiesenen Leader-Slot n die Validatoren früherer Leader-Slots – also vor n – zensieren will. Wie umfassend dieser Validator zensieren kann, hängt von seinem Stake ab, da seine Fähigkeit, Leader-Slots zu erhalten, direkt an die Höhe seines Stakes gekoppelt ist.

Der PoH-Mechanismus sorgt außerdem dafür, dass Blöcke mit gleichbleibender Rate erzeugt werden. Da jeder Validator die PoH-Sequenz unabhängig verifizieren kann, ist keine externe Zeitsynchronisierung erforderlich. Ethereum verwendet beispielsweise das Network Time Protocol (NTP) in jedem Block für den Konsens. Auf Solana prüft jeder Validator ohne externes Protokoll eigenständig und systemintern, ob jeder Block im richtigen Zeit-Slot erzeugt wurde.

Tower BFT (der Konsensmechanismus von Solana)

Tower BFT, der Konsensmechanismus von Solana, kommt zum Einsatz, nachdem Shreds – partielle Blöcke – an andere Validatoren verteilt wurden:

Wie bereits erwähnt, führt Solana Tower BFT zusammen mit Proof-of-History aus. Tower BFT ist ein pBFT-ähnlicher Konsensalgorithmus, der die synchronisierten Taktberechnungen von Proof-of-History nutzt. So entsteht im gesamten Netzwerk eine universelle Uhr. Dadurch kann das Netzwerk Slots effizient überspringen, die langsamen oder nicht reagierenden Leadern zugewiesen sind. Das Netzwerk muss nicht für jeden Slot eine synchrone Konsensrunde durchlaufen. Dies ermöglicht eine kontinuierliche Blockproduktion, da Validatoren nicht auf vorherige Blöcke warten müssen, bevor sie den nächsten Block erstellen.

Ein weiteres Missverständnis ist, dass der Konsensmechanismus von Solana bereits programmatisches Slashing implementiert. Obwohl Slashing auf der Roadmap steht, hält das Netzwerk derzeit nach einer Safety-Verletzung an und setzt bei Bedarf für das Slashing auf sozialen Konsens.

Der Konsensmechanismus von Solana gibt verschiedenen Nodes unterschiedlich viel Einfluss. Abstimmungen im Netzwerk sind nicht gleichwertig, sondern werden nach dem Stake jeder Node gewichtet. Dabei gelten dieselben Prinzipien wie bei Stake-gewichteter QoS und Turbine. Unter sonst gleichen Bedingungen hat eine Node mit größerem Stake mehr Einfluss auf die Bestimmung des kanonischen Konsenses als eine Node mit kleinerem Stake.

In einem Netzwerk mit vier Nodes, die zusammen 100 Stake-Einheiten halten, könnten Verteilung und Einfluss beispielsweise so aussehen:

  • Node A hat 10 Stake-Einheiten.
  • Node B hat 20 Stake-Einheiten.
  • Node C hat 30 Stake-Einheiten.
  • Node D hat 40 Stake-Einheiten.

In dieser Konstellation haben verschiedene Gruppen unehrlicher Nodes unterschiedliche Möglichkeiten. Eine einzelne Node wie Node D könnte das Netzwerk trotz eines Anteils von nur 25 % an allen Nodes wegen ihres großen Stakes anhalten. Ebenso könnten Nodes C und D gemeinsam falsche Transaktionen genehmigen. Sie stellen zwar nur 50 % der Nodes, halten aber genügend Stake, um das Ergebnis zu beeinflussen.

Der Schwellenwert von einem Drittel zum Anhalten des Netzwerks kann durch unehrliche, kompromittierte oder blockierte Nodes erreicht werden. Der Zweidrittel-Schwellenwert für die Validierung falscher Transaktionen erfordert dagegen eine aktive Absprache und lässt sich nicht allein durch das Blockieren ehrlicher Nodes erreichen. Deshalb ist das deutlich schwieriger. Nodes müssen korrumpiert oder kompromittiert werden, damit sie aktiv am unehrlichen Vorgehen teilnehmen. Es reicht nicht, ehrliche Nodes zu blockieren.

Kontext innerhalb von Slots

Auf Solana werden Slot-Leadern vier aufeinanderfolgende Slots zugewiesen, die insgesamt etwa 1,6 Sekunden dauern (4 Blöcke x 400 ms pro Block). Die Leader werden zu Beginn jeder Epoche ausgewählt (432.000 Slots oder ~2–3 Tage). Der Leader-Zeitplan wird zufällig und relativ zum Stake-Gewicht eines Validators bestimmt.

Der Leader muss für jeden ihm zugewiesenen Slot einen neuen Block erstellen und vorschlagen. Eine Trennung zwischen Proposer und Builder wie bei Ethereum gibt es nicht. Andere Validatoren bestätigen die Gültigkeit eines Blocks über Abstimmungstransaktionen. Dazu wenden sie die Fork-Choice-Regel auf ihre lokale Sicht der Spitze des Solana-Netzwerks an.

Leader müssen Blöcke innerhalb eines bestimmten PoH-Tick-Bereichs veröffentlichen, damit der Block gültig ist. Ein außerhalb dieses Bereichs veröffentlichter Block gilt als übersprungen.

Betrachten wir das folgende Beispiel eines Leader-Zeitplans mit vier Teilnehmern (A, B, C, D), in dem D versucht, die Reihenfolge zu stören. Will D während des Slots von C eingreifen, muss D eine Sequenz von PoH-Ticks erzeugen, die den Block von C effektiv überspringt. Daraus entsteht eine Chain wie diese:

A - B - [C fehlt] - D.

Fehlt der Block von C, müsste ein ehrlicher D eine PoH-Sequenz erzeugen, die die gesamte Dauer des Slots von C abdeckt, bevor sein eigener Slot beginnt. Dadurch würde der Block von D gültig erscheinen, weil er nach Ablauf der für den Slot von C vorgesehenen Zeit auf den Block von B folgt.

Während D die PoH-Sequenz für den Slot von C erzeugt, würde C normalerweise seinen Block streamen, der durch eine passende PoH-Sequenz mit dem Block von B verbunden ist. Daraus ergeben sich zwei mögliche Ergebnisse:

  • Wenn D PoH nicht schneller berechnet als C: C schließt seinen Block ungefähr zu dem Zeitpunkt ab, an dem D mit der Übertragung seines eigenen Blocks beginnt. Da das Netzwerk den Block von C bereits gesehen hat, lehnt es den Block von D ab.
  • Wenn D PoH schneller berechnet als C: D beginnt mit der Übertragung seines Blocks, bevor C seinen eigenen abgeschlossen hat. Trotzdem müsste D erheblich schneller als C sein, um die Reihenfolge wesentlich zu beeinflussen. Das ist angesichts der hohen Geschwindigkeit und der relativ ähnlichen Leistungsobergrenzen der von Validatoren für SHA-256-Berechnungen verwendeten CPUs unwahrscheinlich.

In beiden Fällen hat D kaum eine Chance, C erfolgreich zu ersetzen. Scheitert der Versuch, C zu ersetzen, verliert D außerdem die Möglichkeit, in seinem eigenen Slot einen Block auszugeben. Direkt nach B einen Block auszugeben und es nach C erneut zu versuchen, wäre ein Verstoß, da D zwei Blöcke für seinen Slot erzeugen würde. Dieser Verstoß könnte mit Slashing bestraft werden. Bei jedem gescheiterten Versuch verliert D seine eigene Chance zur Blockproduktion. Daher ist es unwahrscheinlich, dass D diese Strategie verfolgt. 

Aus Sicht des Netzwerks lassen sich die Absichten von D nicht bestimmen. Es ist schwierig oder sogar unmöglich zu unterscheiden, ob D den Block von C einfach nicht gesehen hat und C nicht zensieren wollte oder ob D beabsichtigte, B zu zensieren. Daher lässt sich dieses Verhalten nicht leicht erkennen und vom Netzwerk nicht bestrafen.

Abstimmungstransaktionen

Der Konsensmechanismus von Solana basiert auf Abstimmungstransaktionen. Sie befinden sich innerhalb eines Blocks, werden aber priorisiert, damit reguläre Transaktionen sie nicht verdrängen. Derzeit sind die meisten Transaktionen in einem Block Abstimmungstransaktionen:

Das muss jedoch nicht immer so bleiben. Der Anteil der Abstimmungstransaktionen in einem Block bildet das Verhältnis zwischen der Aktivität und der Zahl der am Konsens beteiligten Validatoren ab. Künftig könnten Abstimmungstransaktionen nur noch eine Minderheit in einem Block ausmachen.

Abstimmungstransaktionen sind für den Konsens erforderlich – sie sind keine überflüssigen Transaktionen, die TPS-Metriken künstlich aufblähen. Würden Abstimmungen nur per Gossip verbreitet (informelle Peer-to-Peer-Kommunikation), könnten Validatoren den Zustand des Towers und seiner Abstimmungen unterschiedlich wahrnehmen. Solche Abweichungen könnten dazu führen, dass Validatoren unterschiedliche Einschätzungen dazu haben, welcher Fork wahrscheinlich der richtige ist. Das kann wiederum Abspaltungen verursachen, wenn Validatoren auf Grundlage unvollständiger oder inkonsistenter Informationen eigennützige Entscheidungen treffen. Kontinuierliche Blockproduktion erfordert fortlaufende Abstimmungen, insbesondere solange vorherige Blöcke noch bestätigt werden. Dafür ist eine zuverlässige und konsistente Sicht auf den Zustand des Towers nötig.

Wie reguläre, von Nutzern initiierte Transaktionen müssen auch Abstimmungstransaktionen die Grundgebühr von 0,000005 SOL zahlen. Sie wird von der Validator-Identität bezahlt, die sich für das ständige Signieren in einer Hot Wallet befinden muss. Das Abstimmungskonto dient dagegen der Kontosuche und Delegation.

Jede vom Validator signierte Abstimmung enthält den öffentlichen Schlüssel des Validators und den Hash des Blocks, für den er abstimmt.

Empfängt ein Validator mehrere Blöcke für denselben Slot, verfolgt er alle möglichen Forks, bis er den „besten“ bestimmen kann. Validatoren führen die relevante Zustandsübergangsfunktion lokal aus – das ändert sich mit der asynchronen Ausführung – und stimmen nach dem Replay über neue Blöcke ab. Ihre Stimme für einen bestimmten Fork geben sie über On-Chain-Abstimmungstransaktionen ab.

In jeder Abstimmungstransaktion veröffentlicht ein Validator Stimmen mit einer Lockout-Periode. Dieser Lockout fungiert als Bindungsmechanismus. Er bindet Validatoren an den gewählten Fork und verursacht Opportunitätskosten für ihre Entscheidungen. Heute erzwingt die Runtime Lockouts nicht. Stattdessen geschieht dies über sozialen Konsens: Wer Abstimmungs-Lockouts wiederholt verletzt, wird sehr wahrscheinlich manuell mit Slashing bestraft. Programmatisches Slashing für Verstöße gegen Lockout-Perioden dürfte in naher Zukunft hinzukommen, da der Verlust von Abstimmungsgutschriften keinen ausreichend starken Fehlanreiz darstellt.

Der Validator signiert außerdem für jeden Vorgängerblock zwischen seiner vorherigen Abstimmung und verwurzelten beziehungsweise finalisierten Blöcken einen Hash des Blocks. Das ist nötig, um doppelte Blöcke zu erkennen. Würde ein Leader an jede Node unterschiedliche Blöcke senden, würde jede Node für denselben Slot über einen anderen Vorgänger abstimmen. In einer Epoche mit 65.000 Slots könnte jede Abstimmung im extremsten Fall jedoch bis zu 2 MB groß werden. Für jeden der 65.000 Slots könnten Hashes mit jeweils 32 Byte erforderlich sein. Ein künftiger Beitrag wird dieses Thema ausführlicher behandeln.

Die Validatoren verwalten einen „Vote Tower“, einen sequenziellen Stapel von Abstimmungen. Jede Abstimmung stärkt einen Fork und ist ein Vorgänger des darüberliegenden Forks im Tower. Wird dem Tower eine neue Abstimmung hinzugefügt, verdoppeln sich die Lockouts aller vorherigen Abstimmungen im Stapel. Dadurch steigen Bindung und Lockout-Periode früherer Entscheidungen schrittweise. Der Abstimmungsprozess selbst unterliegt mehreren Prüfungen: Validatoren müssen die Lockout-Perioden vorheriger Abstimmungen beachten. Sie müssen sicherstellen, dass sich auch ein erheblicher Teil des Netzwerks – üblicherweise zwei Drittel – auf denselben Fork festgelegt hat. Vor dem Wechsel zu einem neuen Fork ist außerdem eine deutliche Mehrheit von über 38 % der Abstimmungen auf alternativen Forks erforderlich.

Für einen Block in Slot n erscheinen Abstimmungen von anderen Teilnehmern als dem Leader frühestens in n+1 On-Chain. Es gibt keine Abstimmungs-Unterkomitees – alle Validatoren dürfen über alle Blöcke abstimmen. Diese Stimmen erscheinen zuerst in den Blöcken anderer Validatoren, die im Turbine-Baum nahe liegen, also einen Hop entfernt sind. Abstimmungen für Slot n können bis Slot n+512 erscheinen. Ein Validator darf über jeden Slot abstimmen, dessen „Slot-Hash“ noch bekannt ist, und Slot-Hashes werden für 512 Slots aufbewahrt (danke an Shinobi). Für Slot n gibt es bei keinem bestimmten Block eine vorab festgelegte Obergrenze. Verwurzelte Slots, auf denen mindestens 32 kontinuierliche Blöcke aufbauen, nehmen jedoch keine Abstimmungen mehr an und werden finalisiert.

Das Abstimmungssystem hat einige Eigenheiten, die von der Runtime nicht vollständig durchgesetzt werden. Validatoren haben derzeit beispielsweise einen Anreiz, nur für „verwurzelte“ Slots abzustimmen und die Spitze der Chain zu ignorieren. Der Konsens bestraft das nicht. So kann ein Validator fortlaufend Abstimmungsgutschriften für Forks verdienen, die mit extrem hoher Wahrscheinlichkeit kanonisch werden, ohne an den tatsächlichen Konsensvorgängen an der Spitze der Chain mitzuwirken. Das geschieht bereits heute: Ein Validator hat eine durchschnittliche „Abstimmungslatenz“ von mehr als 68 Slots. Eine vorgeschlagene Funktion namens Timely Vote Credits soll diese falschen Anreize reduzieren.

Fork-Choice-Regel von Solana

Wie Ethereum (LMD Ghost und Casper FFG) hat Solana zwei Bestätigungsregeln: eine für die kurzfristige Fork-Auswahl und eine für den vollständigen PoS-Konsens zur Finalität. Dadurch können Nutzer und Clients ihre UX-Auswahl an unterschiedliche Bestätigungsregeln anpassen. Das spiegeln die beiden Verbindlichkeitsstufen „bestätigt“ und „finalisiert“ wider.

„Bestätigte“ Blöcke, auch als optimistische Bestätigung bezeichnet, erfordern, dass mindestens zwei Drittel der Validatoren über Abstimmungstransaktionen für einen bestimmten Block gestimmt haben. Damit Verletzungen der Finalität möglich werden, müssten ~4,6 % des aktuellen Stakes mit Slashing bestraft werden. „Finalisierte“ Blöcke erfordern Abstimmungen über mindestens 32 nachfolgende Slots oder eine Supermehrheit (>2/3) der Stimmen. Ein böswilliger Angriff würde erfordern, dass mehr als ein Drittel des Stakes mit Slashing bestraft wird. Das dauert deutlich länger als bei „bestätigten“ Blöcken, da für vollständige Finalität auf die Verwurzelung der 32 vorherigen Blöcke gewartet werden muss.

Mit einer Fork-Choice-Regel kann das Netzwerk einen Konsens über die Spitze der Chain erreichen. Die Implementierung von Solana Labs handhabt die Fork-Auswahl hauptsächlich über eine ~4600 Zeilen lange Rust-Datei mit dem passenden Namen heaviest_subtree_fork_choice.rs. Sie enthält die nötige Logik, mit der Validatoren bestimmen, welcher Fork am wahrscheinlichsten kanonisch wird. Eine detailliertere Aufschlüsselung des Codes folgt in einem künftigen Beitrag. Auf sehr hoher Ebene funktioniert die Fork-Auswahl so:

  1. Abstimmungen werden mit add_votes() hinzugefügt:

Dabei werden die neuen Abstimmungen durchlaufen, bei Bedarf Stakes von Abstimmungskonten aus alten Slots abgezogen und den neu gewählten Slots hinzugefügt.

  1. generate_update_operations() wird aufgerufen, um einen Stapel von Fork-Aktualisierungsoperationen zu erstellen:

Das bewirkt Folgendes:

  • Stake vom alten Fork abziehen
  • Stake dem neuen Fork hinzufügen
  • Stake jedes Forks bis zur Wurzel aggregieren
  1. process_update_operations():
  • Ruft bei Bedarf mark_fork_valid()/invalid() auf
  • Ruft für jeden Fork aggregate_slot() auf, um die Fork-Gewichte zu aktualisieren
  • Ruft add_slot_stake()/subtract_slot_stake() auf, um Stakes zu aktualisieren
  1. aggregate_slot():
  • Summiert den Stake aller untergeordneten Slots
  • Ermittelt anhand des Stake-Gewichts den schwersten untergeordneten Fork
  • Ermittelt anhand der Höhe den tiefsten untergeordneten Fork
  • Überträgt diese Werte nach oben, um den schwersten und tiefsten Fork ab diesem Slot zu ermitteln
  1. select_forks():
  • Gibt den insgesamt schwersten Fork für die Blockproduktion zurück
  • Gibt den schwersten Fork zurück, der von der letzten Abstimmung abstammt

Stake wird entsprechend den Abstimmungen hinzugefügt oder abgezogen. Die Aggregation berechnet die Gewichte für jeden Fork von unten nach oben neu. Die Wurzel mit dem am stärksten gewichteten Teilbaum wird als bester Fork für weitere Blöcke und Abstimmungen ausgewählt.

Wahrscheinlichkeit der Aufnahme

Die Wahrscheinlichkeit, dass eine Transaktion aufgenommen wird, ändert sich im Verlauf ihres Lebenszyklus, nachdem sie die jeweiligen Anforderungen der entsprechenden Bestätigungsregeln erfüllt hat.

Slots können „übersprungen“ werden, etwa wenn der Leader offline ist. Die betreffende Transaktion kann dann entweder in künftigen Blöcken landen oder überhaupt nicht aufgenommen werden.

Die hier angegebenen Slots sind grobe Näherungswerte. Sie sollen veranschaulichen, wann sich üblicherweise Abstimmungen ansammeln. Das ist außerdem für jeden Block unterschiedlich: Blöcke können die Bestätigungsstufe „bestätigt“ oder „finalisiert“ nach unterschiedlich langer Zeit erreichen. Das Risiko einer Rücknahme sinkt im gesamten Lebenszyklus der Transaktion monoton. Selbst ein finalisierter, also verwurzelter, Block könnte theoretisch durch sozialen Konsens abgespalten und aus der „kanonischen“ Chain entfernt werden.

Künftige Forschungsbereiche und Fazit

Dieser Beitrag hat die internen Abläufe von Tower BFT, dem Konsensmechanismus von Solana, sowie weitere relevante Mechanismen beleuchtet. Wir haben die Rolle von Proof-of-History, Abstimmungstransaktionen und der Fork-Auswahl im Kontext von Solana untersucht, die gemeinsam einen kanonischen Fork für die Reihenfolge von Transaktionen erzeugen.

Diese Mechanismen bieten zahlreiche weitere Ansätze für Forschung und Formalisierung, darunter:

  • Ethereum-Forscher haben den Wert von Timing Games quantifiziert, bei denen Blockproduzenten bis zum Ende des Slots warten, bevor sie ihre Blöcke einreichen. Wie sehen diese Spiele auf Solana quantitativ aus, und finden sie bereits heute statt?
  • Die asynchrone Ausführung steht als wichtigste Protokolländerung für 2024 auf der Roadmap. Welche potenziellen Angriffsvektoren und relevanten Sicherheitsaspekte gibt es für Nodes, die lediglich über vorhandene Forks abstimmen, statt die Zustandsübergänge lokal zu berechnen?
  • Heute führt eine bedeutende Minderheit der Validatoren (<20 %) modifizierte Versionen des Clients von Solana Labs oder Jito-Solana aus. Welche Schwellenwerte ändern sie, die weder von der Runtime noch von Bestätigungsregeln gesteuert werden?
  • Programmatisches Slashing implementieren. Derzeit gibt es außerhalb des sozialen Konsenses kaum wirtschaftliche Anreize, hochprofitable Handelsstrategien nicht ohne Slashing-Risiko auszuführen.
  • Wie verhält sich die Leistung des Konsensmechanismus von Solana, wenn zwei völlig unterschiedliche Clients ausgeführt werden, selbst wenn beide durch dieselben Bestätigungsregeln definiert sein sollen?
  • Welche Vorteile für Leistung und Zustandsreduzierung sind von Abstimmungs-Unterkomitees zu erwarten?
  • Welche potenziellen Angriffsvektoren entstehen, wenn ein Neustart von einem optimistisch bestätigten statt von einem finalisierten Slot erfolgt? Wie sollten externe Off-Chain-Lösungen wie Börsen mit optimistischer Bestätigung oder vollständiger Finalität umgehen?
  • Sollten durch Slashing eingezogene Mittel als Versicherung für Transaktionen dienen, die von Safety-Verletzungen betroffen sind? Wie könnten Mechanik und Anreize eines auf SOL lautenden Versicherungspools aussehen?

In diesem Beitrag haben wir einige der Mechanismen und Schwellenwerte untersucht, die Solana in seinem Konsensmechanismus implementiert, und ihren Zusammenhang mit der typischen Blockproduktion durch Leader innerhalb bestimmter Slots betrachtet. Die jüngste Aktivitätszunahme auf Solana unterzieht diese Mechanismen realen Lebendigkeits- und Safety-Tests. Gleichzeitig steigen die Anreize für böswillige Angriffe.

Vielen Dank an anoushk (Tinydancer), dubbel06 (Overclock), Prithvi (Helius), Mert (Helius) und Jarry (Ellipsis Labs) für die Diskussionen und Kommentare.

Helius abonnieren

Bleib bei der Solana-Entwicklung auf dem Laufenden und erhalte Updates, wenn wir neue Beiträge veröffentlichen

Vergrößertes Bild