Com a versão atual do Bitcoin Script, isso não é possível. No entanto, com algumas atualizações no ScriptVM do Bitcoin isso se tornaria possível, os pré-requisitos são:
- Uma maneira de confirmar as saídas da transação (por exemplo, OP_CHECKTEMPLATEVERIFY ou opcodes de introspecção TX + OP_CAT)
- Uma maneira de dividir e concatenar itens da pilha (OP_CAT e OP_SPLIT)
- Uma forma de as entradas “verem” umas às outras (opcodes de introspecção)
Com isso, pode-se codificar um hash-lock, mas com um requisito adicional: outra entrada deve revelar um compromisso antigo com (prevout + conteúdo de saída do TX). Isso é algo que apenas a pessoa que conhece o segredo seria capaz de produzir antes de revelá-lo. Assim que ele gastar o contrato ele irá revelá-lo, mas já terá o compromisso antigo e outros não poderão roubar seus fundos. Uma vez postado no mempool, a segurança dependeria da mineração do TX de gastos antes que um invasor pudesse envelhecer um compromisso alternativo e postar um TX de gastos alternativo.
Existe uma prova de conceito para tal contrato para o Bitcoin Money (BCH), um fork blockchain do Bitcoin (BTC) que atualizou o ScriptVM com as primitivas L1 necessárias em ’18 (OP_CAT e OP_SPLIT) e ’22 (códigos de operação de introspecção) atualizações de rede.
O script de resgate “lock”, colocado no UTXO que manteria o saldo
(nota: não há dados de desbloqueio, o script de desbloqueio da entrada é apenas o push do script de resgate)
// sha256(one_time_secret + commit_script_tail)
<93168bb98087a29aeb40733ef301f907c3e4125568dd0ddf851f304b43438a14>
// slice related enter's script
OP_INPUTINDEX OP_1ADD
OP_INPUTBYTECODE
<1> OP_SPLIT
OP_SWAP OP_SPLIT
<2> OP_SPLIT
<1> OP_SPLIT
<32> OP_SPLIT
<1> OP_SPLIT
<1> OP_SPLIT
// confirm sha256(one_time_secret + commit_script_tail)
<6> OP_ROLL OP_SWAP OP_CAT OP_SHA256
<6> OP_ROLL OP_EQUALVERIFY
// confirm enter script head format
<0x51> <0x61> OP_WITHIN OP_VERIFY
<0x51> <0x61> OP_WITHIN OP_VERIFY
OP_SIZE <32> OP_EQUALVERIFY
OP_DROP <32> OP_EQUALVERIFY
<0x4c72> OP_EQUAL
O script de resgate “commit”, colocado no UTXO que revelaria o compromisso antigo
(nota: os dados de desbloqueio são apenas os one_time_secret
)
// sha256(associated_outpoint + one_time_secret + {first 3 outputs})
<0x8bda8c89d438b6da3fd9d289da59532736bfb23d93bba1e2e8da41c194ea43e9>
// age_reveal
<2>
// age_cleanup
<4>
OP_DEPTH <4> OP_LESSTHAN
// if no secret is supplied then it is a cleanup spend
OP_IF
// as soon as redeem script is revealed and utxo aged past age_cleanup,
// any miner can declare the mud to himself
// confirm age_cleanup
OP_CHECKSEQUENCEVERIFY OP_DROP
OP_2DROP
// else it's a reveal spend
OP_ELSE
// drop age_cleanup, not wanted right here
OP_DROP
// confirm age_spend
OP_CHECKSEQUENCEVERIFY OP_DROP
// get related outpoint on high of stack
OP_INPUTINDEX OP_1SUB OP_DUP
OP_OUTPOINTTXHASH
OP_SWAP OP_OUTPOINTINDEX OP_CAT
// get one_time_secret on high of stack and concatenate
OP_ROT OP_CAT
// concatenate outputs 00 (& 01 (& 02))
<0> OP_OUTPUTVALUE OP_CAT
<0> OP_OUTPUTTOKENCATEGORY OP_CAT
<0> OP_OUTPUTTOKENCOMMITMENT OP_CAT
<0> OP_OUTPUTTOKENAMOUNT OP_CAT
<0> OP_OUTPUTBYTECODE OP_CAT
OP_TXOUTPUTCOUNT <2> OP_GREATERTHANOREQUAL
OP_IF
<1> OP_OUTPUTVALUE OP_CAT
<1> OP_OUTPUTTOKENCATEGORY OP_CAT
<1> OP_OUTPUTTOKENCOMMITMENT OP_CAT
<1> OP_OUTPUTTOKENAMOUNT OP_CAT
<1> OP_OUTPUTBYTECODE OP_CAT
OP_ENDIF
OP_TXOUTPUTCOUNT <3> OP_GREATERTHANOREQUAL
OP_IF
<2> OP_OUTPUTVALUE OP_CAT
<2> OP_OUTPUTTOKENCATEGORY OP_CAT
<2> OP_OUTPUTTOKENCOMMITMENT OP_CAT
<2> OP_OUTPUTTOKENAMOUNT OP_CAT
<2> OP_OUTPUTBYTECODE OP_CAT
OP_ENDIF
OP_SHA256
// confirm towards embedded pre-commitment
OP_EQUALVERIFY
OP_ENDIF
OP_1
Os contratos podem ser carregados no depurador BitAuthIDE usando esse hyperlink.
Os contratos foram gastos com sucesso na rede principal do BCH:
Esta prova de conceito foi publicada pela primeira vez aqui