3

I have been following BIP16 in creating a P2SH transaction. I want to create a simple (one signature) P2SH. I am getting an error when trying to broadcast the tx. Error is 16: mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)

To be clear, I am not trying multisig. What I am doing can be best described as P2SH-P2PK, though I have not seen this term. This is the only example given in BIP16, so this should work.

Here is what I have tried (testnet):

private key: BB2AC60BC518C0E239D5AF9D8D051A6BDFD0D931268DCA70C59E5992 
public key: 039f53e45f8f18b8ed294378bda342eff69b2053debf27fbede7d2d6bd84be6235 
(compressed)

redeemScript: [{pubKeySize,pubKey}] [OP_CHECKSIG]
21039F53E45F8F18B8ED294378BDA342EFF69B2053DEBF27FBEDE7D2D6BD84BE6235AC 

redeemScriptHash: RIPEMD160(SHA256(redeemScript))  
323D0E8A083E98010299109337850D05DD6157F7

p2shAddress: Base58Check(0xC4 + redeemScriptHash) (C4 for testnet)
2MwprvB9tUMtX4vK8zJK8K329fNu79CJgR7

The above address has two UTOXs on testnet:

UTXO1: e434a13cac79dc3d26e7279bff05c0f071a2df03e2ba6ca13c88f0e82dca9998:0
UTXO2: 9b4943e7ab5f4512e42c94254eb6aab4c6823ce06d4ff816b7ce4fda155a2571:0

I now want to spent both UTXOs and keep following outputs:

Out1: 2MwprvB9tUMtX4vK8zJK8K329fNu79CJgR7 34000000 Satoshis
Out2: 2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF 100000000 Satoshis   

I created the tx as follows:

  1. Create unsigned transactions with all scriptSigs empty
  2. For each input to sign, set its scriptSig to redeemScript: 21039F53E45F8F18B8ED294378BDA342EFF69B2053DEBF27FBEDE7D2D6BD84BE6235AC, keeping other scriptSigs to empty.
  3. Serialize the new tx and append SIGHASHALL bytes (0x01) in little endian 4 bytes
  4. Double Sha256 above and sign resulting value. Add one byte 0x01 to signature to indicate SIGHASH_ALL. Let sig be the resulting value.

  5. Set the scriptSig as:

    [0x00] [{sigSize, sig}] [{pubKeySize, pubKey}] [OP_CHECKSIG]

I am assuming that the following scriptPubKey will be used:

[OP_HASH160] [{scriptHashSize, scriptHash}] [OP_EQUAL]

The following are the k, r and s values for each input's signature:

Input 1:

k = 98790447509501799195296257240616657470656053786701275200434341714298778299820  
r = 96398386359095408146340664941016369169423137684113382189227162443480418477689
s = 62903510511574365450545635776206168644738316078298063260649088246548574249129

Input 2:

k = 109372172176680138721552873719725202562296645126925021083510279924852033069204  
r = 105162394984132461723584277789901247831150698039237112243693144757926439529504
s = 62903510511574365450545635776206168644738316078298063260649088246548574249129

After this, I am getting the following error in bitcoind for sending the tx:

error code: -26
error message:
16: mandatory-script-verify-flag-failed 
(Signature must be zero for failed CHECK(MULTI)SIG operation)

What am I doing wrong?

EDIT: Thanks to the answer by arubi, I found there were two issues with the above steps. First thing, I was doing wrong was not encoding the redeemScript as stack data. Second thing, I was doing wrong was putting [0x00] in scriptSig. After fixing that, Step 5 should be:

  1. Set the redeemScript as [{pubKeySize, pubKey}] [OP_CHECKSIG]

  2. Set the scriptSig as [{sigSize, sig}] [{redeemScriptSize, redeemScript}]

2

The issue is, scriptsig contains the actual redeemScript instead of the serialized script as a push. The second error, the redeemscript contains an extraneous 0x00 value that should not be there as this is a simple CHECKSIG.

  • 2
    It's worth to note that the 0x00 value left on the stack does not invalidate the transaction, rather it will not be caught before relay by local policy as it doesn't adhere to the cleanstack rule. – arubi Dec 22 '17 at 18:51
  • If some node mines the tx with the leading 0x00, will be be considered valid? – Jus12 Dec 28 '17 at 18:03
  • Yes, I think it will be valid as the OP_CHECKSIG which executes last will push a value that evaluates to True (0x01 in this case) to the top of the stack. The stack will be : 0x01 0x00 Making the whole script evaluate to True. – arubi Dec 30 '17 at 9:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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