Closed ghost closed 7 years ago
This has to do with the way multisig signing works in bcoin. Multisig signatures need to maintain the same order as the keys presented in the redeem script.
So, when you sign a multisig, bcoin will create "signature slots" in the input script during the "templating" process. These slots are just OP_0
's. So, if it's a 2-of-3, bcoin creates 3 signature slots (even though only 2 signatures are ultimately needed). This is so signatures can be properly ordered. Whenever a different signer calls mtx.sign
, one of the OP_0
's will be replaced with their signature, corresponding to the index of their key in the redeem script. Once 2 signatures are added, the final OP_0
is removed since it isn't necessary anymore and was really just there to preserve order (since we didn't know who else might sign).
This is a lot better than bitcoind's "merge" signing, where it creates a map of signatures/keys, and tries to verify every signature against every key to determine the order.
Your final input script is only half-signed. 1 of 2 have signed (note the 2 OP_0
's in the middle):
<Script: OP_0 0x48 0x3045022100908db44b379bf4b4d561ace38995f76f0c55c748cdf8ed0b1bfd9a00b512662b022038f6350b101dfc02ac73cc407657d37d6190ef668be06fe04b0d2716d169a67a01 OP_0 OP_0 OP_PUSHDATA1 0x69 0x5221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae>
It's failing with SIG_NULLDUMMY
because the top stack item isn't the first OP_0
when the multisig verification loop finishes (due to the extra OP_0
we have as a signature slot still). If you were to execute this script with just consensus standards, you would see the script fail with EVAL_FALSE
.
If you want to check whether a transaction is fully signed, mtx.isSigned()
is useful.
In other words, you just need to sign it with one of the 2 other keys.
@chjj I signed when the other key and worked. the verify does not complain anymore. awesome thanks.
but what if I need to pass a valid half signed tx to another cosigner who may not be using bcoin (like an electrum wallet)? wouldn't the bcoin way of signing broke compatibility when trying to sign?
@jmliz, it all depends on how the wallet handles multisig signing. I'm not sure how electrum would handle it, but bitcoind would need to do the transaction merging stuff. The fact that this isn't really a standardized thing is what makes layer 2 protocols for doing multisig so useful (Copay, for example, solves this problem). If you need interoperability with a specific implementation, I would recommend creating the input script yourself and making calls to mtx.signature()
directly.
@chjj ok thank you very much. such useful information. I'm closing since my problem is solved. I'll test compatibility with electrum and maybe learn how to use the new plugin module for copay. thank you. awesome lib!!! :D
@chjj sidenote on interop with Electrum. found this spesmilo/electrum#2478 it seem they use different sig slots and redeem scripts.
I'm trying to import a transaction to bcoin and use the spv wallet to get the utxos from the network (Coins) and fill the tx to be able to sign them. Included error, input script sample, code and output at the end.
Also the final signed raw tx when deserialized the inputs appear to be signed by 3 of the multisig keys, while in the code I only use 1 of them. Also there's only 3 inputs. ??https://coinb.in/?verify=0100000003f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b00000000b7004830450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffffb7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed3367900000000b700483045022100908db44b379bf4b4d561ace38995f76f0c55c748cdf8ed0b1bfd9a00b512662b022038f6350b101dfc02ac73cc407657d37d6190ef668be06fe04b0d2716d169a67a0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffff88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a01000000b700483045022100f8420cb8a257043108deaa37e8d432cb8df9795704c06dbab950587457a7bc0e022035aea4a6c55155b6732e677e8865365f68e797ca7d24c452ff14bc66e1f332ab0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffff0250a50500000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88acf86b0000000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac00000000#verify coinbin link??.
error:
That error is thrown at
script.js
when executing the input and not finding the extra dummy value for multisig scripts. The mtx.sign() function does not complain though. I'm not sure what's going on here.input script sample:
<Script: OP_0 0x48 0x30450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd01 OP_0 OP_0 OP_PUSHDATA1 0x69 0x5221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae>
code:
output: