HomeCriptovaluteBitcoinBitcoin: script delle transazioni e linguaggio Script. Guida parte 7

Bitcoin: script delle transazioni e linguaggio Script. Guida parte 7

Questo articolo, in cui si parlerà di Bitcoin e script, il settimo di una serie di approfondimenti sulla parte più tecnica di Bitcoin, continuando una guida pensata per entrare gradualmente nella “tana del bianconiglio” del mondo blockchain.

A livello bibliografico è d’obbligo citare il testo “Mastering Bitcoin” di Andreas Antonopoulos, dal quale sono state tratte le immagini. 

Chi fosse interessato ad approfondire questi temi, con o senza integrazione delle dinamiche legate al codice, può trovare supporto nei corsi formativi e nella attività consulenziali erogate da Bcademy. Questo il prossimo corso modulare, da curiosi ad aspiranti developer con lunghezza variabile, in partenza ll’1 ottobre a Milano.

Bitcoin: Script delle transazioni e linguaggio Script

Il linguaggio di script delle transazioni bitcoin si chiama script e gli script di blocco di un UTXO e sblocco sono scritti in questo linguaggio: quando una transazione è validata gli script di sblocco di ogni input sono eseguiti insieme al corrispondente script di blocco per vedere se questo soddisfa le condizioni di spesa.

Turing incompleteness. Il linguaggio di script di bitcoin contiene operatori ma è arbitrariamente delimitato: non ci sono loop o complesse funzionalità di controllo del flusso oltre al controllo del flusso condizionale, ergo il linguaggio non è Turing complete.

Stateless verification. Nel linguaggio di script delle transazioni bitcoin non ci sono stati preliminari o successivi all’esecuzione di uno script: le informazioni necessarie per eseguire uno script sono contenute nello stesso script, che eseguirà in maniera prevedibile, nello stesso modo, su qualsiasi sistema (ci sono operatori che possono accedere a informazioni esterne: CSV può controllare se una tx in input è stata confermata da x blocchi; CLTV può controllare il campo nLockTime della tx).

Costruzione dello script (blocco e sblocco). Il motore di validazione delle transazioni (tx) Bitcoin si basa su due tipi di script per validare le transazioni: uno script di blocco e uno script di sblocco.

Uno script di blocco è una condizione di spesa messa su un output. Lo script di blocco è chiamato scriptPubKey, perché contiene una chiave pubblica o un indirizzo bitcoin (public key hash).

Uno script di sblocco è uno script che risolve (o soddisfa) le condizioni poste su uno script di blocco e permette di spendere (o consumare) l’output. Gli script di sblocco sono parte di ogni input di tx: nella maggior parte dei casi contengono una firma digitale prodotta dalle chiavi private del wallet. Gli script di sblocco sono chiamati scriptSig, perché di solito contengono una firma digitale.

Ogni nodo Bitcoin valida le transazioni eseguendo entrambi gli script (blocco e sblocco). Ogni input contiene uno script di sblocco e si riferisce ad un precedente UTXO. Il software di validazione copia lo script di sblocco, recupera l’UTXO a cui fa riferimento l’input, e copia lo script di blocco da quell’UTXO. Gli script di sblocco e di blocco sono eseguiti in sequenza: l’input è valido se lo script di sblocco soddisfa le condizioni di blocco; tutti gli input sono validati indipendentemente, come parte di una generale validazione delle transazioni.

The script execution stack. Il linguaggio di script di Bitcoin è chiamato stack-based perché usa stack, una struttura dati semplice (pila). Essa permette due operazioni: push e pop. Push aggiunge un oggetto in cima alla pila, pop rimuove l’oggetto in cima alla pila.

Il linguaggio di script esegue lo script da sinistra a destra.

  1. I numeri (dati costanti) sono spinti (“pushati”) sulla pila.
  2. Gli operatori “pushano” o “poppano” uno o più parametri dalla pila, agendo su essi e possono “pushare” un risultato sulla pila. OP_ADD toglie (pop) due oggetti dalla pila, li somma e spinge (push) la somma in cima alla pila.
  3. Operatori di condizione (conditional operators) valutano una determinata condizione, producendo un risultato (booleano) di TRUE (1) o FALSE (0).
  4. L’operatore OP_EQUAL toglie due oggetti dalla pila e inserisce TRUE se essi sono uguali, FALSE se differenti.

Le transazioni sono valide se il valore finale è TRUE o qualsiasi altro valore diverso da 0; le transazioni sono invalide se il valore in cima è FALSE o se l’esecuzione dello script è fermata da un operatore come OP_VERIFY, OP_RETURN o un conditional terminator come OP_ENDIF.

Nel client originale (Satoshi Client), gli script di sblocco e blocco erano concatenati ed eseguiti in sequenza. Dopo il 2010 (per ragioni di sicurezza) gli script sono eseguiti separatamente: prima viene eseguito lo script di sblocco, poi la main stack è copiata e viene eseguito lo script di blocco. Se il risultato è TRUE, lo script di sblocco ha avuto successo nel risolvere le condizioni imposte dallo script di blocco, ergo l’input è valido per spendere gli UTXO.

Pay-to-Public-Key-Hash (P2PKH). La maggior parte delle transazioni processate dal network sono script P2PKH. Questi output contengono uno script di blocco che blocca l’output all’hash di una chiave pubblica (ergo un indirizzo bitcoin). Un output bloccato con uno script P2PKH può essere sbloccato (speso) presentando una chiave pubblica e una firma digitale creata dalla corrispondente chiave privata. Un tale output avrebbe uno script di blocco in questa forma:

OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG (dove l’hash della chiave pubblica è uguale all’indirizzo bitcoin senza il codice Base58Check). Questo script di blocco può essere soddisfatto con uno script di sblocco nella forma:

<Cafe Signature> <Cafe Public Key> e i due script insieme formerebbero la seguente combinazione:

<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

Nel concreto, partendo dallo script:

<sig> <PubK> DUP HASH160 <PubKHash> EQUALVERIFY CHECKSIG

Primo: la firma passa in cima alla pila (pila, dall’alto: <sig>)

 <PubK> DUP HASH160 <PubKHash> EQUALVERIFY CHECKSIG

Secondo: la chiave pubblica passa in cima alla pila (pila, dall’alto: <PubK>  <sig>)

DUP HASH160 <PubKHash> EQUALVERIFY CHECKSIG

Terzo: l’operatore DUP duplica l’oggetto in cima alla pila e pone il risultato on top (pila, dall’alto: <PubK> <PubK>  <sig>)

HASH160 <PubKHash> EQUALVERIFY CHECKSIG

Quarto: l’operatore HASH160  “hasha” l’oggetto in cima alla pila (prima con SHA256 e poi con RIPEMD160) e pone il risultato on top (pila, dall’alto: <PubKHash> <PubK>  <sig>)

<PubKHash> EQUALVERIFY CHECKSIG

Quinto: il valore PubKHash passa on top (pila, dall’alto: <PubKHash> <PubKHash> <PubK>  <sig>)

EQUALVERIFY CHECKSIG

Sesto: l’operatore EQUALVERIFY compara i due PubKHash eliminandoli dalla pila in caso di uguaglianza (pila, dall’alto: <PubK>  <sig>)

CHECKSIG

Settimo: l’operatore CHECKSIG controlla il match tra la chiave pubblica on top e la firma, rimuovendole e “pushando” il valore TRUE se “matchano” (pila, dall’alto: TRUE)

Firme digitali (ECDSA). L’algoritmo per le firme digitali usato in Bitcoin è Elliptic Curve Digital Signature Algorithm, o ECDSA, basato sulla matematica delle curve ellittiche per l’accoppiamento tra chiave privata e pubbliche, che utilizza le funzioni di script OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_CHECKMULTISIG, e OP_CHECKMULTISIGVERIFY.

Una firma digitale è uno schema matematico  consistente in due parti:

  • un algoritmo per creare la firma da un messaggio, utilizzando una chiave privata (la chiave che firma);
  • un algoritmo che permette a chiunque di verificare la firma, dati il messaggio e una chiave pubblica.

Nell’implementazione dell’algoritmo ECDSA in Bitcoin il messaggio che viene firmato è la transazione, o meglio un hash di uno specifico sottoinsieme di dati nella transazione. La chiave che firma è la chiave privata, e il risultato è la firma:

\(\(Sig = F_{sig}(F_{hash}(m), dA)\)\)

dove:

  • dA is the signing private key (è la chiave privata che firma)
  • m is the transaction, or parts of it (è la transazione, o parte di essa)
  • Fhash is the hashing function (è la funzione di hashing)
  • Fsig is the signing algorithm (è l’algoritmo che firma)
  • Sig is the resulting signature (è la firma risultante

La funzione Fsig crea una firma Sig che è composta di due valori, R e S, che una volta calcolati sono “serializzati” in uno schema di codifica chiamato Distinguished Encoding Rules, or DER. Ad esempio:

3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e381301

Questa firma è un byte-stream serializzato dei valori di R e S prodotti da un wallet per provare il possesso della chiave privata per spendere un output. Il format is serializzazione consiste di 9 elementi:

  • “30”—indicating the start of a (indica l’inizio della sequenza DER)
  • ”45”—the length of the sequence (la lunghezza della sequenza, 69 bytes)
  • “02”—an integer value follows (indica che un intero segue)
  • “21”—the length of the integer (la lunghezza dell’intero, 33 bytes)
  • R—00884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb
  • “02”—another integer follows
  • “20”—the length of the integer (32 bytes)
  • S—4b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813
  • “01” A suffix indicating the type of hash used (un suffisso che indica il tipo di hash usato SIGHASH_ALL)

Verificare la firma. Per verificare la firma occorre avere le firme R e S, la transazione serializzata e la chiave pubblica (corrispondente): l’algoritmo di verifica prende il messaggio (un hash della transazione o una sua parte), la chiave pubblica del firmatario e la firma (i valori R e S), e riporta TRUE se la firma è valida per il messaggio e la chiave pubblica.

Indirizzi bitcoin, saldi e altre astrazioni

Le transazioni non contengono indirizzi bitcoin “in sé”, ma operano attraverso script di blocco e sblocco. Ergo non si dovrebbe concretamente parlare di saldi (balance) se non indirettamente, poiché ogni wallet li mostra: si tratta di astrazioni che derivano semplicemente dalle componenti primitive delle transazioni.

Alessio Salvetti
Alessio Salvetti
Co-founder di Bcademy e board member (VP), Alessio è partner e board member di Impact Hub Trentino, uno dei 102 nodi del network mondiale. Dopo un'esperienza come docente di filosofia, abbandona l’insegnamento per coordinare un team di ricerca sui temi della connessione tra neuroscienze ed economia, prima di dedicarsi alla vera e propria creazione d’impresa. Business developer e consulente per numerose startup, bitcoiner per passione ed esperto di modeling e lean startup, è co-founder di Inbitcoin e responsabile per l’erogazione dei prodotti di Bcademy (CPO).
RELATED ARTICLES

MOST POPULARS

GoldBrick