I'm trying to learn the Bitcoin protocol by implementing it, and I've got OP_CHECKSIG
working (following instructions in https://en.bitcoin.it/wiki/OP_CHECKSIG), but I can't get an transaction input using OP_CHECKMULTISIG
to pass signature verification.
Specifically, I'm stuck with the second tx_input of transaction eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb, and I suspect that the culprit is subscript (the one to replace signature script in current transaction).
Here's how subscript is computed in my implementation.
First, generate the script by concatenating [sigScript][OP_CODESEPARATOR][pubkeyScript]
(I understand that script execution has evolved from this).
So a (parsed) script for the input would be like this:
Frame 00: 0(00)
Frame 01:
0000 - 30 44 02 20 27 6d 6d ad 3d ef a3 7b 5f 81 ad d3
0010 - 99 2d 51 0d 2f 44 a3 17 fd 85 e0 4f 93 a1 e2 da
0020 - ea 64 66 02 02 20 0f 86 2a 0d a6 84 24 93 22 ce
0030 - b8 ed 84 2f b8 c8 59 c0 cb 94 c8 1e 1c 53 08 b4
0040 - 86 81 57 a4 28 ee 01 END
Frame 02: OP_CODESEPARATOR(0xab)
Frame 03: 1(0x51)
Frame 04:
0000 - 02 32 ab dc 89 3e 7f 06 31 36 4d 7f d0 1c b3 3d
0010 - 24 da 45 32 9a 00 35 7b 3a 78 86 21 1a b4 14 d5
0020 - 5a END
Frame 05: 1(0x51)
Frame 06: OP_CHECKMULTISIG(0xae)
Frame 07: OP_CODESEPARATOR(0xab)
Frame 08:
0000 - 2a 9b c5 44 7d 66 4c 1d 01 41 39 2a 84 2d 23 db
0010 - a4 5c 4f 13 END
Frame 09: OP_NOP2/OP_CHECKLOCKTIMEVERIFY(0xb1)
Frame 10: OP_DROP(0x75)
Then, I create the subscript from the closest OP_CODESEPARATOR
before the OP_CHECKMULTISIG
that I am executing till the end of the script. So, I include Frame 03 to Frame 10.
Then, I remove other OP_CODESEPARATOR
s in the script, which is Frame 07.
That means these frames should compose the subscript:
Frame 03: 1(0x51)
Frame 04:
0000 - 02 32 ab dc 89 3e 7f 06 31 36 4d 7f d0 1c b3 3d
0010 - 24 da 45 32 9a 00 35 7b 3a 78 86 21 1a b4 14 d5
0020 - 5a END
Frame 05: 1(0x51)
Frame 06: OP_CHECKMULTISIG(0xae)
Frame 08:
0000 - 2a 9b c5 44 7d 66 4c 1d 01 41 39 2a 84 2d 23 db
0010 - a4 5c 4f 13 END
Frame 09: OP_NOP2/OP_CHECKLOCKTIMEVERIFY(0xb1)
Frame 10: OP_DROP(0x75)
Serialized, the final subscript looks like this:
0000 - 51 21 02 32 ab dc 89 3e 7f 06 31 36 4d 7f d0 1c
0010 - b3 3d 24 da 45 32 9a 00 35 7b 3a 78 86 21 1a b4
0020 - 14 d5 5a 51 ae 14 2a 9b c5 44 7d 66 4c 1d 01 41
0030 - 39 2a 84 2d 23 db a4 5c 4f 13 b1 75
However, when this subscript is used to replace signature script, and eventually generate hash, the ecdsa_verify function reports that signature verification fails (but the inputs are legal).
Since the same procedure works for OP_CHECKSIG
, I probably missed something obvious, but I couldn't figure this out reading the original Satoshi code, the current implementation, or Bitcoin Wiki.
If it helps, my code for OP_CHECKMULTISIG is here: https://github.com/blaesus/tinybtc/blob/checkmultisig/src/script.c#L687
A more simplistic version (using prevTx.pubkeyScript as subscript) doesn't yield valid results either: https://github.com/blaesus/tinybtc/blob/validate/src/script.c#L344