0

I am trying to spend a P2SH UTXO based on a redeem script that requires no signatures and simply needs the correct input to equal the OP_HASH160 digest in the corresponding P2SH locking script.

My unlocking script pushes 17 bytes onto the stack (0x11) which are the following 17 bytes that constitute the "secret" number to get the correct hash.

The decoded raw tx is the following (with the 17 byte secret number removed):

"txid": "0ba564fc00cbeada33ccded7f4e45f17bfff69c8f8a38132dc715de0d905b857",
"hash": "0ba564fc00cbeada33ccded7f4e45f17bfff69c8f8a38132dc715de0d905b857",
"version": 1,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 0,
"vin": [
  {
    "txid": "f8e5dfe32a57872d58cee6f3eb32ec0277f3563306ae623109ea651fd9dc8087",
    "vout": 1,
    "scriptSig": {
      "asm": "<17 byte redeem script>",
      "hex": "11<17 byte redeem script>"
    },
    "sequence": 4294967295
  }
],
"vout": [
  {
    "value": 0.00002000,
    "n": 0,
    "scriptPubKey": {
      "asm": "02de153317307164e7c9918791c7787d9833a3a8201bdff880e631e490cf9a087c      OP_CHECKSIG",
      "desc": "pk(02de153317307164e7c9918791c7787d9833a3a8201bdff880e631e490cf9a087c)#epafp6sh",
      "hex": "2102de153317307164e7c9918791c7787d9833a3a8201bdff880e631e490cf9a087cac",
      "type": "pubkey"
    }
  }
]
}

I can't see any mistakes however "sendrawtransaction" gives me the error: error code: -26 error message: mandatory-script-verify-flag-failed (Opcode missing or not understood)

I had thought maybe this was a non-standard tx and therefore wouldn't be valid unless submitted directly to miner*, however it was my understanding that P2SH allowed the freedom to submit arbitrary redeem scripts, provided the unlocking script is valid and the redeem script equals the redeem script hash in the locking script.

*bitcoin-cli decodescript for my unlocking script hex does give me Type:nonstandard

1
  • 1
    Hi Peter, please consider using regtest, testnet, or signet instead of mainnet to create experimental transactions.
    – Murch
    Commented Feb 6, 2023 at 19:08

1 Answer 1

1

A p2sh unlocking script first pushes the actual script, then any stack element needed to fulfill this script. The interpreter will pop one element from the stack and verify if it's hash160 is equal to the one committed in the spk. If yes, then the interpreter destroys the runtime, and build a new one, but using the popped element as script instead.
In your case, bitcoind is interpreting your secret as a script, and it isn't a valid script. Hence, yielding an error about opcodes. The correct way of doing this with p2sh is by taking the hash160 of the hex-encoded script:

OP_HASH160 OP_PUSH20 <your_hash> OP_EQUALVERIFY

Your program hash is the resulting digest.
When spending, you first push this script, and your secret as a second stack element. Your initial stack looks like this: <script> <secret>

8
  • I don't follow. Are you saying that my redeem script should have the 0x11 included? So the entire unlocking script would be <11secret key>? Also it's not clear to me why 11<redeem script> wouldn't just push <redeem script> onto the stack, and then the HASH_160 on the unlocking script would pop this off and compare result to script hash. In my case there is no "script" on the unlocking side, I just want to push the redeem script/number on the stack, and be evaluated by the locking script.
    – Peter
    Commented Feb 6, 2023 at 4:23
  • Appears I have some confusion with regards to the push byte opcodes. For example this P2SH UTXO mempool.space/tx/… , the redeem script is 00140e90dbfd847487b28ce26055b11826116d040090 and the full unlocking script is 1600140e90dbfd847487b28ce26055b11826116d040090. So 0x16 push 22 bytes onto stack, but then the redeem script also has push 0x14 bytes onto stack (when it is already on stack?)
    – Peter
    Commented Feb 6, 2023 at 4:30
  • Following that logic, should my unlocking script be: 12<11secret key>?
    – Peter
    Commented Feb 6, 2023 at 4:33
  • What you are missing is that p2sh isn't just the explicit script. If you see the sh template, you make an extra step that is not in the script where the first element is popped out from the stack and used as scrip. Otherwise, you wouldn't run the actual script, just the p2sh template. Take a look at bip 16 to more details. And yes OP_PUSH18 <script> where script is <OP_PUSH17 <secret>. But I think this violates the clean stack rule. Commented Feb 6, 2023 at 11:32
  • Alright, I didn't realize P2SH has a different script execution logic, although BIP16 doesn't lay out how this works precisely. Is it correct to say with a P2SH locking script, this somehow triggers a different execution logic, where in the locking script, one must push n bytes of redeem script onto stack, the stack is the copied, the redeem script executed (where 1 must be left on top of stack at end). If 1 on top then stack is replaced by redeem script, where the locking script is executed to compare the hash?
    – Peter
    Commented Feb 7, 2023 at 2:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.