Para que um script de resgate satisfaça as condições de um script, o que ele deve deixar na pilha após a execução?

Dec 07 2020

Eu estava assistindo a esta apresentação de Andreas Antonopoulos sobre scripts avançados de bitcoin.

Parece a partir dos exemplos de Andreas que para um script de resgate satisfazer as condições do script, ele precisa deixar TRUE (e nada mais) na pilha após ter sido executado. Isso também foi questionado aqui .

Portanto, há um sufixo VERIFY de forma que alguns opcodes (por exemplo, EQUAL, CHECKSIG, CHECKMULTISIG) têm opcodes concorrentes (por exemplo, EQUALVERIFY, CHECKSIGVERIFY, CHECKMULTISIGVERIFY). Em vez de deixar TRUE na pilha, esses opcodes VERIFY "continuarão a execução do Script se o resultado do operador condicional for TRUE", mas "não empurrarão esse TRUE de volta para a pilha, simplesmente continuarão a execução". Esses opcodes VERIFY podem ser usados ​​para garantir que a execução do script de resgate deixe TRUE (e nada mais) na pilha em vez de dizer TRUE TRUE TRUE.

No entanto, nesta sessão do clube de revisão do Bitcoin Core PR , Pieter Wuille declarou (parafraseando):

Para CLEANSTACK, você deve ter uma pilha com um único elemento que deve ser diferente de zero. Sem CLEANSTACK, uma pilha não vazia com vários elementos está ok, desde que o elemento superior seja diferente de zero

Eu tenho duas perguntas:

  1. Presumivelmente, TRUE é equivalente a 1 e FALSE é equivalente a 0?

  2. Quaisquer opcodes avaliados como FALSO resultarão em falha imediata e término da execução? Portanto, com não CLEANSTACK, você nunca veria uma pilha resultante de TRUE FALSE TRUE passando como FALSE resultaria em falha imediata e você não avaliaria o TRUE final. No entanto, você poderia ver uma pilha de, digamos, TRUE 3 TRUE 5 e isso passaria com não CLEANSTACK. (Haveria falha com CLEANSTACK, pois CLEANSTACK deve ter um único elemento na pilha resultante).

Respostas

3 MichaelFolkson Dec 07 2020 at 20:42

Obrigado a harding por responder a esta pergunta no IRC e sanket1729 para edições.

Presumivelmente, TRUE é equivalente a 1 e FALSE é equivalente a 0?

TRUE é qualquer valor diferente de zero. Isso é frequentemente usado em scripts que envolvem os códigos de operação OP_NOPx anteriores que não retiram seus valores da pilha após a verificação, por exemplo, um script que pode ser gasto por um minerador após uma certa altura pode usar <locktime> OP_CLTV:; se o CLTV falhar, a transação é inválida; se for aprovado, o valor diferente de zero deixado na pilha permitirá que o script seja aprovado.

Quaisquer opcodes avaliados como FALSO resultarão em falha imediata e término da execução? Portanto, com não CLEANSTACK, você nunca veria uma pilha resultante de TRUE FALSE TRUE passando como FALSE resultaria em falha imediata e você não avaliaria o TRUE final. No entanto, você poderia ver uma pilha de, digamos, TRUE 3 TRUE 5 e isso passaria com não CLEANSTACK. (Haveria falha com CLEANSTACK, pois CLEANSTACK deve ter um único elemento na pilha resultante).

Tudo o que importa sem CLEANSTACK é o valor do topo da pilha no final da execução. Qualquer coisa mais abaixo na pilha não importa.

CLEANSTACK é uma regra de padronização para P2SH, mas é uma regra de consenso para Segwit v0 ( especificação BIP141 ) e Tapscript, SegWit v1 ( especificação BIP342 , regra 4, ii)

A palavra "falha" é ambígua aqui. Existem diferentes maneiras pelas quais diferentes opcodes podem falhar. Por exemplo, se OP_CHECKSIG falhar, ele apenas coloca um 0 na pilha. Mas se OP_CHECKSIGVERIFY falhar, todo o script falhará. Você pode colocar TRUE FALSE FALSE na pilha usando apenas OP_0 OP_0 OP_1.

Alguns dos opcodes VERIFY, por exemplo, EQUALVERIFY, CHECKSIGVERIFY, CHECKMULTISIGVERIFY, terminam imediatamente em caso de falha, mas seus equivalentes não VERIFY não.

Tudo o que importa é o estado da pilha no final da avaliação do script. Por exemplo, você poderia fazer OP_CHECKSIG seguido por OP_IF OP_PUSHNUM1 OP_ELSE OP_PUSHNUM2 OP_ENDIF, por exemplo, se a assinatura for bem-sucedida, escolha um ramo; se falhar, escolha outro branch (embora isso não seja considerado uma prática recomendada e geralmente não deve ser feito).

CLEANSTACK é uma tentativa de evitar a maleabilidade fazendo com que as pessoas coloquem um monte de lixo em seu scriptSig ou dados de testemunha. Porque você pode simplesmente colocar um monte de dados na pilha que nunca são usados ​​e não impedem que o script seja avaliado corretamente. (Pré-segwit, isso afetou a maleabilidade txid e foi aplicado como uma regra de política de padronização; com segwit, isso não é mais possível, pois é uma regra de consenso)