Come nasce il Genesis Block Bitcoin? Alla riga 113!
Condividi

Indice
Più o meno tutti nel mondo Bitcoin conosciamo il Genesis Block, il primo blocco cioè che compone la Blockchain (o chain of blocks, come la chiamava Satoshi nel suo Whitepaper) di Bitcoin.
In questo articolo ti andrò a spiegare come nasce davvero il Genesis Block, andando a studiare direttamente il codice del protocollo Bitcoin che nel lontano 2009 ha dato inizio alla chain of blocks più famosa di sempre!
Prima di tutto, Bitcoin è scritto in C++ e il suo sviluppo viene coordinato attraverso il repository su GitHub che ad oggi conta circa 20.356 commit (ndr modifiche al codice) e 624 contributori diversi. Puoi facilmente scaricarlo cliccando il pulsante verde in alto a destra ‘Clone or Download‘ e poi su ‘Download ZIP‘.
Alla ricerca del codice!
Il codice che andremo a studiare si trova all’interno della cartella src nel file chainparams.cpp. Tutto comincia all’interno del costruttore della classe CMainParams
, al cui interno troviamo una chiamata alla funzione CreateGenesisBlock
alla riga 113.
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); | |
consensus.hashGenesisBlock = genesis.GetHash(); | |
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); | |
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); |
All’interno di questa funzione troviamo la dichiarazione di una nuova variabile che Satoshi ha chiamato
genesis
di tipo CBlock
.
CBlock genesis; | |
genesis.nTime = nTime; | |
genesis.nBits = nBits; | |
genesis.nNonce = nNonce; | |
genesis.nVersion = nVersion; |
Analisi dei parametri
Come puoi osservare, alla riga 113 la funzione CreateGenesisBlock
viene chiamata passandogli dei valori, chiamati argomenti della funzione.
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); |
Andiamo ora a spiegare il significato di questi valori molto importanti:
1231006505
: Unix timestamp del blocco. Il numero di secondi trascorsi dal 1° Gennaio 1970. 1231006505 corrisponde al 3 Gennaio 2009 ore 18:15:05 GMT come possiamo facilmente verificare su EpochConverter2083236893
: Nonce, cioè il numero per collegare il blocco genesis0x1d00ffff
: Soglia (target threshold) entro cui deve essere contenuto l’hash dell’header del blocco per essere considerato valido, valore legato alla difficulty e all’hash rate.1
: versione del protocollo Bitcoin, serve per decidere quali blocchi accettare e quali rifiutare. A partire da Bitcoin Core 0.11.2 gli headers dei blocchi Bitcoin hanno questo valore impostato a0x3fff0000
.50 * COIN
: il reward per il mining del blocco Genesis. Per i primi 210.000 blocchi (cioè fino al primo Halving) la ricompensa era di 50 Bitcoin. Chi stabilisce il numero di blocchi ogni cui effettuare l’Halving? Sempre all’interno di questo file possiamo trovare una proprietà assegnata all’attributoconsensus
alla riga 66.
CMainParams() { | |
strNetworkID = "main"; | |
consensus.nSubsidyHalvingInterval = 210000; | |
consensus.BIP16Exception = uint256S("0x00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22"); | |
consensus.BIP34Height = 227931; |
Questa funzione non andrà ancora a creare il blocco, ma chiamerà un’altra funzione dallo stesso nome ma con diversi parametri (overloading). Molto interessante la riga 54, in cui possiamo trovare la famosa frase che Satoshi segnò per sempre all’interno del Genesis Block, assegnata ad una variabile di tipo puntatore a char.
The Times 03/Jan/2009 Chancellor on brink of second bailout for banks
static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) | |
{ | |
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; | |
const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; | |
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); | |
} |
Assert e check del risultato
Il blocco creato grazie alla funzione CreateGenesisBlock
viene poi salvato all’interno dell’attributo consensus
. Successivamente troviamo la direttiva assert
, con cui viene controllato il risultato tramite due check, uno sull’hash del blocco e uno sull’hash del merkle root.
La funzione assert
è una funzione molto speciale con cui possiamo effettuare un check tra due valori; l’esecuzione del programma continuerà solo in caso di esito positivo, cioè solo quando i valori confrontati saranno uguali! Questo controllo hardcoded è possibile grazie alla natura deterministica delle funzioni di Hash. Per una successione di input avremo sempre lo stesso output, indipendentemente dal momento in cui eseguiremo la funzione (escludendo che nella successione ci sia un timestamp, ovviamente).
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); | |
consensus.hashGenesisBlock = genesis.GetHash(); | |
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); | |
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); |
Conclusioni
Questa prima analisi del codice di Bitcoin è terminata. Abbiamo deciso di partire dalle basi, quale argomento sarebbe stato più adatto se non il Genesis Block? Potremmo definire questo articolo il Genesis Article of Bitcoin Code Analysis 😃
PS: Non dimenticarti di entrare nel nostro gruppo Telegram per rimanere aggiornate su tutte le news, articoli e iniziative!