Author

Topic: Error message "mandatory-script-verify-flag-failed" when constructing a S|A tx (Read 67 times)

legendary
Activity: 3472
Merit: 10611
It is not a simple "it is possible/impossible" answer. To get a better answer to your question, it is best if you first create exact examples of it (like you did here) and then use a reliable code to generate sighash values and see if they are the same. Then with actual transactions we can analyze why it worked or didn't work by looking at the code.

For example in here we had 3 transactions: tx1, tx2 and txCombined.
tx1 has 1 input, 1 output. Same as tx2.
txCombined combines tx1 & tx2 and has 2 inputs and 2 outputs.

The sighah for first and only input of tx1 and first input of txCombined were both: 6b122db40e279d4d557c09a34489dbf957b88829f59abfb7e2151c71af071c7d
but the sighash for first and only input of tx2 is 601f841ebc69424c8df7aa264d14fa421e4bb9212c6c0a75da8a4a3b82f86202 while for second input of txCombined is ef8056cea6d4248d3ace4632a5e0ea38f838d855d3ee7341d599cb858163abfb

So you can already guess that your tx1 signature should be valid for your txCombined but not the signature of tx2.

Now lets go through the code to understand what is causing the difference. In this case we deal with this line:
https://github.com/bitcoin/bitcoin/blob/bb57017b2945d5e0bbd95c7f1a9369a8ab7c6fcd/src/script/interpreter.cpp#L1332
which deals with txOutCount or nOutputs and for SIGHASH_SINGLE the number of outputs depends on the index of the input you are signing.

And these lines dealing with serialization of outputs after we decided on their count:
https://github.com/bitcoin/bitcoin/blob/bb57017b2945d5e0bbd95c7f1a9369a8ab7c6fcd/src/script/interpreter.cpp#L1334-L1335
https://github.com/bitcoin/bitcoin/blob/bb57017b2945d5e0bbd95c7f1a9369a8ab7c6fcd/src/script/interpreter.cpp#L1313-L1319

When signing tx1, tx2 and the first input in txCombined using SIGHASH_SINGLE which is at nIn=0 your txoutcount is going to be 1 (nOutputs).
But when you sign the second input in txCombined (which is the only input of tx2) using SIGHASH_SINGLE which is at nIn=1 your txoutcount is going to be 2.

That's the first difference that changed the final sighash for second input.

The next step is to serialize the outputs.
When signing tx1, tx2 and the first input in txCombined using SIGHASH_SINGLE you are only serializing 1 output regardless of how many outputs there are. And the serialization process is the same (L1313-L1319).
But when you sign the second input of txCombined using SIGHASH_SINGLE you are serializing 2 outputs while using a default (-1) for the first output and use the correct second output (the default CTxOut() that is passed to the Serialize method).

This is the second difference that changed the final sighash for second input.
?
Activity: -
Merit: -
Many thanks for your response!

There are Bitcoin resources that mention combining various Single|Anyonecanpay (S|A) transactions as the primary use case for this type of SigHash flag. This is why I provided the interpretation I explained earlier.

Based on your response, I now understand that:

1. It is not possible to combine two S|A transactions that are initially unaware of each other.

However,

2. It is possible to sign an S|A transaction first, and then add other inputs/outputs using SigHash flags like ALL, which take into account the already-signed S|A transaction (signed separately before adding the other inputs). This is demonstrated here: https://mempool.space/tx/59bd7b2cff5da929581fc9fef31a2fba14508f1477e366befb1eb42a8810a000

I would greatly appreciate your help in validating the two statements above.
legendary
Activity: 3472
Merit: 10611
When using SIGHASH_SINGLE, regardless of the fact that you are only signing a "single" output, the digest is actually going to be different based on the number of outputs because the output count is still part of the digest and other outputs are still used during signing.

When you sign the first input with SIGHASH_SINGLE the output_count used during signing is 1 but when you sign the second input it is 2.
You also have to write -1 (negative one or 9 byte 255,255,...,0) as each output that is not being signed. Meaning you are signing a "single" output's script and amount while also signing other outputs but not care about their script or amount (acknowledge that they exist).

This is why you can't just reuse the signature produced for a transaction with 1 output (your Transaction 1) for a transaction with 2 outputs (your combined/last tx).
?
Activity: -
Merit: -
Title: Error message "mandatory-script-verify-flag-failed" when constructing a SigHash SINGLE | ANY transaction

One of the main possibilities that SigHash SINGLE | ANY (0x83) has, is to combine two or more transactions with this particular flag into one (Modularity).

That's the theory, but when it comes to practice, it is not working (at least for me); Let me explain:

I created this two transactions in testnet4, both spending only one input and sending it to only one output, both P2PKH:

Transaction 1:

0100000001bd20399c1f2d841f1e147ad2e03df1635f48fc5b8cdbb55ea3a86b14225e274300000 0006a4730440220435c5161232d1b3215c44169f7c0328f1af1d40b4a8f2ec16795f442e9b80f7e 022047fd3dd15421d2a0956a79e2141f3a72d2fe69c4e6c5bcc75047bd6d8bf019f5832102313b3 5fdf7af967980d29e684c508c90e11d99b10cab20ef477c9e63d9bf7bf7ffffffff015898000000 0000001976a914c103e57c094061209b419e5ca559704a8a22f3f988ac00000000

Transaction 2:

0100000001d38e64afa39dd966f96e07bf56ae44bc3d402630771480f461389edff8a0051e01000 0006a4730440220645a7a25ebb00194a3b2f940d5618d021f513c2dd9bdc0504f623824e9845d8e 0220077af01808e98b7ca97d2927243f9beb8cbd48e85d07dde26ea46c2e79d6c2ee832102e90fb 489e28444cdfd85057fcce5f6d6ab1ba525acf570a7ffa355dbb7f21162ffffffff0128a0000000 0000001976a914d80f48340dd7ee6c7fae287342d3eeb1d4d887e288ac00000000

Then, I have combined them into one, making sure that outputs are in the correct index position:

0100000002bd20399c1f2d841f1e147ad2e03df1635f48fc5b8cdbb55ea3a86b14225e274300000 0006a4730440220435c5161232d1b3215c44169f7c0328f1af1d40b4a8f2ec16795f442e9b80f7e 022047fd3dd15421d2a0956a79e2141f3a72d2fe69c4e6c5bcc75047bd6d8bf019f5832102313b3 5fdf7af967980d29e684c508c90e11d99b10cab20ef477c9e63d9bf7bf7ffffffffd38e64afa39d d966f96e07bf56ae44bc3d402630771480f461389edff8a0051e010000006a4730440220645a7a2 5ebb00194a3b2f940d5618d021f513c2dd9bdc0504f623824e9845d8e0220077af01808e98b7ca9 7d2927243f9beb8cbd48e85d07dde26ea46c2e79d6c2ee832102e90fb489e28444cdfd85057fcce 5f6d6ab1ba525acf570a7ffa355dbb7f21162ffffffff0258980000000000001976a914c103e57c 094061209b419e5ca559704a8a22f3f988ac28a00000000000001976a914d80f48340dd7ee6c7fa e287342d3eeb1d4d887e288ac00000000

When I verify the signatures with a code that I created (that also reconstructs the Hash-Preimage of each one; I have checked that the Hash-Preimage reconstructed for each input, is the same one as the Hash-Preimage of the transaction separately), the signatures are valid.

But when I try to broadcast it, the following error message appears: (code 26) Failed to broadcast transaction, reason: mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)

What could be happening?
Jump to: