Scelta del fork e difficoltà cumulativa
A volte due versioni della catena sono in concorrenza per un certo tempo, per esempio quando la rete resta divisa per qualche minuto. Ogni nodo ZooBC segue allora il ramo con la difficoltà cumulativa maggiore: un totale progressivo dei pesi dei blocchi in cui un blocco di un produttore estratto presto pesa più di uno tardivo. La regola è lo stesso calcolo su ogni nodo, quindi la rete converge senza che nessuno scelga un vincitore.
Più pesante, non più lungo
Ogni blocco aggiunge al totale progressivo una quantità che diminuisce quanto più in basso, nell'estrazione di quell'altezza, si trovava il suo produttore. Nella forma più semplice, un blocco aggiunge 1.000.000 diviso per la posizione del produttore nell'estrazione: un blocco del primo produttore estratto aggiunge 1.000.000, uno del terzo circa 333.333.
Una catena di blocchi puntuali pesa quindi più di una catena i cui produttori hanno continuato a saltare i loro turni, anche quando la seconda catena è più lunga. Tre blocchi di primo round pesano 3.000.000; quattro blocchi di terzo round pesano circa 1.333.332.
Le alternative non funzionerebbero. Contare le transazioni permetterebbe a un produttore di gonfiare il suo blocco per vincere. Il «primo visto» cambia da nodo a nodo a causa dei ritardi di rete, quindi i nodi potrebbero restare divisi per sempre. E non esiste un'autorità che dichiari ufficiale un ramo.
Il peso esatto di un blocco
Dalla versione 0.5.8 l'incremento di un blocco è:
increment = floor(1,000,000 × |S| / (k × |A|))
- S è l'insieme di estrazione al blocco precedente: i nodi attivi meno quelli sospesi.
- A è l'intero registro attivo al blocco precedente. La quota |S| / |A| non supera mai 1.
- k conta le estrazioni fino all'ultima comparsa del produttore nei round fino al round del blocco: 1 per il produttore estratto per primo che data il blocco in orario, 3 per un produttore designato dalla terza estrazione. (Se il produttore non vi si trova, si usa la sua prima comparsa entro 2 × n estrazioni, dove n è il numero di nodi dell'insieme di estrazione, e, in mancanza anche di questa, una posizione in ordine di hash.)
Due limiti inferiori impediscono a un blocco di rivendicare più di quanto gli spetti. k non è mai inferiore al round in cui cade il timestamp del blocco, quindi un timestamp tardivo non può conservare il peso di un round anticipato (vedi round, tempi e finestre). E per il produttore del blocco precedente k non è mai inferiore al suo round retrocesso, 10 (vedi round prioritari, blocchi vuoti e il produttore precedente).
La quota dell'insieme di estrazione conta quando la rete si divide. Se ciascun lato di una divisione sospende i nodi che non riesce a sentire, entrambi i lati aggiungerebbero altrimenti 1.000.000 per ogni blocco puntuale e sembrerebbero ugualmente pesanti. Con la quota, un lato che funziona con 3 seggi su 11 aggiunge al massimo 272.727 per blocco, contro 727.272 del lato che ne ha 8. Blocco per blocco, il lato che detiene più seggi è il più pesante.
Ogni blocco porta la propria difficoltà cumulativa come stringa decimale. Ogni validatore la ricalcola e rifiuta un blocco che la dichiari in modo errato. Due totali si confrontano prima per lunghezza, poi cifra per cifra.
Il punteggio di partecipazione non ha alcun ruolo in tutto questo: il peso legge le posizioni nell'estrazione e l'insieme di estrazione, non i punteggi.
Parità esatte
Le parità esatte capitano, per esempio quando due rami della stessa lunghezza sono entrambi fatti di blocchi puntuali di primo round. Dalla versione 0.5.8 gli hash dei blocchi di punta dei due rami vengono confrontati come byte, e vince l'hash più basso. Un nodo passa a un ramo di pari peso il cui hash di punta è più basso del proprio, altrimenti mantiene il proprio, e non chiede nulla a nessuno. Ogni nodo applica lo stesso confronto agli stessi due hash, quindi l'intera rete converge subito.
Pesare un ramo prima di passarvi
L'affermazione di un peer che il suo ramo sia più pesante non prova nulla di per sé. Un nodo pesa un ramo concorrente prima di toccare la propria catena:
- Trova l'ultimo blocco che le due catene hanno in comune.
- Scarica a pagine il ramo successivo a quel blocco, verificando la firma di ogni intestazione e i collegamenti tra i blocchi.
- Ricalcola il peso di ogni blocco, riproducendo il registro e le sospensioni propri di quel ramo dal blocco comune in avanti, perché dall'altra parte di una divisione possono essere diversi.
- Si ferma non appena il ramo è più pesante della propria catena, e solo allora fa rollback e lo applica. Un ramo che risulta più leggero, o che non riesce a superarla entro un numero limitato di blocchi, viene rifiutato senza alcun rollback.
Un peer la cui difficoltà dichiarata differisce dal valore ricalcolato viene registrato come bugiardo.
I rollback hanno limiti rigidi: mai più di 720 blocchi (3 ore) su mainnet, e mai sotto l'ultimo checkpoint co-firmato sulla catena spine. Vedi finalità e rollback.
Nodi indietro e sondaggi tra peer
Un nodo la cui punta è più vecchia di 7.200 secondi (2 ore) non si fida di qualunque peer dichiari di essere più avanti: segue la punta che riportano almeno due terzi di un campione di peer registrati. Gli altri sondaggi tra peer che un nodo può eseguire, per confermare un ramo più pesante o controllare il proprio stato di salute, sono una politica locale, non consenso.