Skip to main content
Festgeschriebener Zustand muss zwei Anforderungen genügen, die gegeneinander ziehen. Die Ausführung will den aktuellen Wert eines Schlüssels, schnell, millionenfach. Die Verifikation will einen Beweis dafür, dass ein Wert bei einer bestimmten Version das war, was das Netzwerk sagt. Beides aus einer Struktur zu bedienen heißt, beides schlecht zu tun. Die Speicherung teilt das Problem deshalb auf getrennte Stores auf, jeder auf sein eigenes Zugriffsmuster zugeschnitten.

Drei Stores

Festgeschriebener Block
Ledger-StoreTransaktionen · Ausgaben · Ereignisse · Write Sets · Akkumulatoren · Blockmetadaten
Replay und Audit
State-KV-Storeaktuelle und historische Werte, 16 Shards, heißer Zustand in eigener Stufe
Abfragen und Ausführung
State-Merkle-Storeein versionierter Sparse Merkle Tree, dazu die Indizes über überholte Knoten
Verifikation – Beweise
Ein Lesezugriff, der nur einen Wert braucht, zahlt nicht für die Baumtraversierung, und ein Beweis wird nicht aus einem Store rekonstruiert, der für Punktabfragen optimiert ist.
Der Ledger-Store hält die Historie der Chain: Transaktionen, ihre Ausgaben und Zusatzdaten, Ereignisse, Write Sets, Blockmetadaten und die Akkumulatoren. Das ist der Teil, den ein Replay durchläuft. Der State-KV-Store hält Zustandswerte, adressiert über Schlüssel und Version. Aus ihm lesen Ausführung und Abfragen. Er ist sechzehnfach geshardet, sodass sich die Schreibvorgänge eines Blocks auf sechzehn unabhängige RocksDB-Instanzen verteilen, statt sich in einer einzigen zu stauen. Häufig genutzter Zustand liegt zusätzlich in einer eigenen Stufe, damit das Working Set eines aktiven Marktes nicht unter allem gesucht werden muss, was die Chain je gespeichert hat. Der State-Merkle-Store hält die authentifizierte Struktur – die Baumknoten, mit denen sich ein Wert beweisen lässt, und die Indizes, die festhalten, welche Knoten überholt sind. Die Trennung bewirkt, dass ein Lesezugriff, der nur einen Wert braucht, nicht für die Baumtraversierung zahlt, und dass ein Beweis nicht aus einem Store rekonstruiert werden muss, der für Punktabfragen optimiert ist.

Authentifizierung

Zwei Merkle-Strukturen erledigen verschiedene Aufgaben.
Versionierter Sparse Merkle Tree
Akkumulatoren
Ihr Schlüssel und sein Wert
Geschwister-Hash
Geschwister-Hash
State-Root, konsensbestätigt
Ihre Transaktion oder ein Ereignis
Transaktionsakkumulator · Ereignisakkumulatorlegt sich auf alles bisher Aufgenommene fest, geordnet
Ledger-Root, konsensbestätigt
Der Baum beweist, was ein Wert war; die Akkumulatoren beweisen, was passiert ist und in welcher Reihenfolge. Zusammen machen sie „diese Transaktion steht an dieser Stelle in der Chain“ beweisbar, ohne die Chain zu halten.
Ein versionierter Sparse Merkle Tree authentifiziert den Zustand. Jeder Schlüssel hat eine Position, die sein Hash bestimmt, und jede Version des Baums teilt sich die Knoten, die sich nicht geändert haben – das Schreiben eines Schlüssels in einem Block fügt also einen Pfad hinzu, keinen Baum. Ein Beweis für einen Schlüssel bei einer Version ist der Pfad von dessen Blatt bis zu der Wurzel, die das Netzwerk festgeschrieben hat. Akkumulatoren authentifizieren die Reihenfolge. Einer akkumuliert Transaktionen, einer Ereignisse; jeder erzeugt eine Wurzel, die sich auf alles bisher Aufgenommene in genau dieser Reihenfolge festlegt. Das macht „diese Transaktion steht an dieser Stelle in der Chain“ beweisbar, ohne die Chain zu halten. Zusammen: Der Zustandsbaum beweist, was ein Wert war, die Akkumulatoren beweisen, was passiert ist und in welcher Reihenfolge.

Spekulativer Zustand

Die Ergebnisse eines Blocks existieren, bevor sie festgeschrieben werden. Statt sie in den dauerhaften Baum zu schreiben und das rückgängig zu machen, falls der Block nicht festgeschrieben wird, liegt nicht festgeschriebener Zustand in einem Sparse-Merkle-Overlay im Arbeitsspeicher über der zuletzt festgeschriebenen Version. Die Ausführung liest durch das Overlay hindurch und sieht eine konsistente Sicht. Wird der Block festgeschrieben, wird das Overlay materialisiert. Wird er es nicht, wird das Overlay verworfen, und nichts Dauerhaftes wurde je angefasst. Genau das verhindert, dass spekulative Ausführung Müll in der Speicherung hinterlässt.

Caching

Baumknoten werden auf zwei Ebenen zwischengespeichert: ein versionsbewusster Cache, der jüngere Versionen adressierbar hält, und darunter ein Least-Recently-Used-Cache. Das Zugriffsmuster einer Trading-Chain – eine kleine Menge heißer Schlüssel, die jeder Block berührt, gegen einen langen Schwanz, der selten berührt wird – ist genau die Form, für die sie gemacht sind.

Pruning

Dass jede Version für immer erhalten bleibt, ist eine Entscheidung, keine Vorgabe. Drei unabhängige Pruner laufen gegen die drei Stores, jeder mit eigener Aufbewahrungsrichtlinie: einer über das Ledger, einer über die Zustandswerte, einer über die Merkle-Knoten. Der Merkle-Pruner und der Zustandswert-Pruner werden von Stale-Indizes gesteuert, die gleichzeitig mit den Daten geschrieben werden. Überholt eine Version einen Knoten oder einen Wert, wird der überholte Eintrag bei dieser Version als stale vermerkt. Pruning ist damit ein Bereichsscan über einen Index statt einer Suche nach Müll – der Schreiber hat bereits gesagt, was wann gelöscht werden kann.
Die Aufbewahrung ist eine Betreiberentscheidung mit realen Folgen. Eine Node mit aggressivem Pruning bedient den aktuellen Zustand effizient und kann weder historische Abfragen beantworten noch einer Node, die weiter hinten startet, die Zustandssynchronisation liefern. Eine Archiv-Node behält alles und zahlt dafür. Siehe Node betreiben.

Backup und Wiederherstellung

Die Stores lassen sich unabhängig von der laufenden Node sichern und wiederherstellen. Das macht es möglich, eine Node aus einem Snapshot aufzusetzen, statt sie von Genesis an neu auszuführen, und den Zustand einer wiederhergestellten Node anhand der festgeschriebenen Wurzeln zu prüfen, statt dem Backup zu vertrauen.

Wie es weitergeht

Zustandssynchronisation

Wie eine Node zur Chain aufschließt, ohne sie ganz erneut auszuführen.

Zustandsmodell

Was gespeichert wird und welche Darstellung maßgeblich ist.

Indexer

Historie aus festgeschriebenen Datensätzen rekonstruieren.

Node betreiben

Node-Rollen und wie man sich für den Betrieb einer Node meldet.