Come creare una blockchain con Python?

Sapevi che Bitcoin è costruito sopra Blockchain? Oggi costruiremo una Blockchain con Python da zero.

Cos’è la Blockchain?

Nel 2008 il Carta bitcoin è stato pubblicato da un individuo o gruppo sconosciuto di nome Satoshi Nakamoto. Bitcoin è uscito come una versione peer-to-peer del denaro elettronico che consentiva transazioni senza passare attraverso istituzioni centralizzate (banche). La maggior parte delle persone non sa che in quello stesso articolo Satoshi ha definito un modo distribuito di archiviare le informazioni, oggi noto come Blockchain.

Tecnologia blockchain

Per dirla semplicemente, Blockchain è un registro digitale condiviso e immutabile che memorizza le transazioni su una rete decentralizzata di computer.

Possiamo dividere Blockchain in due semplici termini:

  • Block: uno spazio in cui memorizziamo le transazioni
  • Catena: un insieme di record collegati

Questo definisce Blockchain come una catena di blocchi collegati, in cui ogni blocco memorizza una transazione effettuata con parametri specifici.

Ogni blocco è costruito sopra un altro blocco, creando una catena irreversibile di blocchi. In altre parole, ogni blocco dipende da un altro. Questo risulta in un sistema robusto e immutabile in cui chiunque abbia le autorizzazioni corrette può rivedere l’integrità.

Blockchain introduce un interessante insieme di funzionalità:

  • Immutabilità della storia
  • Persistenza dell’informazione
  • Nessun errore con i dati memorizzati

Molti sistemi attualmente si basano su Blockchain, come criptovalute, trasferimento di asset (NFT) e forse nel prossimo futuro, votazione.

Vale la pena ricordare che una Blockchain Python non deve essere un programma complesso con migliaia di righe di codice. Al centro, sarebbe un elenco di transazioni collegate tra loro.

Naturalmente, questa è stata una breve spiegazione, ma se vuoi una guida completa, abbiamo prodotto un tutorial completo su Blockchain per principianti. Assicurati di controllarlo.

Senza ulteriori indugi, costruiamo una semplice Blockchain con Python.

Costruire una blockchain con Python

Prima di iniziare, definiamo cosa faremo in questo tutorial:

  • Costruisci un semplice sistema Blockchain scritto in Python
  • Usa la nostra Blockchain con transazioni prestabilite rappresentate come stringhe
  • Metti alla prova l’immutabilità della nostra Blockchain

Non useremo JSON ma elenchi Python. Questo ci consentirà di semplificare il processo e concentrarci sull’applicazione dei concetti chiave di una Blockchain.

Di cosa avrai bisogno per seguire questo tutorial:

Creazione della classe Block

Apri il tuo editor di codice preferito e crea un file main.py. Questo sarà il file con cui lavoreremo.

Ora importa hashlib, un modulo che ci consente di creare messaggi crittografati unidirezionali. Le tecniche di crittografia come l’hashing fanno sì che Blockchain crei transazioni sicure.

Una funzione hash è un algoritmo che prende alcuni dati (di solito una stringa codificata) e restituisce un identificatore univoco, spesso chiamato “digest” o “firma”. Quest’ultima parte è vitale; con una funzione hash, una leggera differenza nell’input produce un identificatore radicalmente diverso come output. Lo vedremo in azione più avanti.

Per ora, importa semplicemente il modulo integrato hashlib:

# main.py file
"""
A simple Blockchain in Python
"""

import hashlib

Questo modulo include la maggior parte degli algoritmi di hashing di cui avrai bisogno. Tieni presente che useremo la funzione hashlib.sha256().

Ora, entriamo nel GeekCoinBlock, il nostro nome blockchain totalmente originale.

class GeekCoinBlock:
    
    def __init__(self, previous_block_hash, transaction_list):

        self.previous_block_hash = previous_block_hash
        self.transaction_list = transaction_list

        self.block_data = f"{' - '.join(transaction_list)} - {previous_block_hash}"
        self.block_hash = hashlib.sha256(self.block_data.encode()).hexdigest()

So che questo potrebbe comportare un pezzo di codice goffo. Analizziamo ogni parte nella prossima sezione.

Spiegazione GeekCoinBlock

Innanzitutto, creiamo una classe denominata GeekCoinBlock, un wrapper per oggetti che avranno determinate caratteristiche (attributi) e comportamenti (metodi).

Quindi definiamo il metodo __init__ (chiamato anche costruttore), che viene invocato ogni volta che viene creato un oggetto GeekCoinBlock.

Questo metodo ha tre parametri:

  • sé (l’istanza di ogni oggetto)
  • previous_block_hash (un riferimento al blocco precedente)
  • Transaction_list (un elenco di transazioni effettuate nel blocco corrente).

Memorizziamo l’hash precedente e l’elenco delle transazioni e creiamo una variabile di istanza block_data come stringa. Questo non accade con le vere criptovalute, in cui memorizziamo quel tipo di dati come un altro hash, ma per semplicità memorizzeremo ogni blocco di dati come una stringa.

Infine, creiamo block_hash, che gli altri blocchi utilizzeranno per continuare la catena. Ecco dove hashlib torna utile; invece di creare una funzione hash personalizzata, possiamo utilizzare lo sha256 predefinito per creare blocchi immutabili.

Questa funzione riceve stringhe (o byte) codificate come parametri. Ecco perché stiamo usando il metodo block_data.encode(). Successivamente, chiamiamo hexdigest() per restituire i dati codificati in formato esadecimale.

So che tutto questo può essere travolgente, quindi giochiamo con hashlib su una shell Python.

In [1]: import hashlib

In [2]: message = "Python is great"

In [3]: h1 = hashlib.sha256(message.encode())

In [4]: h1
Out[4]: <sha256 ... object @ 0x7efcd55bfbf0>

In [5]: h1.hexdigest()
Out[5]: 'a40cf9cca ... 42ab97'

In [6]: h2 = hashlib.sha256(b"Python is not great")

In [7]: h2
Out[7]: <sha256 ... object @ 0x7efcd55bfc90>

In [8]: h2.hexdigest()
Out[8]: 'fefe510a6a ... 97e010c0ea34'

Come puoi vedere, un leggero cambiamento nell’input come “Python è fantastico” in “Python non è eccezionale” può produrre un hash completamente diverso. Questo ha tutto a che fare con l’integrità della Blockchain. Se introduci qualche piccola modifica in una blockchain, il suo hash cambierà radicalmente. Questo è il motivo per cui il detto “Non puoi corrompere una Blockchain” è vero.

Usando la nostra Block Class

Costruiremo un’intera classe Blockchain in seguito, ma per ora utilizziamo la nostra classe Block per creare una catena di blocchi (Blockchain).

Nello stesso file creare un paio di transazioni composte da semplici stringhe memorizzate in variabili, ad esempio:

class GeekCoinBlock:
    ...

t1 = "Noah sends 5 GC to Mark"
t2 = "Mark sends 2.3 GC to James"
t3 = "James sends 4.2 GC to Alisson"
t4 = "Alisson sends 1.1 GC to Noah"

Naturalmente, GC si riferisce a GeekCoin

Ora costruisci il primo blocco della nostra Blockchain usando la classe GeekCoinBlock e stampa i suoi attributi. Tieni presente che il parametro previous_hash del blocco genesis (il primo blocco che precede gli altri blocchi) sarà sempre una stringa o un hash arbitrario, in questo caso “firstblock”.

block1 = GeekCoinBlock('firstblock', [t1, t2])

print(f"Block 1 data: {block1.block_data}")
print(f"Block 1 hash: {block1.block_hash}")

Quindi, facciamo lo stesso con il secondo blocco, ma passando l’hash del primo blocco come argomento previous_hash.

block2 = GeekCoinBlock(block1.block_hash, [t3, t4])

print(f"Block 2 data: {block2.block_data}")
print(f"Block 2 hash: {block2.block_hash}")

Eseguiamo e analizziamo l’output che otteniamo da questo pezzo di codice. Ancora una volta, digita nel tuo terminale:

❯ python main.py
Block 1 data: Noah sends 5 GC to Mark - Mark sends 2.3 GC to James - firstblock
Block 1 hash: 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 hash: 448c4306caf7f6937b0307f92f27fbea3bb73b3470363dee5026a1209dadcfa8

Per ora, vedi solo testo e alcuni hash di 64 caratteri, ma questo riprende praticamente il meccanismo di una Blockchain.

Inizi con un blocco di genesi, la base di tutti gli altri blocchi.

Chiunque può convalidare l’integrità della catena, ed è per questo che una Blockchain è un sistema così sicuro. Ad esempio, se modifichiamo leggermente il contenuto di una transazione, diciamo:

t2 = "Mark sends 2.3 GC to James" -> t2 = "Mark sends 3.2 GC to James" 

Vediamo un cambiamento drammatico nell’hash dei blocchi.

Block 1 data: Noah sends 5 GC to Mark - Mark sends 3.2 GC to James - firstblock
Block 1 hash: 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 hash: 569b977306ce88b53e001dca7ba00c03a51c60d6df4650e7657dcd136f2da0ac

Puoi vedere il progetto attuale su questo repository GitHub.

Codificare una Blockchain

Non è così intelligente basare l’integrità del nostro sistema su variabili codificate manualmente, quindi abbiamo bisogno di un altro approccio.

Abbiamo i blocchi. È ora di creare una classe che li unisca in una Blockchain.

Iniziamo eliminando le nostre transazioni precedenti e bloccando gli oggetti, quindi utilizzando il codice seguente.

# main.py

class Blockchain:
    def __init__(self):
        self.chain = []
        self.generate_genesis_block()

    def generate_genesis_block(self):
        self.chain.append(GeekCoinBlock("0", ['Genesis Block']))
    
    def create_block_from_transaction(self, transaction_list):
        previous_block_hash = self.last_block.block_hash
        self.chain.append(GeekCoinBlock(previous_block_hash, transaction_list))

    def display_chain(self):
        for i in range(len(self.chain)):
            print(f"Data {i + 1}: {self.chain[i].block_data}")
            print(f"Hash {i + 1}: {self.chain[i].block_hash}n")

    @property
    def last_block(self):
        return self.chain[-1]

Questo è di nuovo un enorme pezzo di codice. Analizziamo ogni parte:

  • self.chain — L’elenco in cui sono registrati tutti i blocchi. Possiamo accedere a ogni blocco tramite elenchi di indici.
  • generate_genesis_block — Aggiunge la genesi o il primo blocco alla catena. L’hash precedente del blocco è “0” e l’elenco delle transazioni è semplicemente “Genesis Block”.
  • create_block_from_transaction — Questo ci permette di aggiungere blocchi alla catena con solo un elenco di transazioni. Sarebbe molto fastidioso creare un blocco manualmente ogni volta che vogliamo registrare una transazione
  • display_chain — Stampa la catena di blocchi con un ciclo for
  • last_block — Una proprietà che ci consente di accedere all’ultimo elemento della catena. L’abbiamo usato sul metodo create_block_from_transaction.

Proviamo questa Blockchain.

# main.py

import hashlib

class GeekCoinBlock:
    ...


class Blockchain:
    ...

t1 = "George sends 3.1 GC to Joe"
t2 = "Joe sends 2.5 GC to Adam"
t3 = "Adam sends 1.2 GC to Bob"
t4 = "Bob sends 0.5 GC to Charlie"
t5 = "Charlie sends 0.2 GC to David"
t6 = "David sends 0.1 GC to Eric"

myblockchain = Blockchain()

myblockchain.create_block_from_transaction([t1, t2])
myblockchain.create_block_from_transaction([t3, t4])
myblockchain.create_block_from_transaction([t5, t6])

myblockchain.display_chain()

Ora, esegui il file main.py.

Data 1: Genesis Block - 0
Hash 1: 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e

Data 2: George sends 3.1 GC to Joe - Joe sends 2.5 GC to Adam - 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e
Hash 2: 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5

Data 3: Adam sends 1.2 GC to Bob - Bob sends 0.5 GC to Charlie - 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5
Hash 3: 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589

Data 4: Charlie sends 0.2 GC to David - David sends 0.1 GC to Eric - 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589
Hash 4: 869df2f03c9860767d35b30a46233fbeea89a3000ae5019d1491e3829d1ab929

Congratulazioni! 🙌 Hai appena creato una semplice Blockchain Python da zero.

Ora puoi rafforzare l’immutabilità Blockchain utilizzando getter e setter e implementare altre funzionalità come proof-of-work, mining o qualsiasi altro concetto che abbiamo spiegato nell’articolo sui fondamenti di Bitcoin Mining.

Conclusione

Blockchain è la tecnologia dietro Bitcoin, Etherium e ogni altra criptovaluta là fuori. In questo articolo, hai imparato come creare una Blockchain con Python utilizzando algoritmi hash come sha256, classi e oggetti.

La tua sfida è creare un sistema di mining e, perché no, implementarlo con un’API REST utilizzando framework come Django o Flask.

Molte persone stanno facendo fortuna con le criptovalute. Immagina cosa potresti fare se ne creassi uno da solo. 🤑

Continua a codificare! 👨‍💻