Un post che spiega le idee essenziali del protocollo Bitcoin. L’ispirazione è questo post di Michael Nielsen.
Aprendo per la prima volta un portafoglio Bitcoin, cioè un programma che gestisce Bitcoin (provate!), preliminarmente il programma farà due cose:
- Scaricherà un file gigantesco (più di 100GB) chiamato blockchain.
- Vi darà un “indirizzo”, cioè una specie di numero di conto corrente, una cosa tipo 1Mz46Gtr44…
Il file gigantesco, la blockchain, è l’elenco di tutte le transazioni mai avvenute in bitcoin. L’indirizzo invece è l’identificatore unico del vostro conto bitcoin. Ora vediamo di capirci qualcosa.
Una banca tradizionale
Per prima cosa semplifichiamoci il lavoro e consideriamo una banca tradizionale, l’unica ad emettere una certa moneta che chiameremo il forcone. Essendo l’unica banca a trattare forconi, tutte le transazioni in forconi passano attraverso di essa: allora la banca dovrà tenere conto di tutte queste transazioni scrivendole in una lista di transazioni che consisterà in tante scritte del tipo:
Indirizzo 1Mz46Gt dà 2,44 forconi a indirizzo 3TrwqM3
Quest’idea può essere un po’ controintuitiva: potremmo pensare che alla banca basti tenere traccia dei numeri di conto e dei soldi disponibili. Avere la lista di transazioni è sufficiente per ricostruire i soldi disponibili sul conto: basta sommare le entrate e sottrarre le uscite. Il vantaggio della lista di transazioni è che se una transazione viene effettuata per errore, allora per risolvere il problema basta rimuovere la transazione dalla lista. Al contrario, se tenessimo conto solo dei soldi disponibili, non potremmo cancellare una transazione.
La lista di transazioni in forconi è un file enorme, ed è quasi la blockchain, come vedremo fra poco. Ora, cosa succede quando un utente della banca, ad esempio Arduino, prova a fare una transazione, cioè a dare dei soldi, ad esempio a Brunilde?
- La banca controlla che sia davvero Arduino a fare la transazione (ad esempio chiedendogli la password)
- Controlla che ci siano abbastanza soldi sul conto di Arduino (cioè calcola i soldi sul conto di Arduino usando la lista di transazioni e verifica che siano sufficienti per la transazione)
- Aggiunge una riga alla lista delle transazioni dicendo: “Arduino dà X forconi a Brunilde”, cioè “trasferisce” i soldi sul conto di Brunilde.
La lista concatenata, o blockchain
Il problema del realizzare il bitcoin è quello di rimuovere la banca centrale: le operazioni da 1, 2 e 3 devono essere svolte da tutti gli utenti della rete bitcoin collettivamente.
La cosa non è affatto facile. Innanzitutto, ogni utente deve avere sul proprio computer l’intera lista di transizioni effettuate in bitcoin sin dall’inizio dei tempi. In questa maniera ogni utente bitcoin può sapere se un altro utente è autorizzato a effettuare una certa transazione. Per evitare che un utente qualsiasi possa falsificare la lista delle transazioni, questa viene fatta diventare una lista concatenata, o blockchain in inglese. La lista concatenata è uguale alla lista di transazioni ma include un meccanismo per impedire la contraffazione della lista stessa.
Abbiamo detto prima che la lista di transazioni è formata da tante righe della forma “Indirizzo 1Mz46Gt dà 2,44 forconi a indirizzo 3TrwqM3”. Nella lista concatenata includiamo un pezzo in più, cioè ogni volta che aggiungiamo una transazione alla lista mettiamo anche l’hash della lista stessa (della lista intera). Abbiamo parlato delle funzioni hash in un altro articolo.
Ciò garantisce una maggiore sicurezza: supponiamo che qualcuno voglia modificare una vecchia transazione. Allora non basterà modificare solo quella transazione, ma dovrà modificare anche tutte le successive. Questo perché le successive transazioni includono l’hash della lista intera fino a quel punto; cambiando una vecchia transazione, cambieranno tutti gli hash e quindi chi vuole modificare una singola transazione dovrà modificare anche tutte le transazioni successive.
Ciò non assicura che non sia possibile modificare la lista concatenata, ma lo rende molto più complicato e soprattutto più facile da scoprire. La lista concatenata è il file enorme che l’applicazione per i bitcoin scarica la prima volta che la aprite.
Come mettersi d’accordo
Ora ogni utente ha la propria copia della lista concatenata sul proprio computer, che contiene tutte le transazioni fino a quel momento. Il problema principale adesso è: come riuscire a mettere d’accordo tutti su quali transazioni aggiungere alla lista?
Se ognuno potesse semplicemente aggiungere transazioni a caso, allora potrebbe aggiungere transazioni che lo avvantaggiano a scapito degli altri (tipo: tutti i soldi del mondo vanno nel mio conto). Dobbiamo trovare un modo per mettere d’accordo tutti su come continuare la lista concatenata e al contempo impedire comportamenti del genere.
Una prima regola potrebbe essere: seguiamo la maggioranza. Se la maggioranza degli utenti approva una transazione, allora la transazione viene aggiunta alla blockchain.
A questo punto però un utente malevolo può semplicemente crearsi tante identità virtuali e farle votare in massa la transazione malevola. A parte la rottura di palle, non c’è nessun problema tecnico nel creare tante identità virtuali in modo da avere la maggioranza degli utenti della rete. Ci serve un altro metodo.
La soluzione è di dare maggiore potere di voto agli utenti con maggiore potere di calcolo. Così se Arduino volesse prendere il controllo della rete bitcoin dovrebbe avere il $50\%+1$ della potenza di calcolo di tutta la rete. Molto più complicato: servono tanti computer, e i computer sono costosi, succhiano energia, eccetera.
In concreto, supponiamo che oltre ad Arduino e Brunilde, nella rete collettiva che gestisce i forconi ci sia anche un terzo utente, Cagliostro. Avevamo detto che Arduino vuole mandare dei forconi a Brunilde. Per farlo, invia a tutti gli utenti della rete un messaggio in cui dice: “Sono il numero di conto XYg45 e voglio mandare 5 dei miei forconi al numero di conto 767bx”. A questo punto il terzo utente della rete, Cagliostro, controlla la sua versione della lista delle transazioni e dice: ah! Arduino ha davvero 5 forconi. Se attuassimo l’idea di prima, cioè seguire la maggioranza, gli basterebbe inviare a tutti un messaggio tipo “la transazione 67637 può avvenire”. Invece no: deve anche dimostrare di avere abbastanza potenza di calcolo, e per fare ciò gli chiediamo anche di inviare una cosa che chiamiamo il sudore-della-fronte (“proof-of-work” in inglese).
Il sudore-della-fronte è una cosa difficile da ottenere, perché bisogna aver faticato per ottenerlo, però una volta ottenuto chiunque può vedere che l’avete ottenuto. Fuor di metafora Cagliostro dovrà risolvere un complesso problema matematico, difficile da risolvere (cioè che richiede una certa potenza di calcolo per un certo tempo), ma la cui soluzione è facile da verificare. Ad esempio: quali sono i fattori primi di 869? Non è per niente facile trovare la soluzione. Però una volta trovata ($79 \times 11$) basta moltiplicare i due numeri insieme per verificare che è corretta.
Nel protocollo bitcoin l’idea è la stessa, ma il problema da risolvere è diverso e si basa sulle funzioni di hash. Prima di tutto la transazione che si vuole convalidare è trasformata in una sequenza numerica, e poi il problema posto è il seguente: si chiede di trovare il numero che aggiunto alla fine della transazione e dato in pasto alla funzione hash dia un risultato con all’inizio $10$ zeri. Avremmo potuto richiedere $20$ zeri oppure $2$ o qualsiasi altro numero: più zeri richiediamo più è difficile trovare la soluzione. La potenza dei computer aumenta di continuo; il numero di zeri è aggiustato automaticamente dal sistema in modo tale che un blocco impieghi in media $10$ minuti per trovare la soluzione.
Quindi Arduino vuole mandare dei forconi a Brunilde. Scrive la transazione, la spedisce a tutti i computer nella rete chiedendo di convalidare. Cagliostro, che è connesso alla rete bitcoin, confronta la transazione con la sua copia della blockchain, vede che è valida, risolve il problema corrispondente, spedisce la convalida con la soluzione del problema a tutti gli utenti, che quindi verificano il problema e aggiornano la loro copia della blockchain.
Cagliostro ha convalidato la transazione e per farlo ha dovuto usare notevoli risorse computazionali, che si traducono in un costo (elettricità, computer, rete, ecc.). Chiaramente non ha nessuna convenienza nel farlo. Per convincere gli utenti a convalidare le transazioni, e quindi a usare le loro risorse computazionali, il sistema gli assegna automaticamente un certo numero di bitcoin per ogni tot transazioni convalidate. Questo è il cosiddetto “minare” (mining) nel senso di estrarre da una “miniera”. Quelli che “minano” bitcoin in pratica convalidano le transazioni della rete. Per ogni blocco convalidato, ricevono $25$ bitcoin. Di solito si mina in gruppo e si dividono i guadagni.
Rimane un unico problema: che succede se due gruppi di utenti ad un certo punto cominciano ad avere due liste diverse? La regola è semplice: si aspetta un po’, e poi si segue la lista più lunga, cioè quella su cui sono impiegate le risorse computazionali maggiori. Quindi se un utente malevolo volesse modificare la blockchain da solo, potrebbe farlo, purché controlli il $50\%+1$ della potenza di calcolo della rete. In questo modo potrebbe convalidare da solo una transazione malevola, e gli altri lo seguirebbero perché la sua sarebbe sempre la lista più lunga. Chiaramente ottenere il $50\%+1$ della potenza di calcolo della rete è nella pratica estremamente difficile.