Introduzione a Ethereum per sviluppatori Python, parte 1
Quindi, hai sentito parlare di questo Ethereum e sei pronto ad avventurarti nella tana del bianconiglio? Questo articolo coprirà rapidamente alcune basi della blockchain, per poi farti interagire con un nodo Ethereum simulato: leggendo i dati dei blocchi, controllando i saldi degli account e inviando transazioni. Lungo il percorso, evidenzieremo le differenze tra i modi tradizionali di creare app e questo nuovo paradigma decentralizzato.
Prerequisiti (leggeri)
Questo articolo aspira a essere accessibile a un'ampia gamma di sviluppatori. Saranno coinvolti strumenti Python, ma sono solo un veicolo per le idee: nessun problema se non sei uno sviluppatore Python. Tuttavia, farò solo alcune supposizioni su ciò che già sai, in modo da poter passare rapidamente alle parti specifiche di Ethereum.
Presupposti:
- Sai muoverti in un terminale,
- Hai scritto qualche riga di codice Python,
- La versione 3.6 o superiore di Python è installata sulla tua macchina (l'uso di un ambiente virtuale (opens in a new tab) è fortemente incoraggiato), e
- hai usato
pip, l'installatore di pacchetti di Python. Ancora una volta, se una di queste condizioni non è vera, o non hai intenzione di riprodurre il codice in questo articolo, probabilmente potrai comunque seguire senza problemi.
Blockchain, in breve
Ci sono molti modi per descrivere Ethereum, ma al suo centro c'è una blockchain. Le blockchain sono composte da una serie di blocchi, quindi iniziamo da lì. In termini più semplici, ogni blocco sulla blockchain di Ethereum è solo un insieme di metadati e un elenco di transazioni. In formato JSON, si presenta più o meno così:
1{2 "number": 1234567,3 "hash": "0xabc123...",4 "parentHash": "0xdef456...",5 ...,6 "transactions": [...]7}Ogni blocco ha un riferimento al blocco che lo ha preceduto; il parentHash è semplicemente l'hash del blocco precedente.
Una blockchain è essenzialmente una lista concatenata; ogni blocco ha un riferimento al blocco precedente.
Questa struttura dati non è una novità, ma le regole (ovvero i protocolli peer-to-peer) che governano la rete lo sono. Non c'è un'autorità centrale; la rete di peer deve collaborare per sostenere la rete e competere per decidere quali transazioni includere nel blocco successivo. Quindi, quando vuoi inviare del denaro a un amico, dovrai trasmettere quella transazione alla rete, per poi aspettare che venga inclusa in un blocco imminente.
L'unico modo per la blockchain di verificare che il denaro sia stato veramente inviato da un utente all'altro è utilizzare una valuta nativa (cioè creata e governata da) quella blockchain. In Ethereum, questa valuta si chiama ether e la blockchain di Ethereum contiene l'unico registro ufficiale dei saldi degli account.
Un nuovo paradigma
Questo nuovo stack tecnologico decentralizzato ha generato nuovi strumenti per sviluppatori. Tali strumenti esistono in molti linguaggi di programmazione, ma noi li guarderemo attraverso la lente di Python. Per ribadire: anche se Python non è il tuo linguaggio preferito, non dovrebbe essere un grosso problema seguire.
Gli sviluppatori Python che vogliono interagire con Ethereum probabilmente ricorreranno a Web3.py (opens in a new tab). Web3.py è una libreria che semplifica notevolmente il modo in cui ti connetti a un nodo Ethereum, per poi inviare e ricevere dati da esso.
I client Ethereum possono essere configurati per essere raggiungibili tramite IPC (opens in a new tab), HTTP o Websocket, quindi Web3.py dovrà rispecchiare questa configurazione. Web3.py si riferisce a queste opzioni di connessione come provider. Dovrai scegliere uno dei tre provider per collegare l'istanza di Web3.py al tuo nodo.
Configura il nodo Ethereum e Web3.py per comunicare tramite lo stesso protocollo, ad es. IPC in questo diagramma.
Una volta che Web3.py è configurato correttamente, puoi iniziare a interagire con la blockchain. Ecco un paio di esempi di utilizzo di Web3.py come anteprima di ciò che verrà:
1# leggi i dati del blocco:2w3.eth.get_block('latest')34# invia una transazione:5w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})Installazione
In questa guida, lavoreremo solo all'interno di un interprete Python. Non creeremo directory, file, classi o funzioni.
$ sono destinati a essere eseguiti nel terminale. (Non digitare il $, indica solo l'inizio della riga.)Per prima cosa, installa IPython (opens in a new tab) per avere un ambiente user-friendly in cui esplorare. IPython offre il completamento con il tasto Tab, tra le altre funzionalità, rendendo molto più facile vedere cosa è possibile fare all'interno di Web3.py.
pip install ipythonWeb3.py è pubblicato con il nome web3. Installalo in questo modo:
pip install web3Un'ultima cosa: più tardi simuleremo una blockchain, il che richiede un paio di dipendenze in più. Puoi installarle tramite:
pip install 'web3[tester]'Sei pronto per iniziare!
Nota: Il pacchetto web3[tester] funziona fino a Python 3.10.xx
Avviare una sandbox
Apri un nuovo ambiente Python eseguendo ipython nel tuo terminale. Questo è paragonabile all'esecuzione di python, ma è dotato di più funzionalità.
ipythonQuesto stamperà alcune informazioni sulle versioni di Python e IPython che stai eseguendo, dopodiché dovresti vedere un prompt in attesa di input:
1In [1]:Ora stai guardando una shell Python interattiva. Essenzialmente, è una sandbox in cui giocare. Se sei arrivato fin qui, è il momento di importare Web3.py:
1In [1]: from web3 import Web3Introduzione al modulo Web3
Oltre a essere un gateway per Ethereum, il modulo Web3 (opens in a new tab) offre alcune funzioni di utilità. Esploriamone un paio.
In un'applicazione Ethereum, avrai comunemente bisogno di convertire le denominazioni di valuta. Il modulo Web3 fornisce un paio di metodi di supporto proprio per questo: from_wei (opens in a new tab) e to_wei (opens in a new tab).
Nota: I computer sono notoriamente pessimi nel gestire la matematica decimale. Per aggirare questo problema, gli sviluppatori spesso memorizzano gli importi in dollari in centesimi. Ad esempio, un articolo con un prezzo di $5.99 potrebbe essere memorizzato nel database come 599.
Un modello simile viene utilizzato quando si gestiscono transazioni in ether. Tuttavia, invece di due cifre decimali, l'ether ne ha 18! La denominazione più piccola di ether si chiama wei, quindi questo è il valore specificato quando si inviano transazioni.
1 ether = 1000000000000000000 wei
1 wei = 0.000000000000000001 ether
Prova a convertire alcuni valori da e verso wei. Nota che ci sono nomi per molte delle denominazioni (opens in a new tab) tra ether e wei. Una delle più note tra queste è il gwei, poiché è spesso il modo in cui vengono rappresentate le commissioni della transazione.
1In [2]: Web3.to_wei(1, 'ether')2Out[2]: 100000000000000000034In [3]: Web3.from_wei(500000000, 'gwei')5Out[3]: Decimal('0.5')Altri metodi di utilità sul modulo Web3 includono convertitori di formato dati (ad es., toHex (opens in a new tab)), helper per gli indirizzi (ad es., isAddress (opens in a new tab)) e funzioni di hash (ad es., keccak (opens in a new tab)). Molti di questi verranno trattati più avanti nella serie. Per visualizzare tutti i metodi e le proprietà disponibili, utilizza l'autocompletamento di IPython digitando Web3. e premendo due volte il tasto Tab dopo il punto.
Parlare con la catena
I metodi di utilità sono adorabili, ma passiamo alla blockchain. Il passo successivo è configurare Web3.py per comunicare con un nodo Ethereum. Qui abbiamo l'opzione di utilizzare i provider IPC, HTTP o Websocket.
Non seguiremo questa strada, ma un esempio di flusso di lavoro completo utilizzando l'HTTP Provider potrebbe assomigliare a questo:
- Scarica un nodo Ethereum, ad es. Geth (opens in a new tab).
- Avvia Geth in una finestra del terminale e attendi che sincronizzi la rete. La porta HTTP predefinita è
8545, ma è configurabile. - Dì a Web3.py di connettersi al nodo tramite HTTP, su
localhost:8545.w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545')) - Usa l'istanza
w3per interagire con il nodo.
Sebbene questo sia un modo "reale" per farlo, il processo di sincronizzazione richiede ore ed è inutile se desideri solo un ambiente di sviluppo. Web3.py espone un quarto provider per questo scopo, l'EthereumTesterProvider. Questo provider di test si collega a un nodo Ethereum simulato con permessi rilassati e valuta finta con cui giocare.
L'EthereumTesterProvider si connette a un nodo simulato ed è comodo per ambienti di sviluppo rapidi.
Quel nodo simulato si chiama eth-tester (opens in a new tab) e lo abbiamo installato come parte del comando pip install web3[tester]. Configurare Web3.py per utilizzare questo provider di test è semplice come:
1In [4]: w3 = Web3(Web3.EthereumTesterProvider())Ora sei pronto per navigare sulla catena! Non è una cosa che si dice. Me la sono appena inventata. Facciamo un rapido tour.
Il tour rapido
Prima di tutto, un controllo di integrità:
1In [5]: w3.is_connected()2Out[5]: TruePoiché stiamo utilizzando il provider di test, questo non è un test molto prezioso, ma se fallisce, è probabile che tu abbia digitato qualcosa di sbagliato durante l'istanziazione della variabile w3. Ricontrolla di aver incluso le parentesi interne, ovvero Web3.EthereumTesterProvider().
Tappa del tour n. 1: account
Per comodità, il provider di test ha creato alcuni account e li ha precaricati con ether di test.
Per prima cosa, vediamo un elenco di quegli account:
1In [6]: w3.eth.accounts2Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',3 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',4 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]Se esegui questo comando, dovresti vedere un elenco di dieci stringhe che iniziano con 0x. Ognuna è un indirizzo pubblico ed è, in qualche modo, analoga al numero di conto di un conto corrente. Forniresti questo indirizzo a qualcuno che volesse inviarti ether.
Come accennato, il provider di test ha precaricato ciascuno di questi account con alcuni ether di test. Scopriamo quanto c'è nel primo account:
1In [7]: w3.eth.get_balance(w3.eth.accounts[0])2Out[7]: 1000000000000000000000000Sono un sacco di zeri! Prima di andare a ridere fino alla finta banca, ricorda quella lezione sulle denominazioni di valuta di prima. I valori in ether sono rappresentati nella denominazione più piccola, i wei. Convertilo in ether:
1In [8]: w3.from_wei(1000000000000000000000000, 'ether')2Out[8]: Decimal('1000000')Un milione di ether di test: non è affatto male.
Tappa del tour n. 2: dati del blocco
Diamo un'occhiata allo stato di questa blockchain simulata:
1In [9]: w3.eth.get_block('latest')2Out[9]: AttributeDict({3 'number': 0,4 'hash': HexBytes('0x9469878...'),5 'parentHash': HexBytes('0x0000000...'),6 ...7 'transactions': []8})Vengono restituite molte informazioni su un blocco, ma ci sono solo un paio di cose da sottolineare qui:
- Il numero del blocco è zero, indipendentemente da quanto tempo fa hai configurato il provider di test. A differenza della vera rete Ethereum, che aggiunge un nuovo blocco ogni 12 secondi, questa simulazione aspetterà finché non le darai del lavoro da fare.
transactionsè un elenco vuoto, per lo stesso motivo: non abbiamo ancora fatto nulla. Questo primo blocco è un blocco vuoto, solo per dare il via alla catena.- Nota che il
parentHashè solo un mucchio di byte vuoti. Questo significa che è il primo blocco della catena, noto anche come blocco genesi.
Tappa del tour n. 3: transazioni
Siamo bloccati al blocco zero finché non c'è una transazione in sospeso, quindi diamogliene una. Invia alcuni ether di test da un account all'altro:
1In [10]: tx_hash = w3.eth.send_transaction({2 'from': w3.eth.accounts[0],3 'to': w3.eth.accounts[1],4 'value': w3.to_wei(3, 'ether'),5 'gas': 210006})Questo è in genere il punto in cui aspetteresti diversi secondi affinché la tua transazione venga inclusa in un nuovo blocco. L'intero processo si svolge più o meno così:
- Invia una transazione e conserva l'hash della transazione. Finché il blocco contenente la transazione non viene creato e trasmesso, la transazione è "in sospeso".
tx_hash = w3.eth.send_transaction({ … }) - Attendi che la transazione venga inclusa in un blocco:
w3.eth.wait_for_transaction_receipt(tx_hash) - Continua la logica dell'applicazione. Per visualizzare la transazione andata a buon fine:
w3.eth.get_transaction(tx_hash)
Il nostro ambiente simulato aggiungerà la transazione in un nuovo blocco all'istante, in modo da poter visualizzare immediatamente la transazione:
1In [11]: w3.eth.get_transaction(tx_hash)2Out[11]: AttributeDict({3 'hash': HexBytes('0x15e9fb95dc39...'),4 'blockNumber': 1,5 'transactionIndex': 0,6 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',7 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',8 'value': 3000000000000000000,9 ...10})Mostra tuttoVedrai alcuni dettagli familiari qui: i campi from, to e value dovrebbero corrispondere agli input della nostra chiamata send_transaction. L'altro dettaglio rassicurante è che questa transazione è stata inclusa come prima transazione ('transactionIndex': 0) all'interno del blocco numero 1.
Possiamo anche verificare facilmente il successo di questa transazione controllando i saldi dei due account coinvolti. Tre ether dovrebbero essersi spostati da uno all'altro.
1In [12]: w3.eth.get_balance(w3.eth.accounts[0])2Out[12]: 99999699997900000000000034In [13]: w3.eth.get_balance(w3.eth.accounts[1])5Out[13]: 1000003000000000000000000Il secondo sembra a posto! Il saldo è passato da 1.000.000 a 1.000.003 ether. Ma cosa è successo al primo account? Sembra aver perso poco più di tre ether. Ahimè, niente nella vita è gratis e l'utilizzo della rete pubblica di Ethereum richiede di compensare i propri peer per il loro ruolo di supporto. Una piccola commissione della transazione è stata detratta dall'account che ha inviato la transazione: questa commissione è la quantità di gas bruciato (21000 unità di gas per un trasferimento di ETH) moltiplicata per una commissione di base che varia in base all'attività della rete più una mancia che va al validatore che include la transazione in un blocco.
Maggiori informazioni sul gas
E respira
Siamo stati su questo per un po', quindi questo sembra un buon posto come un altro per fare una pausa. La tana del bianconiglio continua e continueremo a esplorare nella seconda parte di questa serie. Alcuni concetti in arrivo: connessione a un nodo reale, contratti intelligenti e token. Hai domande di follow-up? Fammelo sapere! Il tuo feedback influenzerà la direzione che prenderemo da qui in poi. Le richieste sono benvenute tramite Twitter (opens in a new tab).
Ultimo aggiornamento della pagina: 6 febbraio 2025


