Comincia con questa domanda un post che ho scritto il 23 ottobre di quest’anno sul gruppo Bitcoin Italia. Un interrogativo che chiunque potrebbe porsi, specie chi è già solito effettuare transazioni digitali classiche e non conosce bene Bitcoin.

La risposta che solitamente viene data è: “Assolutamente no! Le transazioni Bitcoin non sono reversibili.

Questo è la conclusione a cui arriviamo se ad esempio leggiamo il whitepaper di Satoshi Nakamoto:

“Nonostante il sistema (attuale, di scambi digitali) funzioni abbastanza bene per la maggior parte delle transazioni, esso soffre ancora delle debolezze intrinseche di un modello basato sulla fiducia. Transazioni totalmente irreversibili non sono realmente possibili, dal momento che le istituzioni finanziarie non possono evitare le dispute di mediazione.”

Bitcoin nasce dunque in alternativa a un sistema centralizzato che per funzionare richiede fiducia e che, come tradeoff, contempla la possibilità di avere transazioni totalmente reversibili.

Da qui si diffonde l’idea che le transazioni di Bitcoin siano irreversibili; concetto che poi, purtroppo, si è esteso alla cosiddetta blockchain, tant’è che ancora oggi, quando questo termine viene utilizzato, lo si fa spesso in riferimento a fantomatiche proprietà della stessa che renderebbero i dati “inseriti nella blockchain” del tutto al riparo da manomissioni.

Per iniziare a fornire una risposta alla domanda “Può una transazione Bitcoin essere cancellata?”, bisognerebbe avere ben in mente come queste transazioni avvengono.

Ipotizziamo che due utenti, Alice e Bob, vogliano scambiarsi dei bitcoin.

Alice ha necessità di inviare 1 bitcoin a Bob, e dunque chiede a quest’ultimo un indirizzo pubblico. Bob invia l’indirizzo ad Alice, questa lo inserisce all’interno del suo portafoglio e paga, di fatto trasmettendo alla rete la sua transazione composta da 1 bitcoin più le commissioni di mining (mining fee). Bob vede comparire quasi istantaneamente questa transazione nel suo portafoglio, indicata come “in arrivo” (pending).

Un utente poco pratico potrebbe pensare che la transazione abbia avuto luogo e i fondi siano definitivamente in possesso di Bob, ma questa osservazione è errata.

La transazione di Alice verso Bob viene propagata, a poco a poco, a partire dal nodo di Alice, o dal nodo a cui è connesso direttamente il portafoglio di Alice, a tutti i nodi della rete, e memorizzata temporaneamente al loro interno in quella che viene chiamata Mempool, una memoria temporanea appunto. Ogni nodo della rete ha una sua Mempool.

La transazione però è stata finora solamente propagata, non confermata dalla rete.
La conferma della validità della transazione verrà data dall’inserimento della stessa all’interno di un blocco di transazioni e di quest’ultimo all’interno della catena di blocchi, vale a dire la blockchain.

La validazione è il più importante processo che avviene all’interno di Bitcoin: senza di esso le regole monetarie potrebbero venire spazzate via, si potrebbe avere a che fare con bitcoin “falsi” perché non seguono il Consenso e il network perderebbe la capacità di funzionare senza unità di controllo centrale perché richiederebbe un sistema di validazione atto ad evitare il double spending.

Solo quando la transazione di Alice viene inserita in un blocco e questo diviene un anello della catena di blocchi di transazioni di Bitcoin, allora Bob può essere (relativamente) sicuro di essere il possessore finale di quella quantità di bitcoin. Può dunque una transazione non ancora confermata dalla rete essere “cancellata”?

La risposta a questa domanda è: “Certo che sì!”. Ma in che modo?

Esistono principalmente cinque modi per “cancellare” una transazione, di cui tre indiretti e due diretti. Andremo qui ad analizzarli.

Transaction drop

Come spiegato in precedenza, quando una transazione viene inviata, raggiunge il nodo a cui il nostro portafoglio è collegato direttamente, per poi venire propagata agli altri nodi e rimanere nella mempool finché non viene inserita in un blocco valido.

Quando però ci si trova in un periodo di congestione del network Bitcoin, la Mempool di ciascun nodo si riempie di transazioni: ogni transazione ha un peso in byte e la somma delle transazioni può essere tale da raggiungere il limite massimo di memoria temporanea assegnato alla Mempool dal gestore del nodo.

A quanto corrisponde questo limite? Dipende. Nel mio caso corrisponde a 250 MB.

Per verificare a quanto ammonta il valore massimo in byte della vostra mempool, eseguite il comando $ bitcoin-cli getmempoolinfo nel vostro nodo

Per verificare a quanto ammonta il valore massimo in byte della vostra mempool, eseguite il comando $ bitcoin-cli getmempoolinfo nel vostro nodo

Quando questo limite, espresso dal parametro “maxmempool”, viene raggiunto, le transazioni con fee molto basse vengono rimosse dalla Mempool e due limiti chiamati “mempoolminfee” e “minrelaytxfee” entrano in gioco, facendo rifiutare al nodo qualsiasi nuova transazione prodotta da esso che abbia una quantità di fee inferiore a quanto stabilito (nel mio caso mempoolminfee = 1'000 satoshi) e impedendogli di accettare e dunque propagare nuove transazioni con fee inferiori alla soglia (nel mio caso minrelaytxfee = 1'000 satoshi), provenienti dagli altri nodi.

Per chiarire maggiormente, se impostassi il mempoolminfee del mio nodo ad esempio su un valore di 10'000 satoshi, questo rifiuterebbe qualsiasi mia transazione con fee inferiori a quella soglia, mentre ritrasmetterebbe transazioni provenienti da altri nodi che hanno fee superiori ai 1'000 satoshi ma anche inferiori a 10'000 sat.

Se dunque Alice inviasse a Bob la transazione da 1 bitcoin con una fee molto bassa, inferiore alla soglia minima, in un periodo di congestione del network in cui la Mempool del suo nodo ha già raggiunto il suo limite, allora la transazione verrà istantaneamente droppata, interrompendone di fatto la propagazione.

Potrebbe altresì succedere che il nodo di Alice riesca a propagare la transazione, perché le commissioni di questa sono superiori al mempoolminfee del suo nodo, ma che il nodo a cui è connesso il portafoglio di Bob abbia un minrelaytxfee più basso di quello di Alice, e dunque rifiuti la sua transazione. In entrambi i casi, Bob non vedrà la transazione di Alice in arrivo sul suo portafoglio.

Non basta. Esiste infatti un altro parametro che fa sì che una transazione possa venir droppata: il cosiddetto “transaction timeout”.

Attraverso un parametro chiamato “mempoolexpiry”, Bitcoin Core stabilisce per quanti giorni una transazione può rimanere “in sospeso” all’interno della Mempool senza venire confermata, dopodiché procede alla rimozione. Di default questo limite è di 14 giorni ma può essere personalizzato o del tutto eliminato.

Ciò non significa però che la transazione verrà annullata in automatico, perché potrebbe comunque essere nuovamente propagata da altri nodi, se risiede anche nelle loro mempool.

Presupponendo che nessuno ritrasmetta la transazione e non lo faccia nemmeno il wallet+nodo iniziale, allora la transazione verrà di fatto dimenticata dal network e i fondi ritorneranno a disposizione del mittente, che potrà eseguire una nuova transazione o tenersi i fondi.

Ritornando al nostro esempio, qualora Alice trasmettesse una transazione da 1 bitcoin per pagare Bob, con fee basse ma sufficienti a farla rimanere nella mempool dei vari nodi a cui è stata broadcastata, allora Bob vedrà quasi immediatamente la transazione in arrivo sul suo portafoglio.

Se però questa transazione viene lasciata in mempool per molti giorni e i nodi a cui è stata inviata hanno un timeout settato e non la ribroadcastano prima che questo timeout venga raggiunto, allora la transazione verrà droppata, e Alice tornerà in possesso dei suoi fondi, con buona pace di Bob che vedrà scomparire la transazione “in arrivo” dall’elenco delle sue transazioni e dal suo bilancio, se il suo wallet inserisce a bilancio le transazioni non ancora confermate.

Quindi ricapitolando, una transazione può venire droppata se:

  1. Le commissioni inserite dal mittente sono inferiori alla soglia minima del nodo di partenza→ La transazione non parte neanche;
  2. Le commissioni inserite dal mittente sono sufficienti per il suo nodo ma insufficienti per gli altri nodi che la dovrebbero broadcastare → La transazione parte ma il ricevente non vede;
  3. Le commissioni inserite dal mittente sono sufficienti ma molto basse rispetto alla media, dunque la transazione rimane in pending per molti giorni, non broadcastata e dunque rimossa dalle mempool dei vari nodi.

Quelli illustrati finora sono eventi che portano indirettamente alla cancellazione della transazione. Le casistiche non sono molto alte, specialmente se ci si trova in un periodo tranquillo per il network Bitcoin, senza congestioni in vista, però possono accadere e spesso lasciano gli utenti esterrefatti.

Ma se volessimo cancellare volontariamente una transazione? Impossibile? Non direi.

A seguito del post in cui chiedevo: “È possibile 'cancellare' una transazione Bitcoin?”, mi sono arrivati diversi commenti: alcuni erano categorici ed escludevano questa possibilità, mentre altri ipotizzavano che fosse possibile ma si trattasse di double spending di una transazione già confermata, e dunque fosse un evento non realistico.

Ci sono però stati degli utenti che, giustamente, hanno affermato che fosse possibile, attraverso un comando chiamato -zapwallettxes o tramite l’RBF di Bitcoin.

Il comando -zapwallettxes

I possessori di un nodo Bitcoin possono eseguire il comando zapwallettxes e cancellare le transazioni in queue, presenti nella mempool del nodo.

Le chance di successo sono però estremamente ridotte perché queste transazioni sono molto probabilmente già state broadcastate ad altri nodi ed è impossibile obbligare questi ultimi a rifiutarle.

Replace by Fee (RBF)

RBF è l’acronimo di Replace by Fee. Si tratta di una policy dei nodi Bitcoin attivata nel 2015 con il Bip 125. Trattandosi di una policy con attivazione volontaria da parte dell’utente, non è obbligatorio utilizzarla.

Ma in che cosa consiste questo RBF?

L’RBF consente di sostituire una transazione non confermata con un’altra transazione che utilizza lo stesso input della precedente ma con una commissione di mining più elevata. 

Una transazione Bitcoin è infatti formata da uno o più input, che rappresentano delle quantità di bitcoin da inviare al ricevente. Una volta che la transazione viene firmata dal mittente e gli input sono assegnati al ricevente, questi diverranno output non spesi, e potranno essere utilizzati come input di una nuova transazione solo ed esclusivamente dal destinatario della transazione precedente.

Se dunque Alice dovesse inviare 1 bitcoin a Bob e decidesse di utilizzare RBF ,  ammesso che il suo portafoglio supporti questo tipo di transazioni ,  potrebbe scegliere inizialmente di utilizzare una commissione relativamente bassa (ad esempio, 4 sat/byte) per poi incrementarla in un secondo momento, qualora la rete dovesse essere congestionata.

L’introduzione di Replace by Fee si è reso necessario principalmente per due motivi:

  1. I blocchi di Bitcoin hanno un limite in MB  a livello protocollare ( massimo 4 MB se tutte le transazioni fossero SegWit e quindi utilizzassero il paramentro block weight )  , dunque le transazioni inseribili in un blocco sono limitate;
  2. È necessario sviluppare un Fee Market, detto anche Blockspace Market, perché l’incentivo monetario per i minatori smetterà in futuro di essere costituito principalmente da nuovi bitcoin e sarà composto per lo più dalle commissioni degli utenti.

RBF permette dunque all’utente di essere parte attiva di questo mercato delle fee, consentendogli di iniziare una transazione con commissioni basse per poi eventualmente aumentarle “se il mercato lo richiede”.

Nell’immagine, una transazione inviata con RBF attivo. I 2 sat/byte possono essere aumentati dall’utente qualora lo volesse

Nell’immagine, una transazione inviata con RBF attivo. I 2 sat/byte possono essere aumentati dall’utente qualora lo volesse

Il tradeoff di RBF

RBF introduce delle innovazioni ma anche un tradeoff che in qualche modo potrebbe essere visto da alcuni come un’ulteriore feature: la “cancellazione” delle transazioni non confermate.

Fin dall’inizio dell’articolo ho scritto “cancellazione” tra virgolette ed i motivi sono presto detti: per quanto riguarda il Transaction drop, non si tratta di cancellazione ma di non propagazione della transazione, che dunque non arriva ad essere inserita nella catena di blocchi. Per quanto concerne l’RBF, vedremo qui di seguito come non si tratti in effetti di una cancellazione della transazione dalle mempool dei nodi, ma di una sostituzione con un’altra transazione che ha gli stessi input ma un diverso destinatario: noi stessi.

Alcuni portafogli hanno colto l’occasione presentata dall’introduzione della BIP 125 e i creatori si sono detti: “Perché non sfruttare questa funzionalità per introdurre anche su Bitcoin il concetto di reversibilità delle transazioni, almeno per quanto riguarda quelle non ancora confermate?” Tra questi wallet, cito ad esempio Blue Wallet, per i dispositivi mobili, ed Electrum, per i desktop.

Ciò potrebbe sembrare contrario alle premesse che hanno portato alla creazione di Bitcoin, tuttavia abbiamo spiegato finora che il concetto di reversibilità è relativo e di sicuro non si applica a transazioni che di fatto non sono ancora state inserite nella catena di blocchi di Bitcoin.

Questa “reversibilità” introdotta da alcuni wallet, sommata alla possibilità di agire attivamente sulle commissioni di mining ex post, non è altro che un miglioramento a livello di user experience (UX) che permette all’utente avanzato di essere un elemento attivo del mercato delle fee e all’utente base di avere la possibilità di rimediare agli errori eventualmente commessi.

Quante volte si sente infatti di utenti che hanno inviato la cifra sbagliata o hanno pagato l’indirizzo sbagliato?

L’esperimento inizia

Nel già citato post, ho chiesto agli utenti di partecipare a un esperimento: la dimostrazione che è effettivamente possibile “cancellare” una transazione non ancora confermata.

Un utente in particolare, Andrea Mazziotti, che ringrazio, ha subito manifestato interesse e mi ha inviato un suo indirizzo Bitcoin.

A questo indirizzo ho inviato una transazione da 18'148 satoshi, con una fee di 3 sat/byte, dal mio wallet Electrum v.4.0.4. Qui di seguito vedete la transazione non confermata:

ID: 743dc74fcf7a9d40fa6ba10935c92def9268300e979f1ba984720ca606de049d, https://blockchair.com/bitcoin/transaction/743dc74fcf7a9d40fa6ba10935c92def9268300e979f1ba984720ca606de049d

Qui invece vedete la conferma data dal mio wallet:

La transazione è stata broadcastata dal mio nodo e ha raggiunto quasi istantaneamente il nodo a cui era collegato il wallet di Andrea. La sua conferma è infatti giunta poco dopo, sia nel suo wallet, sia nel suo explorer di riferimento:

Electrum permette già da tempo di effettuare transazioni con RBF attivo, ma è solo dalla versione 4.0.4 che si può sfruttare questa feature anche per “cancellare” le transazioni:

Cliccando con il tasto destro del mouse sulla transazione non confermata vediamo infatti un nuovo comando, chiamato Cancel (double-spend). Ed è proprio questo ciò che avverrà, qualora decidessimo di utilizzarlo: la transazione non sarà cancellata, ma verrà spesa due volte. Verranno utilizzati gli stessi input della transazione originaria ma con fee più alte e con un nuovo indirizzo di destinazione, generato dal wallet.

Una nuova transazione con gli stessi input ma con fee da 20 sat/byte è stata inviata. La transazione ha ovviamente un nuovo Transaction ID.

Controllando l’ID in un explorer, ecco che si ha conferma dell’avvenuta transazione, anch’essa ancora non confermata, ma con commissioni più elevate e un nuovo indirizzo di destinazione:

Dopo pochi minuti la transazione è stata confermata e la prima transazione di fatto cancellata.

Come potete verificare che la prima transazione sia stata effettivamente droppata?
Semplice, recatevi qui oppure incollate l’ID della prima transazione in un qualunque block explorer.

Esperimento riuscito!

Ebbene, abbiamo dimostrato che è possibile cancellare una transazione non ancora confermata, o meglio spendere due volte uno stesso input, grazie a RBF. Quali conclusioni possiamo trarre da tutto ciò?

La più basica delle “leggi” di Bitcoin dopo “not your keys, not your bitcoins”: non considerare valida una transazione che non abbia almeno una conferma sulla blockchain.

Bisognerebbe aggiungere che, per importi alti, è bene aspettare diverse conferme, perché maggiore è la quantità di blocchi passati dalla prima conferma, più è lecito considerare la transazione come irreversibile.

In chiusura, un piccolo suggerimento

La capacità di effettuare double spending di una transazione non ancora confermata potrebbe esporre l’utente ricevente a tentativi di truffa, se questo non aspetta almeno una conferma prima di cedere un bene o servizio in cambio di quei bitcoin.

Se infatti questa transazione venisse cancellata dal mittente, l’utente ricevente rimarrebbe senza bitcoin e senza beni.

Quindi il primo metodo per evitare truffe è quello di attendere la conferma della ricezione. Esiste però un secondo metodo, per cercare di approvare la transazione del truffatore prima che questo tenti l’eliminazione tramite RBF: utilizzare la tecnica del Child Pay for Parent (CPFP).

Child Pay for Parent (CPFP)

Questa tecnica è simile all’RBF per quanto riguarda la velocizzazione della transazione, perché consiste anch’essa nell’inviare a sé stessi una transazione con gli stessi input ma con fee maggiori. Qual è dunque la differenza principale?

Con RBF si crea una transazione pressoché identica alla precedente, che differisce solo per le commissioni e per l’indirizzo destinatario. Con CPFP invece si crea una transazione con gli altri input del proprio wallet, compreso quello della transazione non confermata, e dunque il peso di questa grande transazione sarà maggiore di una più semplice transazione con RBF.

Eseguire una transazione CPFP è piuttosto semplice purché il wallet utilizzato supporti questa tecnica. Ci si reca nel portafoglio in cui si ha la transazione non ancora confermata, si richiede un nuovo indirizzo, e infine si invia a questo indirizzo il totale del bilancio con una commissione maggiore di quella della transazione non confermata.

Quindi andiamo di fatto a consolidare tutti gli input presenti nel nostro portafoglio, inviando a noi stessi la somma di quest’ultimi, compreso l’input della transazione non confermata.

Se siamo fortunati, la prima transazione del truffatore verrà confermata prima della sua seconda transazione con fee maggiori (RBF, double spend), perché i suoi input verranno inclusi nella nostra transazione CPFP.

Dato che i minatori preferiscono inserire nei loro blocchi candidati delle transazioni con commissioni maggiori, specialmente in periodi di forte congestione del network, allora sarà più probabile che la nostra transazione CPFP venga inserita prima della seconda transazione (RBF) del truffatore, semplicemente perché paga di più.