Glossario / Riferimento per sviluppatori
MSG_CMPCT_BLOCK
- Che cos'è MSG_CMPCT_BLOCK?
- MSG_CMPCT_BLOCK, tipo di inventario 4, è un codice riservato alle richieste: non compare mai in un annuncio ed è valido solo all'interno di un messaggio getdata inviato a un peer che lo ha prima accettato.
Specificato nel BIP-152.
I blocchi compatti si negoziano, non si annunciano. Un peer invia sendcmpct una volta per dire che li accetterà, e solo allora l'altra parte può rispondere a un nuovo blocco con il tipo 4 invece del tipo 2. BIP152 è arrivato con Bitcoin Core 0.13.0 ad agosto 2016, e il risparmio è proprio il punto: sei byte per indicare una transazione che il destinatario possiede già, invece dei duecento o più necessari per inviarla due volte.
Come funziona
MSG_CMPCT_BLOCK richiede una descrizione di un blocco invece del blocco, e la descrizione vale la pena solo quando i due nodi hanno mempool simili.
Prima viene la negoziazione. Il messaggio sendcmpct porta un flag e un numero di versione: la versione 1 identifica le transazioni tramite txid, la versione 2 tramite witness txid ed è l'unica in uso dal segregated witness. Un nodo non deve mai mettere il tipo 4 in un getdata destinato a un peer che non ha inviato sendcmpct, perché quel peer non ha alcun obbligo di comprenderlo.
La risposta è un messaggio cmpctblock che contiene l'intestazione di 80 byte, un nonce di otto byte, un identificatore corto di sei byte per transazione e alcune transazioni fornite per intero, tra cui sempre la coinbase, che il destinatario non può in alcun modo aver già visto. Gli identificatori corti sono prodotti con SipHash con chiave derivata dall'intestazione e da quel nonce, quindi cambiano per ogni blocco e per ogni richiesta. La casualizzazione è una difesa: uno schema fisso permetterebbe a un attaccante di precalcolare due transazioni che collidono e di bloccare la ricostruzione in tutta la rete in una volta.
Il destinatario confronta gli identificatori con la propria mempool, chiede ciò che manca con getblocktxn e ricostruisce il blocco localmente. La validazione successiva è quella ordinaria e nessuna regola di consenso viene toccata.
La profondità è limitata. Bitcoin Core serve un blocco compatto solo per i cinque blocchi più recenti e risponde a una richiesta per qualsiasi blocco più vecchio con un blocco completo, perché un destinatario così indietro non ha una mempool utile e finirebbe per chiedere ogni transazione che contiene.
Dove lo vedi
La visione più chiara di MSG_CMPCT_BLOCK è nei log di Bitcoin Core, che riportano come è andata ogni ricostruzione.
Avvia il nodo con -debug=cmpctblock e ogni nuovo blocco produce una riga che indica quante transazioni erano precompilate, quante sono state trovate nella mempool e quante è stato necessario scaricare. Su una macchina in funzione da ore il conteggio delle transazioni scaricate è di solito zero, e il blocco arriva come decine di kilobyte invece di un megabyte e mezzo. Un blocco con 3.000 transazioni richiede 18.000 byte di identificatori corti più l'intestazione e la coinbase.
Quell'aritmetica crolla su un nodo appena avviato. Una mempool vuota significa che ogni identificatore non trova corrispondenze, la richiesta successiva chiede l'intero blocco e il viaggio di andata e ritorno in più rende il percorso compatto più lento del semplice chiedere il blocco direttamente. Per questo il codice appartiene ai nodi che stanno sulla punta della catena e non compare mai durante una sincronizzazione iniziale.
Per chi gestisce un nodo a casa, questa è la funzione che decide se una connessione ordinaria tiene il passo della rete o resta indietro ogni volta che viene trovato un blocco.