Glossário / Transações e taxas
SIGHASH_ALL
- O que é SIGHASH_ALL?
- SIGHASH_ALL é o sinalizador que faz uma assinatura se comprometer com todas as entradas e todas as saídas de uma transação, de modo que nada do pagamento pode ser alterado depois da assinatura.
Este é o sinalizador que sua carteira usa, e é a razão pela qual aprovar uma transação na tela de uma carteira de hardware significa algo. Seu valor é 1, e você pode vê-lo como o último byte de quase toda assinatura em um explorador de blocos. O Taproot renomeou o padrão para SIGHASH_DEFAULT e deixou de escrever o byte, economizando um byte por assinatura.
Como funciona
Com SIGHASH_ALL, o resumo abrange a versão da transação, cada outpoint gasto, cada número de sequência, o valor de cada saída, o script de cada saída e o locktime.
Altere um único satoshi de uma única saída e todas as assinaturas da transação deixam de valer. Adicione uma entrada, elimine uma saída, reordene-as, ajuste o locktime: o mesmo resultado. É isso que as pessoas querem dizer quando afirmam que uma transação de bitcoin assinada é definitiva em conteúdo antes mesmo de ser transmitida. A única decisão que resta a qualquer pessoa é se deve enviá-la.
Uma coisa fica deliberadamente de fora: os scripts de desbloqueio das outras entradas. Se o resumo os abrangesse, em uma transação com dois assinantes cada assinatura teria de ser feita depois da outra, o que é circular e impossível. Deixá-los de fora é o que permite que partes independentes assinem a mesma transação na ordem que quiserem.
A codificação varia conforme o tipo de entrada. Em uma entrada legacy ou segwit de versão 0, o byte 01 é anexado à assinatura codificada em DER, e é daí que vem o conhecido total de 71 ou 72 bytes. Em um gasto por caminho de chave do Taproot, o BIP341 define um valor zero como SIGHASH_DEFAULT, o que significa cobertura idêntica sem nenhum byte escrito, então a assinatura tem exatamente 64 bytes. Escrever 01 explicitamente em uma entrada Taproot continua válido e produz o mesmo resumo, só custa um byte extra em troca de nada.
Onde você o vê
SIGHASH_ALL é usado em quase todo lugar: Bitcoin Core, Electrum, Sparrow, toda carteira de hardware e todo mecanismo de saque de corretora assinam assim por padrão, e nenhum deles oferece uma configuração para mudar isso.
A consequência prática é a que você sente quando um pagamento fica preso. Como a taxa é o que sobra entre as entradas e as saídas, e todas as saídas estão assinadas, você não pode tirar alguns milhares de satoshis de uma saída para aumentar a taxa. A transação precisa ser reconstruída e assinada de novo desde o início, o que só a carteira que guarda as chaves pode fazer. É por isso que o replace-by-fee é um recurso da carteira que envia, e não algo que uma corretora ou um explorador de blocos possa fazer em seu nome, e é por isso que o child-pays-for-parent existe como saída de emergência quando o remetente está inacessível.
Também é isso que transforma a tela de uma carteira de hardware em um contrato, e não em uma sugestão. O dispositivo mostra o destino, o valor e a taxa, e como a assinatura que ele então produz abrange os três, nenhum software posterior pode alterar qualquer um deles sem descartar essa assinatura. Aprove o que a tela diz e nada mais pode acontecer.
SIGHASH_ALL vs SIGHASH_NONE
SIGHASH_ALL se compromete com a lista completa de saídas; SIGHASH_NONE não se compromete com nenhuma delas. A diferença entre os dois é a diferença entre um pagamento e uma mera autorização para mover um bitcoin a um destino não especificado. Os dois sinalizadores ficam a um valor de distância, então uma biblioteca de assinatura que aceita o sinalizador como parâmetro inteiro está a um erro de digitação de transformar o saque de um cliente em um bitcoin que qualquer um que observe a mempool pode redirecionar. O código de assinatura de produção deve fixar o valor no código, em vez de recebê-lo como entrada.