Modelli UTXO e basati su account · Lezione 2 di 6
Tipi di script e formati degli indirizzi
9 min di lettura
Un indirizzo è una codifica leggibile da una persona di uno script di blocco. Il suo formato indica all’analista quale tipo di script viene utilizzato, restringendo così il campo del software del wallet e del periodo in cui è stato creato; determina inoltre quali informazioni diventeranno pubbliche quando le monete verranno spese. Saper leggere correttamente i formati e conoscere ciò che multisig e Taproot nascondono o rivelano sono competenze fondamentali per chiunque lavori con dati UTXO.
Dallo script all’indirizzo
Gli indirizzi non compaiono sulla blockchain. Ciò che la blockchain memorizza è lo scriptPubKey; explorer e decoder lo convertono in un indirizzo da visualizzare. Ogni tipo di script standard corrisponde a una codifica e a un prefisso riconoscibile (gli script stessi sono analizzati nella lezione Transazioni Bitcoin grezze):
| Tipo di script | Pattern di scriptPubKey | Codifica | Prefisso mainnet | Lunghezza |
|---|---|---|---|---|
| P2PKH | OP_DUP OP_HASH160 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG | Base58Check, versione 0x00 | 1 | fino a 34 |
| P2SH | OP_HASH160 <20 bytes> OP_EQUAL | Base58Check, versione 0x05 | 3 | 34 |
| P2WPKH | OP_0 <20 bytes> | bech32 | bc1q | 42 |
| P2WSH | OP_0 <32 bytes> | bech32 | bc1q | 62 |
| P2TR | OP_1 <32 bytes> | bech32m | bc1p | 62 |
Le testnet usano prefissi diversi (m o n per P2PKH, 2 per P2SH, tb1 per SegWit), quindi un indirizzo testnet fuori posto in un dataset è facile da individuare. Alcuni script più datati, come gli output pay-to-public-key dell’era iniziale del mining e il multisig bare, non hanno affatto un indirizzo standard; gli explorer mostrano la chiave pubblica o un’etichetta sintetica, e i data warehouse possono lasciare vuota la colonna dell’indirizzo. Una query che filtra con address IS NOT NULL li esclude senza segnalarlo.
Base58Check
Gli indirizzi legacy usano Base58Check. Il codificatore prende un byte di versione, aggiunge il payload di 20 byte (un HASH160 di una chiave pubblica o di uno script), calcola un checksum e scrive il risultato usando un alfabeto di 58 caratteri che esclude i caratteri facilmente confondibili 0, O, I e l.
byte versione 00 -> P2PKH mainnet, quindi la stringa inizia con "1"
payload HASH160 di 20 byte di una chiave pubblica
checksum primi 4 byte di SHA-256(SHA-256(version || payload))
codificato Base58 dei 25 byte -> 1Fx3…9qLm
Ogni byte zero iniziale diventa un 1 iniziale, ed è per questo che ogni indirizzo P2PKH inizia con quel carattere. Base58Check distingue tra maiuscole e minuscole e il checksum di 4 byte fa sì che un indirizzo digitato in modo errato venga quasi sempre rifiutato. Per gli analisti, il byte di versione è la chiave di classificazione: 0x00 significa P2PKH, 0x05 significa P2SH e qualsiasi altro valore indica un’altra rete o un’altra moneta.
Bech32 e bech32m
Gli indirizzi SegWit nativi usano bech32, definito in BIP-173. Una stringa bech32 ha tre parti: una parte leggibile dall’uomo (bc per mainnet, tb per testnet), il separatore 1 e una parte dati scritta con un alfabeto di 32 caratteri che esclude 1, b, i e o. Il primo carattere dei dati è la versione witness (q è la versione 0, p è la versione 1), seguito dal witness program e da un checksum di 6 caratteri.
bc1q…7k3f 42 caratteri
hrp bc -> Bitcoin mainnet
separatore 1
versione q = 0 -> SegWit v0, quindi il checksum deve essere bech32
programma 20 byte -> P2WPKH (un programma di 32 byte sarebbe P2WSH)
checksum ultimi 6 caratteri
Bech32 usa solo lettere minuscole (le maiuscole sono ammesse per i codici QR, ma i decoder devono rifiutare l’uso misto di maiuscole e minuscole), può avere al massimo 90 caratteri e il suo checksum garantisce il rilevamento di qualsiasi errore che interessi fino a quattro caratteri. Ha un difetto: quando una stringa termina con p, inserire o eliminare caratteri q subito prima di quel p può lasciare valido il checksum. Per la versione 0, le lunghezze rigorose del programma (20 o 32 byte) rendono questo problema in gran parte innocuo. Le versioni successive ammettono altre lunghezze, quindi BIP-350 ha introdotto bech32m, identico tranne che per la costante usata nel checksum (0x2bc830a3 invece di 1). Gli indirizzi della versione 0 continuano a usare bech32; le versioni da 1 a 16, incluso Taproot, usano bech32m. Un decoder deve rifiutare un indirizzo della versione 1 con checksum bech32 e un indirizzo della versione 0 con checksum bech32m.
Indicazioni pratiche per le pipeline: non classificare basandosi soltanto su «inizia con bc1»; leggi il quarto carattere (q o p) e la lunghezza. I parser scritti prima del 2021 potrebbero rifiutare indirizzi bc1p validi o trattarli come errori, e una pipeline che elimina le righe non analizzabili sottostimerà l’attività Taproot senza alcun avviso.
Cosa rivela il formato sui wallet
I formati degli indirizzi rispecchiano la storia dei wallet e quindi forniscono informazioni sul software utilizzato:
1…(P2PKH): wallet datati, servizi che supportano solo il formato legacy e alcuni wallet di exchange di lunga data. Oggi, una nuova attività P2PKH spesso rimanda a software più datato o personalizzato.3…(P2SH): ambiguo finché non viene speso. Potrebbe trattarsi di un wallet multisig oppure di un wallet a chiave singola che usa SegWit annidato (P2WPKH racchiuso in P2SH), una configurazione predefinita comune intorno al 2017–2019.bc1q…(SegWit v0): il tipo di indirizzo di ricezione predefinito della maggior parte dei wallet mainstream degli ultimi anni. P2WSH (62 caratteri) di solito indica un multisig o un altro script personalizzato.bc1p…(Taproot): wallet che hanno adottato Taproot dopo la sua attivazione al blocco 709.632 nel novembre 2021, oltre agli strumenti per inscription e token che si basano su di esso.
Quando viene speso un output 3…, lo script di riscatto compare nell’input e risolve l’ambiguità: uno script di riscatto composto da 0014 seguito da 20 byte è un P2WPKH annidato, 0020 seguito da 32 byte è un P2WSH annidato e uno che termina con ae (OP_CHECKMULTISIG) è un multisig classico.
Anche i tipi di script possono combinarsi nelle transazioni. Se tutti gli input sono P2WPKH e i due output sono un P2WPKH e un P2SH, è più probabile che l’output corrispondente al tipo degli input sia il resto. Il tipo di indirizzo è una delle diverse impronte del wallet, insieme alla versione della transazione, al lock time e ai valori di sequence, nonché alla codifica della firma; la lezione Euristiche per il rilevamento del resto spiega come combinarli e quanta fiducia attribuire loro.
Multisig e la sua impronta
Il multisig classico usa OP_CHECKMULTISIG all’interno di uno script di riscatto P2SH o di uno script witness P2WSH. La policy rimane nascosta finché i fondi non vengono spesi (sulla blockchain è presente solo un hash), ma diventa interamente pubblica al primo spend. Un input P2WSH 2-su-3 decodificato si presenta così:
witness[0] (empty) -- elemento fittizio richiesto da OP_CHECKMULTISIG
witness[1] 3044…01 -- prima firma (DER, byte sighash 01)
witness[2] 3045…01 -- seconda firma
witness[3] 5221…21…21…53ae -- OP_2 <key1> <key2> <key3> OP_3 OP_CHECKMULTISIG
Nello script witness, 52 è OP_2 (sono richieste due firme), ciascun 21 introduce una chiave pubblica compressa di 33 byte, 53 è OP_3 (tre chiavi) e ae è OP_CHECKMULTISIG. Una sola spesa rivela la soglia, tutte e tre le chiavi pubbliche e quali due chiavi hanno firmato.
Questa impronta fornisce prove preziose. Spesso i custodi adottano policy distintive (2-su-3, 3-su-5) per il cold storage, e la stessa chiave pubblica presente in molti script multisig collega quegli indirizzi a un unico titolare della chiave con molta più affidabilità rispetto alle euristiche comportamentali. Molti wallet ordinano le chiavi in ordine lessicografico (BIP-67), cosa che costituisce di per sé una piccola impronta.
Taproot e privacy
Taproot combina tre elementi. BIP-340 definisce le firme Schnorr sulla stessa curva secp256k1: firme fisse di 64 byte e chiavi pubbliche «x-only» di 32 byte. BIP-341 definisce l’output: OP_1 seguito da una chiave di 32 byte Q, dove Q = P + t·G, P è una chiave interna e il tweak t si impegna su P e sulla radice Merkle di un albero opzionale di script alternativi. BIP-342 definisce le regole degli script all’interno di quell’albero, sostituendo OP_CHECKMULTISIG con OP_CHECKSIGADD.
Un output Taproot può essere speso in due modi, che rivelano quantità di informazioni molto diverse:
| Tipo di spesa | Witness | Cosa apprende l’analista |
|---|---|---|
| Multisig P2WSH 2-su-3 | Due firme più lo script completo | Soglia, tutte le chiavi pubbliche, quali chiavi hanno firmato |
| Key path P2TR | Una firma di 64 byte (65 con un byte sighash esplicito) | Nulla sulla policy |
| Script path P2TR | Script foglia, i suoi input, control block di 33 + 32m byte | L’unica condizione usata, la sua profondità m nell’albero, la chiave interna |
Nel key path, un wallet a chiave singola, un gruppo n-su-n che usa l’aggregazione delle chiavi (MuSig2) e uno schema di firma a soglia producono tutti lo stesso risultato: una firma per una chiave. Lo script path rivela solo la foglia effettivamente utilizzata; i rami non usati rimangono nascosti, anche se la lunghezza del percorso Merkle rivela qualcosa sulla dimensione dell’albero, come osserva lo stesso BIP-341, e può aiutare nel clustering.
Per gli analisti, Taproot elimina l’impronta multisig descritta sopra ogni volta che viene usato il key path, rendendo invisibili le policy di custodia. Non nasconde gli importi, il grafo delle transazioni o le tempistiche e, sebbene l’adozione sia modesta, il formato bc1p stesso è un elemento distintivo. Le spese tramite script path includono anche inscription: dal 2023, witness di grandi dimensioni con un «involucro» OP_FALSE OP_IF … OP_ENDIF sono stati usati per incorporare immagini e dati di token, uno schema da escludere dall’analisi dei pagamenti.
Focus sull'esame: associazione di prefissi e lunghezze ai tipi di script (1, 3, bc1q a 42 e 62 caratteri, bc1p a 62); struttura di Base58Check (byte di versione, checksum di 4 byte basato su doppio SHA-256, versione 0x00 rispetto a 0x05); struttura di bech32 (hrp, separatore 1, carattere della versione witness, checksum di 6 caratteri) e passaggio a bech32m introdotto da BIP-350 per la versione witness 1 e successive; perché «inizia con bc1» non è un criterio di classificazione; come la spesa di un output P2SH risolve l’ambiguità tra SegWit annidato e multisig; cosa rivela una spesa multisig classica; differenza tra spese Taproot key path e script path, Q = P + t·G e control block di 33 + 32m byte; cosa nasconde Taproot e cosa no.