Lo scorso 18 settembre 2018, è stato rivelato un Bitcoin bug. Ma procediamo con ordine.
Read this article in the English version here.
Martedì mattina, in attesa del rilascio della v0.17 dell’aggiornamento di Bitcoin (eravamo alla v0.17rc03; rc = release candidate), è successo qualcosa di strano: invece della ve.017 è stato pubblicato un aggiornamento della v0.16, passando così da v0.16.2 a v0.16.3.
La cosa è abbastanza allarmante ed insolita, perché vuol dire che è stato corretto un errore, che deve essere risolto prima del rilascio della v0.17.
Infatti, normalmente, gli update minori sono pubblicati subito prima rispetto agli aggiornamenti maggiori a cui appartengono, e quasi mai vicini agli update maggiori successivi.
Controllando la modifica, il titolo spiega che si tratta di un “Fix crash bug with duplicate inputs within a transaction”.
La correzione, infatti, fa passare da:
if (!CheckTransaction(*tx, state, false))
a:
if (!CheckTransaction(*tx, state, true))
Insomma, si tratta di una modifica di rilievo, da “false” si passa “true” ovviamente questa modifica è stata subito seguita da un test funzionale, che dovrebbe averne verificato la correttezza).
Estetica del Bug
Dal punto di vista estetico è interessante osservare quanto una sì tanto piccola modifica possa essere cruciale e devastante. E come gli addetti ai lavori sanno, nel software, basta una insignificante virgola fuori posto per dare luogo a catastrofi.
I dettagli tecnici del Bitcoin Bug
In pratica, con questa modifica viene ripristinato il controllo degli input duplicati all’interno delle transazioni quando viene processato un blocco, e non solo quando le transazioni vengono inserite nella mempool.
Il controllo era stato tolto con PR #9049 Remove duplicatable duplicate-input check from CheckTransaction (del 31-10-2016), introdotta nella versione v0.14 e commentata direttamente nel codice con queste parole:
// Check for duplicate inputs — note that this check is slow so we skip it in CheckBlock
Il commento era stato inserito da Matt Corallo, alias @TheBlueMatt spiegando che il controllo durante il processo del blocco fosse inutile, essendo già controllato durante l’inserimento nella mempool. Questa modifica, secondo Corallo, avrebbe fatto guadagnare tra 0.5 e 0.7 millesimi di secondo nel processo del blocco (che sui circa 600 mila blocchi attuali costano circa 6 minuti di elaborazione, per un computer dalle prestazioni medie del 2015).
Purtroppo per l’intuizione di Corallo, non tutti i blocchi che devono essere processati devono necessariamente passare per la mempool, ad esempio, nel caso dei blocchi generati dai miner.
Quindi, nelle versioni v0.14.0rc1 e v0.14.2 l’errore può essere sfruttato per far fallire un’asserzione e mandare in crash bitcoind/Bitcoin-Qt.
Nella versione v0.15 l’asserzione che manda in crash le v0.14 è stata leggermente modificata col risultato che, se l’output che si cerca di spendere due volte è stato creato in un blocco precedente, allora la doppia spesa (il cosiddetto double spending) diventa possibile, creando di fatto inflazione.
Le versioni v0.16 e forse anche v0.17.0rc (corretta anche lei con la v0.17.rc4) hanno ereditato tale caratteristica dalla v0.15.
Sinossi delle versioni vulnerabili
Sinossi da Bitcoin-wiki CVE-2018-17144
Inoltre, bisogna notare che l’errore ha coinvolto anche tutte le altcoin parallele a Bitcoin, compreso Litecoin e BCH.
Soft Fork
La correzione è di fatto un soft fork perché la nuova versione non accetta più i blocchi che invece possono essere accettati dalle versioni v0.15, v0.16 e forse anche le v0.17rc1- v0.17rc3, prima della correzione.
Annuncio dell’errore
- PR #14247 “Fix crash bug with duplicate inputs within a transaction” (18-09-2018 21.57 UTC)
- Bitcoin Core 0.16.3 Released (18-09-2018)
- CVE-2018-17144 Full Disclosure (20-09-2018)
E’ negli annunci pubblicati lo scorso 18 settembre che viene segnalato questo Bitcoin bug.
Poi, il 20 settembre, un post in un forum pubblico ha annunciato che l’errore per tutte le versioni a partire dalla 0.15 che, oltre al crash, poteva essere sfruttato per generare inflazione.
Nonostante sia stato immediatamente rimosso, la notizia si è diffusa e, come si legge nel terzo annuncio, ad un certo punto si riteneva che ormai la maggioranza della potenza di calcolo avesse adottato la correzione. Ed è per questo che si è deciso di annunciare la potenzialità di generare inflazione di quell’errore; inflazione che solamente i miner avrebbero potuto generare.
Attribuzione della scoperta
Il 22 settembre scorso è poi comparso un articolo dal titolo “600 Microseconds” in cui un utente anonimo – Awemany – si attribuisce la scoperta della vulnerabilità mentre stava lavorando sul codice di BitcoinABC e di aver timestampato con originstamp.org, una piattaforma che pubblica su Bitcoin solo una volta ogni 24 ore gli hash raccolti – sul canale Slack di BU il seguente messaggio:
Diatriba con Peter Todd
Ne nasce una diatriba. Infatti, Peter Todd su Twitter inizia ad insultare pesantemente Awemany in merito all’orario dell’annuncio che, invece, si è poi scoperto essere causato da un problema di configurazione del browser di Peter Todd nel settaggio del fuso orario.
Pur non essendo madrelingua inglese, l’espressione “Lying piece of shit” sembra essere sinonimo di un dibattito acceso.
La comunità Bitcoin è molto avvezza ai dibattiti pubblici e al dramma, che, però, puntualmente vengono poi spiegati nel dettaglio su Reddit.
Le argomentazioni di Awemany su Reddit
Awemany su Reddit spiega l’accaduto con un post dal titolo “To address concerns about my identity”.
Ringraziamento di Luke-jr su reddit
Ci sono diversi interventi nella discussione su Reddit: per esempio, in un post il core developer di Bitcoin luke-jr ringrazia Awemany, come si vede nell’immagine qui sotto:
Conseguenze
Tecniche
Non si scatenerà una catastrofe, il problema è in fase di risoluzione definitiva e chiusura, ma non è ancora stato reso pubblico un test funzionale che possa rendere riproducibile lo sfruttamento dell’errore per generare inflazione.
CVE-2018-17144 Full Disclosure
il 23-09-2018, il 23.5% dei nodi aveva adottato la versione v0.16.3
Sui dati c’è disaccordo. Ad esempio, secondo Luke Dashjr:
Vale sempre la legge di Bitcoin: Don’t trust, verify
In ottica “don’t trust, verify”, bisogna sempre:
- Verificare puntualmente, che la correzione non sia solo una mitigazione, ma una soluzione vera;
- Verificare se la vulnerabilità sia già stata sfruttata in passato per generare inflazione (i.e. rifare un rescan, ed utilizzare il comando API gettxoutsetinfo).
Ed è per questo che il developer Isidoro Ghezzi ha modificato il codice sorgente di bitcoind (in diverse ramificazioni del codice), aggiungendo informazioni extra di debug e log per analizzare meglio il problema.
Ieri alla conferenza BalticHoneyBadger 2018, alcuni dei protagonisti, come ad esempio Mat Corallo e Bryan Bishop, hanno discusso ampiamente e in estrema trasparenza, la vulnerabilità, il processo di comunicazione e della imminente risoluzione della stessa.
Politiche di rilascio
Scrivere software implica bug, sicuramente il processo di peer review ha mostrato qualche allentamento, visto che la proposta di Corallo era stata approvata da quello che potremmo definire il gotha del development del protocollo Bitcoin: Gregory Maxwell, Pieter Wuille, Wladimir J. van der Laan, (oltre al proponente Matt Corallo).
Evidentemente le troppe priorità hanno lasciato spazio alla leggerezza, anche se il nome della funzione toccata, la CheckBlock, avrebbe dovuto far scattare un campanello d’allarme
Effetti sui mercati
Chi si fosse aspettato un crollo clamoroso del valore di bitcoin sui mercati, a causa di questa vulnerabilità, è rimasto deluso: bitcoin ha un sistema immunitario molto sviluppato. Inoltre, la trasparenza che caratterizza questi avvenimenti ha determinato un non-effetto. Insomma, chi ha scommesso sullo short, ha piazzato la scommessa sbagliata.
Conclusioni
Cosa possiamo dedurre da questo Bitcoin bug? Questa vulnerabilità è stata presente per due anni ma nessuno l’ha sfruttata a proprio vantaggio.
O i nemici di Bitcoin hanno voluto porre in essere un atto nobile e si sono astenuti da trarne profitto, oppure è una ulteriore conferma della superiorità tecnica degli sviluppatori Bitcoin.
Sicuramente, questa vulnerabilità ha posto mostrato l’importanza della peer-review e di come debba essere sempre estesa ed accurata, anche quando si pensa che si tratti di cambiamenti minori: sviluppare sul protocollo Bitcoin è un’attività complessa e con effetti domino imprevedibili.
Necessità di una revisione delle politiche di rilascio in produzione
Le politiche di rilascio e di messa in produzione sono ovviamente sotto scrutinio all’interno della comunità. Si pensa, per esempio, di imporre delle unit test e dei functional test specifici, di avere un numero minimo di di programmatori per la revisione e di avere un rilascio con quarantena, di almeno 6 mesi, su un’altra blockchain, come per esempio quella di Litecoin.