Skip to main content
Lo stato consolidato deve soddisfare due esigenze che tirano in direzioni opposte. All’esecuzione serve il valore corrente di una chiave, veloce, milioni di volte. Alla verifica serve la prova che, a una certa versione, un valore fosse quello che la rete dice. Servirle entrambe da un’unica struttura significa farle entrambe male. L’archiviazione perciò divide il problema su store separati, ciascuno modellato sul proprio schema di accesso.

Tre store

Blocco consolidato
Ledger storetransazioni · output · eventi · write set · accumulatori · metadati del blocco
Replay e audit
State KV storevalori correnti e storici, 16 shard, stato caldo in un livello proprio
Query ed esecuzione
State Merkle storealbero di Merkle sparso versionato, più gli indici dei nodi soppiantati
Verifica — prove
Chi legge solo un valore non paga la traversata dell’albero, e una prova non va ricostruita da uno store ottimizzato per letture puntuali.
Il ledger store contiene lo storico della catena: transazioni, i loro output e dati ausiliari, eventi, write set, metadati dei blocchi e gli accumulatori. È questo che si riesegue. Lo state KV store contiene i valori di stato, indirizzati per chiave e versione. È questo che leggono l’esecuzione e le query. È suddiviso in sedici shard, così le scritture di un blocco si distribuiscono su sedici istanze RocksDB indipendenti invece di contendersene una sola. Lo stato a cui si accede di frequente è tenuto anche in un livello proprio, così il working set di un mercato attivo non va cercato in mezzo a tutto ciò che la catena ha mai archiviato. Lo state Merkle store contiene la struttura autenticata: i nodi dell’albero che permettono di provare un valore, e gli indici che tengono traccia di quali nodi sono stati soppiantati. Separarli significa che una lettura a cui serve solo un valore non paga la traversata dell’albero, e che una prova non va ricostruita da uno store ottimizzato per le letture puntuali.

Autenticazione

Due strutture di Merkle fanno lavori diversi.
Albero di Merkle sparso versionato
Accumulatori
La tua chiave e il suo valore
hash fratello
hash fratello
Radice dello stato consolidata dal consenso
La tua transazione, o un evento
Accumulatore transazioni · accumulatore eventiciascuno vincola tutto quanto incluso finora, nell’ordine
Radice del ledger consolidata dal consenso
L’albero prova quale fosse un valore; gli accumulatori provano che cosa è successo e in che ordine. Insieme rendono dimostrabile «questa transazione è nella catena in questa posizione» senza avere la catena.
Un albero di Merkle sparso e versionato autentica lo stato. Ogni chiave ha una posizione determinata dal proprio hash, e ogni versione dell’albero condivide i nodi che non sono cambiati: scrivere una chiave in un blocco aggiunge un percorso, non un albero. La prova di una chiave a una certa versione è il percorso dalla foglia di quella chiave fino alla radice che la rete ha consolidato. Gli accumulatori autenticano la sequenza. Uno accumula le transazioni e uno gli eventi, e ciascuno produce una radice che vincola tutto ciò che è stato incluso fino a quel punto, nell’ordine. È questo a rendere dimostrabile «questa transazione è nella catena in questa posizione» senza avere la catena. Fra le due: l’albero dello stato prova quale fosse un valore, gli accumulatori provano che cosa è successo e in che ordine.

Stato speculativo

I risultati di un blocco esistono prima di essere consolidati. Invece di scriverli nell’albero durevole e disfare tutto se il blocco non viene consolidato, lo stato non consolidato è tenuto in un overlay di Merkle sparso in memoria sopra l’ultima versione consolidata. L’esecuzione legge attraverso l’overlay e vede una vista coerente. Se il blocco viene consolidato, l’overlay viene materializzato. Se non lo è, l’overlay viene scartato e nulla di durevole è mai stato toccato. È questo che impedisce all’esecuzione speculativa di lasciare detriti nell’archiviazione.

Caching

I nodi dell’albero sono messi in cache su due livelli: una cache consapevole delle versioni, che tiene indirizzabili quelle recenti, e sotto una cache least-recently-used. Lo schema di accesso di una catena di negoziazione — un piccolo insieme di chiavi calde toccate a ogni blocco, contro una coda lunga toccata di rado — è esattamente lo scenario per cui queste cache esistono.

Pruning

Conservare per sempre ogni versione è una scelta, non un obbligo. Tre pruner indipendenti girano sui tre store, ciascuno con la propria policy di conservazione: uno sul ledger, uno sui valori di stato, uno sui nodi di Merkle. I pruner di Merkle e dei valori di stato sono guidati da indici di obsolescenza scritti insieme ai dati. Quando una versione soppianta un nodo o un valore, la voce soppiantata viene registrata come obsoleta a quella versione. Il pruning diventa così una scansione per intervalli su un indice invece di una caccia alla spazzatura: chi ha scritto ha già detto che cosa sarebbe diventato raccoglibile e quando.
La conservazione è una decisione dell’operatore, con conseguenze reali. Un nodo sottoposto a pruning aggressivo serve lo stato corrente in modo efficiente e non può rispondere a query storiche né servire la sincronizzazione dello stato a un nodo che parte da più indietro. Un nodo di archivio tiene tutto e lo paga. Vedi Gestire un nodo.

Backup e ripristino

Gli store possono essere sottoposti a backup e ripristinati indipendentemente dal nodo in esecuzione: è questo che rende possibile mettere in piedi un nodo da uno snapshot invece di rieseguire dal genesis, e verificare lo stato di un nodo ripristinato rispetto alle radici consolidate invece di fidarsi del backup.

Dove proseguire

Sincronizzazione dello stato

Come un nodo si mette in pari con la catena senza rieseguirla tutta.

Modello di stato

Che cosa viene archiviato, e quale rappresentazione fa fede.

Indexer

Ricostruire lo storico dai registri consolidati.

Gestire un nodo

I ruoli dei nodi, e come chiedere di gestirne uno.