Bitcoin in Evoluzione: Differenze Chiave tra Indirizzi Legacy e Descriptor – Un’Analisi Pratica

In questo articolo, approfondiremo in modo pratico le divergenze introdotte dall’implementazione dell’aggiornamento descriptor a partire da Bitcoin Core 0.17.0 nel 2018. Se questa tematica ti è nuova, ti suggerisco di consultare questo articolo per una migliore comprensione.

Come consuetudine, gli esempi qui presentati possono essere replicati agevolmente tramite il nostro ambiente docker e il repository associato.

Con l’introduzione del descriptor, la procedura di utilizzo di dumpprivkey e la successiva firma delle transazioni raw mediante il comando signrawtransactionwithkey è stata abbandonata. Invece, il nodo si occupa della firma della transazione, facendo uso del comando signrawtransactionwithwallet.

In questo esempio, eseguiremo due transazioni: una utilizzando un address descriptor a un indirizzo legacy e successivamente dall’indirizzo legacy al descriptor. Per gestire entrambi i casi, creeremo due portafogli distinti e avvieremo il nodo con la direttiva -deprecatedrpc=create_bdb per poter utilizzare i comandi legacy.

È importante notare che questo esempio si basa sul nodo Bitcoin versione 26.

Riproduzione dell’Esempio:
Per replicare l’esperimento, segui questi passaggi:

  1. Clona il nostro repository.
   docker exec -it bitcoin-in-action-youtube zsh
  1. Entra nel container e spostati nella cartella “Video 13 – P2PKH legacy vs P2PKH descriptor”.
   ./main.sh

In Action!
I nostri esempi sono sempre basati sulla regtest, sia in questo contesto che nei nostri libri “Bitcoin In Action — SegWit, Bitcoin Script e Smart Contracts” e “Libro Bitcoin dalla teoria alla pratica“.

Per ulteriori approfondimenti e per immergerti nel mondo di Bitcoin, visita il nostro linktree.

Dopo aver avviato Docker Compose con il comando docker-compose up, entra nel container mediante:

docker exec -it bitcoin-in-action-youtube bash

Per prima cosa, arresta e pulisci completamente la regtest eseguendo il seguente comando:

bitcoin-cli stop && sleep 5 && rm -Rf $HOME/.bitcoin/regtest && bitcoind -deprecatedrpc=create_bdb && sleep 5

L’avvio con bitcoind -deprecatedrpc=create_bdb è necessario per abilitare l’uso dei comandi legacy.

Successivamente, crea due portafogli: uno legacy e uno descriptor, generando due indirizzi.

Iniziamo effettuando la transazione dal Descriptor al Legacy:

bitcoin-cli -named createwallet wallet_name="biaDescriptor"
bitcoin-cli -named createwallet wallet_name="biaLegacy" descriptors="false"

ADDR_DESC=`bitcoin-cli -rpcwallet="biaDescriptor" getnewaddress "" "legacy"`
ADDR_LEGACY=`bitcoin-cli -rpcwallet="biaLegacy" getnewaddress "" "legacy"`

Da notare che il termine “legacy” si riferisce agli indirizzi legacy e non ai portafogli legacy. Gli indirizzi legacy iniziano con 1 nella mainnet e con m/n nella testnet/regtest.

Successivamente, miniamo 101 blocchi per ottenere un reward da spendere:

bitcoin-cli generatetoaddress 101 $ADDR_DESC >> /dev/null

Recuperiamo le UTXO dall’indirizzo associato al portafoglio descriptor:

UTXO=`bitcoin-cli -rpcwallet="biaDescriptor" listunspent 1 101 '["'$ADDR_DESC'"]'`

Quando si gestiscono più portafogli, specifica con -rpcwallet a quale portafoglio ti stai riferendo. Immagazzina la lista degli UTXO nella variabile d’ambiente UTXO.

A questo punto, con Jq, memorizziamo le informazioni necessarie per effettuare la transazione:

TXID=$(echo $UTXO | jq -r '.[0].txid')
VOUT=$(echo $UTXO | jq -r '.[0].vout')
AMOUNT=$(echo $UTXO | jq -r '.[0].amount-0.009')
TOTAL_UTXO_AMOUNT=$(echo $UTXO | jq -r '.[0].amount')
TXIN=`bitcoin-cli getrawtransaction $TXID`

Ora che abbiamo i dati necessari, creiamo la transazione utilizzando il nuovo metodo introdotto con l’aggiornamento descriptor:

TX_DATA=$(bitcoin-cli createrawtransaction '[{"txid":"'$TXID'","vout":'$VOUT'}]' '[{"'$ADDR_LEGACY'":'$AMOUNT'}]')

Il metodo “signrawtransactionwithwallet” è stato inserito con l’aggiornamento descriptor. Ora firmiamo la transazione:

TX_SIGNED=$(bitcoin-cli -rpcwallet="biaDescriptor" signrawtransactionwithwallet $TX_DATA | jq -r '.hex')

In questo caso, non forniamo la chiave privata direttamente; sarà il metodo signrawtransactionwithwallet a occuparsi della firma. Il risultato viene memorizzato in TX_SIGNED.

Infine, inviamo la transazione:

bitcoin-cli sendrawtransaction $TX_SIGNED

Ora eseguiamo l’operazione inversa, dal legacy al descriptor. Poiché abbiamo già dei bitcoin spendibili grazie alla transazione appena creata, l’operazione sarà più veloce.

Recuperiamo le informazioni necessarie per creare la transazione:

UTXO=`bitcoin-cli -rpcwallet="biaLegacy" listunspent 1 101 '["'$ADDR_LEGACY'"]'`
TXID=$(echo $UTXO | jq -r '.[0].txid')
VOUT=$(echo $UTXO | jq -r '.[0].vout')
AMOUNT=$(echo $UTXO | jq -r '.[0].amount-0.009')
TOTAL_UTXO_AMOUNT=$(echo $UTXO | jq -r '.[0].amount')
SCRIPTPUBKEY=$(echo $UTXO | jq -r '.[0].scriptPubKey')
TXIN=`bitcoin-cli getrawtransaction $TXID`

Usiamo -rpcwallet="biaLegacy" in questo caso. Successivamente, otteniamo la chiave privata con il comando dumpprivkey:

PK=$(bitcoin-cli -rpcwallet="biaLegacy" dumpprivkey $ADDR_LEGACY)

Ora siamo pronti a creare la transazione:

TX_DATA=$(bitcoin-cli createrawtransaction '[{"txid":"'$TXID'","vout":'$VOUT'}]' '[{"'$ADDR_DESC'":'$AMOUNT'}]')

Firmiamo la transazione con la chiave privata e aggiungiamo lo scriptPubKey:

TX_SIGNED=$(bitcoin-cli signrawtransactionwithkey $TX_DATA '["'$PK'"]' '[{"txid":"'$TXID'","vout":'$VOUT',"scriptPubKey":"'$SCRIPTPUBKEY'"}]' | jq -r '.hex')

Infine, inviamo la transazione in broadcast:

TXSPENT=$(bitcoin-cli sendrawtransaction $TX_SIGNED)

Le due differenze principali sono:

  1. Non è più possibile ottenere la chiave privata tramite dumpprivkey dal portafoglio descriptor, che è ora la configurazione predefinita in Bitcoin. Tentare di eseguire il dump restituirà un errore:
   bitcoin-cli -rpcwallet="biaDescriptor" dumpprivkey $ADDR_DESC
   error code: -4
   error message:
   Only legacy wallets are supported by this command
  1. La seconda differenza riguarda il metodo per firmare la transazione: da signrawtransactionwithkey a signrawtransactionwithwallet.

In luce di queste significative differenze tra l’uso di indirizzi legacy e descriptor in Bitcoin, emergono nuove prospettive sulla gestione delle transazioni e sulla sicurezza delle chiavi private. L’evoluzione del protocollo continua a offrire agli utenti nuovi strumenti per interagire in modo sicuro e flessibile.

Per ulteriori dettagli e per approfondire il mondo di Bitcoin, visita il nostro linktree.