Blockchain

I blockchain sono una struttura dati inventata da Satoshi Nakamoto, pseudonimo dell’inventore della criptovaluta bitcoin, che nel 2008 la utilizzò per risolvere il problema del double spending. Il successo di tale struttura dati non è però legata esclusivamente al suo utilizzo nell’infrastruttura bitcoin, ma più in generale nella possibilità di utilizzarla per realizzare registri pubblici distribuiti praticamente inviolabili.

Definizione

Da un punto di vista prettamente informatico il blockchain è una catena o lista di blocchi (di dati) che hanno la caratteristica di include l’hash (funzione matematica non invertibile che mappa una stringa di lunghezza arbitraria in una stringa di lunghezza predefinita) che identifica il blocco in modo univoco e che permette il collegamento con il blocco successivo nella catena.

La peculiarità che rende il registro non modificabile è che l’hash del blocco è calcolato includendo anche l’hash del blocco precedente. Se, ad esempio, andiamo a modificare i dati del blocco 1 in figura, anche il suo hash risulterà differente e conseguentemente l’hash di tutti i blocchi che lo seguono.

L’operazione di hashing, però, di per se non è una operazione computazionalmente difficile, ma come vedremo viene resa tale introducendo dei vincoli sul suo valore. Inoltre, alterare una catena blockchain in un server non è sufficiente, in quanto tutti i server che partecipano alla gestione del registro dovrebbero approvare la modifica. Quest’ultimo aspetto non è comunque oggetto del presente articolo, che si concentra prevalentemente sulla definizione della struttura dati.

Struttura Dati del Blocco

Innanzitutto definiamo la classe che implementa la struttura dati di un blocco. Come accennato conterrà l’hash corrente, l’hash del blocco precedente ed i dati. Inoltre è presente un timestamp ed un intero nonce la cui utilità sarà evidente quando parleremo di mining.

Calcolo dell’Hash

Per il calcolo dell’hash utilizziamo le api di Java Security ed in particolare la classe MessageDigest. L’operazione restituisce però una sequenza di byte quindi per convertirlo in una stringa “stampabile” la codifichiamo in esadecimale con le funzionalità del pacchetto Apache Commons Codec. Per comodità collochiamo la funziona in una classe di utilità Utils.

Integrità della Blockchain

Verificare l’integrità della blockchain significa verificare la correttezza dell’hash del singolo blocco e la corrispondenza dell’hash del blocco precedente (ad eccezione del primo blocco della catena che ovviamente non ha l’hash del blocco precedente). La funzione di verifica della validità riceve quindi in input una coppia di blocchi consecutivi ed esegue i test indicati:

Ovviamente è sufficiente che un solo blocco della catena non soddisfi le condizioni affinché l’intera blockchain risulti non valida e quindi corrotta. Immaginando di memorizzare la blockchain in una  variabile blockchain di tipo ArrayList la funzione di verifica sarà:

Mining

Il mining è l’operazione principale eseguita sulla blockchain e consiste sostanzialmente nel generare  un nuovo blocco e manipolarlo opportunamente affinché possa essere aggiunto alla blockchain mantenendola in uno stato di validità. Molto semplicemente significa calcolarne l”hash ed aggiungerlo alla catena inserendo il riferimento al blocco precedente.

Nella realtà le cose non si svolgono nel modo indicato. La sicurezza dell’intera infrastruttura della blockchain si basa su due requisiti:

  1. la verifica dell’integrità di una blockchain deve essere veloce in modo da poter essere eseguita su catene anche molto grandi in tempi rapidi;
  2. il calcolo dell’hash per l’inserimento di un nuovo blocco nella catena deve essere un’operazione computazionalmente difficile e richiedere quindi tempi lunghi. Questo al fine di rendere praticamente impossibile la corruzione del dato di un blocco che, come detto, richiederebbe il calcolo dell’hash su tutta la catena con tempi “biblici”.

La soluzione presentata soddisfa il primo requisito ma non il secondo. Per rendere difficile l’operazione di mining l’architettura blockchain introduce un semplice vincolo sull’hash generato. Il vincolo è quello che l’hash debba iniziare con un numero di caratteri 0 pari ad una costante del sistema chiamata difficulty. E’ a tale scopo che è introdotta la nonce nella struttura dati del singolo blocco. L’idea del mining è quella di modificare la nonce fino a quando l’hash calcolato non soddisfi il vincolo imposto.

Nella funzione minBlock() la variabile target non è altro che una stringa con tanti 0 quanto è il valore della difficulty. Nel sistema bitcoin la difficulty è un parametro che viene aggiornato periodicamente al fine di rendere sempre più difficile il mining, anche in considerazione dell’upgrade tecnologico degli hardware utilizzati.

Tornando al nostro esempio l’operazione di inserimento di un nuovo blocco diviene:

Mentre all’operazione di verifica della validità dei una blockchain aggiungiamo la condizione che l’hash soddisfi il vincolo della difficulty:

Codice Sorgente

Il codice sorgente completo anche di un Main() che esegue un tentativo di corruzione dei dati della blockchain è scaricabile qui blockchain.