Glossario / Transazioni e commissioni
SIGHASH_ALL
- Che cos'è SIGHASH_ALL?
- SIGHASH_ALL è il flag che fa sì che una firma impegni ogni input e ogni output di una transazione, così nulla del pagamento può essere modificato dopo la firma.
Questo è il flag che usa il tuo wallet, ed è il motivo per cui approvare una transazione sullo schermo di un wallet hardware ha un senso. Il suo valore è 1, e puoi vederlo come ultimo byte di quasi ogni firma su un block explorer. Taproot ha rinominato il valore predefinito in SIGHASH_DEFAULT e ha smesso di scrivere del tutto il byte, risparmiando un byte per firma.
Come funziona
Con SIGHASH_ALL il digest copre la versione della transazione, ogni outpoint speso, ogni numero di sequenza, ogni importo di output, ogni script di output e il locktime.
Cambia un solo satoshi di un solo output e ogni firma sulla transazione muore. Aggiungi un input, elimina un output, riordinali, sposta il locktime: stesso risultato. È questo che si intende quando si dice che una transazione bitcoin firmata è definitiva nel contenuto prima ancora di essere trasmessa. L'unica decisione che resta a chiunque è se inviarla.
Una cosa è deliberatamente esclusa: gli script di sblocco degli altri input. Se il digest li coprisse, in una transazione con due firmatari ogni firma dovrebbe essere apposta dopo l'altra, il che è circolare e impossibile. Lasciarli fuori è ciò che permette a parti indipendenti di firmare la stessa transazione nell'ordine che preferiscono.
La codifica varia in base al tipo di input. Su un input legacy o segwit di versione 0, il byte 01 viene aggiunto alla firma codificata in DER, ed è da lì che viene il noto totale di 71 o 72 byte. Su una spesa tramite key path di Taproot, BIP341 definisce un valore di zero come SIGHASH_DEFAULT, cioè la stessa copertura senza scrivere alcun byte, quindi la firma è esattamente di 64 byte. Scrivere 01 esplicitamente su un input Taproot è comunque valido e produce lo stesso digest, costa solo un byte in più per nulla.
Dove lo vedi
SIGHASH_ALL è usato quasi ovunque: Bitcoin Core, Electrum, Sparrow, ogni wallet hardware e ogni motore di prelievo degli exchange firmano così per impostazione predefinita, e nessuno di loro offre un'impostazione per cambiarlo.
La conseguenza pratica è quella che avverti quando un pagamento si blocca. Poiché la commissione è ciò che resta tra gli input e gli output, e gli output sono tutti firmati, non puoi togliere qualche migliaio di satoshi da un output per aumentare la commissione. La transazione deve essere ricostruita e firmata di nuovo dall'inizio, cosa che solo il wallet che detiene le chiavi può fare. È per questo che il replace-by-fee è una funzione del wallet che invia e non qualcosa che un exchange o un block explorer può eseguire per te, e per questo esiste il child-pays-for-parent come via di fuga quando il mittente è irraggiungibile.
È anche ciò che trasforma lo schermo di un wallet hardware in un contratto anziché in un suggerimento. Il dispositivo mostra la destinazione, l'importo e la commissione, e poiché la firma che produce copre tutti e tre, nessun software a valle può alterarne alcuno senza buttare via quella firma. Approva ciò che dice lo schermo e non può succedere altro.
SIGHASH_ALL vs SIGHASH_NONE
SIGHASH_ALL impegna l'intero elenco degli output; SIGHASH_NONE non ne impegna nessuno. La distanza tra loro è la distanza tra un pagamento e una semplice autorizzazione a spostare un bitcoin verso una destinazione non specificata. I due flag distano un solo valore, quindi una biblioteca software per la firma che accetta il flag come parametro intero è a un errore di battitura dal trasformare il prelievo di un cliente in un bitcoin che chiunque osservi la mempool può reindirizzare. Il codice di firma in produzione dovrebbe avere il valore scritto nel codice invece di riceverlo come input.