bcoin-org / bcoin

Javascript bitcoin library for node.js and browsers
https://bcoin.io
Other
3.01k stars 811 forks source link

DUMMY error on multisig #218

Closed ghost closed 7 years ago

ghost commented 7 years ago

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:

{ [Error: SIG_NULLDUMMY (op=OP_CHECKMULTISIG, ip=5)]
  type: 'ScriptError',
  code: 'SIG_NULLDUMMY',
  message: 'SIG_NULLDUMMY (op=OP_CHECKMULTISIG, ip=5)',
  op: 174,
  ip: 5 }

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:

const
    config = require('../config/config'),
    async = require('async'),
    log = require('../config/log'),
    bcoin  = require('bcoin').set('testnet'),
    http = require('http'),
    wal = require('./wal');
    rawtx = "0100000003f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b0000000000ffffffffb7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed336790000000000ffffffff88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a0100000000ffffffff0250a50500000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88acf86b0000000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac00000000",
    pubkeys = [new Buffer("020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f", 'hex'), new Buffer("038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a968", 'hex'), new Buffer("03ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a2", 'hex')],
    mkey = "tprv8ZgxMBicQKsPdAATA2qvUoBcqwYetrgij9NrqBZzhvwHiWZnVgSDLjj7XEdSJvN5oguCgMMsNc86Mb1mRFA1AEYq6wbEhsjjX6xv16C831L",
    path = 15,
    walletId = "592078b78b7e6fb79a91bfe3";

// recreate mstx from raw
var mstx = new bcoin.mtx.fromRaw(rawtx, 'hex');

console.log('\n------------ ORIGINAL TX -----------\n ');
console.log(mstx);
console.log('\n------------coinview------------------\n');
console.log(mstx.view);
console.log('\n-------------------------------------\n');

// create keyring with pk
var master = new bcoin.hd.PrivateKey.fromBase58(mkey);
// derive path for this escrow
var dkey = master.derive("m/44'/1'/0'/0/" + path);

// create signing keyring
var kr = new bcoin.keyring(dkey);

var sc = new bcoin.script.fromMultisig(2, 3, pubkeys);
kr.script = sc;
console.log('=======================');
console.log(kr);

wal.spv.open().then(function() {
    wal.spv.connect().then(function() {
        wal.spv.startSync();
        // get utxos (coins)
        wal.walletdb.get(walletId).then(function(wallet) {
            wallet.getCoins().then(function(coins) {
                try {
                    async.each(coins, function(coin, cb) {

                            mstx.view.addCoin(coin);
                            log.info(coin);
                            cb();

                    }, function(err) {
                        if(err) {
                            var msg = 'Error funding tx - ' + err;
                            log.info(msg);
                        }

                        console.log(JSON.stringify(mstx.view));

                        // finally sign the tx
                        mstx.sign(kr);

                        log.info('--------------- SIGNED NON FINAL TX: -------------------\n' + JSON.stringify(mstx) + '\n-------------------------\n\n');

                        var fmstx = mstx.toTX();
                        console.log(fmstx.inputs[0].script);
                        if(!mstx.verify()) {
                            log.error('TX is not valid!!');
                        }

                        log.info('--------------- SIGNED FINAL TX: -------------------\n' + JSON.stringify(fmstx) + '\n-------------------------\n\n');

                        var rawftx = fmstx.toRaw().toString('hex');

                        console.log('--------------- SIGNED RAW FINAL TX: -------------------\n' + rawftx + '\n-------------------------');
                        wal.spv.close();
                    });
                } catch(err) {
                    log.error(err);
                    wal.spv.close();
                }
            });
        });
    });
});

output:


------------ ORIGINAL TX -----------

{ hash: '41704e263cc2a933fc9f7ef33b59841beb823ceafb4e80e6588ae3800ca730f6',
  witnessHash: '41704e263cc2a933fc9f7ef33b59841beb823ceafb4e80e6588ae3800ca730f6',
  size: 201,
  virtualSize: 201,
  value: '0.0039764',
  fee: '0.0',
  rate: '0.0',
  minFee: '0.00000201',
  height: -1,
  block: null,
  ts: 0,
  date: null,
  index: -1,
  version: 1,
  flag: 1,
  inputs:
   [ { type: 'nonstandard',
       subtype: undefined,
       address: undefined,
       script: <Script: >,
       witness: <Witness: >,
       redeem: undefined,
       sequence: 4294967295,
       prevout: <Outpoint: 3bfbec327610e3fdda38f8918dce16777919de3a60cfe6b2b009bf2c6ab02af4/0>,
       coin: null },
     { type: 'nonstandard',
       subtype: undefined,
       address: undefined,
       script: <Script: >,
       witness: <Witness: >,
       redeem: undefined,
       sequence: 4294967295,
       prevout: <Outpoint: 7936d31e866df04ea9f6bc6df92890e5d77844d4ff8c3ff8ea5f5ba0dbe3ceb7/0>,
       coin: null },
     { type: 'nonstandard',
       subtype: undefined,
       address: undefined,
       script: <Script: >,
       witness: <Witness: >,
       redeem: undefined,
       sequence: 4294967295,
       prevout: <Outpoint: 4a1c513428082efe006c73ee8fb187d0ad6aced4bf7d71a6468f8b736eecb488/1>,
       coin: null } ],
  outputs:
   [ { type: 'pubkeyhash',
       value: '0.0037',
       script: <Script: OP_DUP OP_HASH160 0x14 0xb27a3b99a2bfc9848b699127b2e1481aa8bfab2f OP_EQUALVERIFY OP_CHECKSIG>,
       address: <Address: type=pubkeyhash version=-1 base58=mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf> },
     { type: 'pubkeyhash',
       value: '0.0002764',
       script: <Script: OP_DUP OP_HASH160 0x14 0xb27a3b99a2bfc9848b699127b2e1481aa8bfab2f OP_EQUALVERIFY OP_CHECKSIG>,
       address: <Address: type=pubkeyhash version=-1 base58=mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf> } ],
  locktime: 0 }

------------coinview------------------

CoinView { map: {}, undo: UndoCoins { items: [] } }

-------------------------------------

=======================
{ network: 'testnet',
  witness: false,
  nested: false,
  publicKey: '020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f',
  script: '5221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae',
  program: null,
  type: 'scripthash',
  address: '2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA' }
2017-05-26T17:15:23.707Z - warn: --- Got Tx hash: 88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a, index: 1, height: 1125623 -----
2017-05-26T17:15:23.710Z - info:  version=1, height=1125623, value=200000, 0=169, 1=20, 2=253, 3=228, 4=162, 5=68, 6=142, 7=193, 8=143, 9=137, 10=158, 11=14, 12=229, 13=216, 14=177, 15=7, 16=255, 17=136, 18=251, 19=65, 20=52, 21=46, 22=135, code=[value=169, data=null, value=20, 0=253, 1=228, 2=162, 3=68, 4=142, 5=193, 6=143, 7=137, 8=158, 9=14, 10=229, 11=216, 12=177, 13=7, 14=255, 15=136, 16=251, 17=65, 18=52, 19=46, value=135, data=null], coinbase=false, hash=88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a, index=1
2017-05-26T17:15:23.712Z - warn: --- Got Tx hash: ac7a0198501fc3b6cb3c660db4981a2d3476c5b40f978904fe94e1b2f9e4f03e, index: 0, height: 1125623 -----
2017-05-26T17:15:23.712Z - info:  version=1, height=1125623, value=200000, 0=169, 1=20, 2=253, 3=228, 4=162, 5=68, 6=142, 7=193, 8=143, 9=137, 10=158, 11=14, 12=229, 13=216, 14=177, 15=7, 16=255, 17=136, 18=251, 19=65, 20=52, 21=46, 22=135, code=[value=169, data=null, value=20, 0=253, 1=228, 2=162, 3=68, 4=142, 5=193, 6=143, 7=137, 8=158, 9=14, 10=229, 11=216, 12=177, 13=7, 14=255, 15=136, 16=251, 17=65, 18=52, 19=46, value=135, data=null], coinbase=false, hash=ac7a0198501fc3b6cb3c660db4981a2d3476c5b40f978904fe94e1b2f9e4f03e, index=0
2017-05-26T17:15:23.713Z - warn: --- Got Tx hash: b7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed33679, index: 0, height: 1125583 -----
2017-05-26T17:15:23.713Z - info:  version=1, height=1125583, value=380000, 0=169, 1=20, 2=253, 3=228, 4=162, 5=68, 6=142, 7=193, 8=143, 9=137, 10=158, 11=14, 12=229, 13=216, 14=177, 15=7, 16=255, 17=136, 18=251, 19=65, 20=52, 21=46, 22=135, code=[value=169, data=null, value=20, 0=253, 1=228, 2=162, 3=68, 4=142, 5=193, 6=143, 7=137, 8=158, 9=14, 10=229, 11=216, 12=177, 13=7, 14=255, 15=136, 16=251, 17=65, 18=52, 19=46, value=135, data=null], coinbase=false, hash=b7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed33679, index=0
2017-05-26T17:15:23.714Z - warn: --- Got Tx hash: f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b, index: 0, height: 1125580 -----
2017-05-26T17:15:23.714Z - info:  version=1, height=1125580, value=10000, 0=169, 1=20, 2=253, 3=228, 4=162, 5=68, 6=142, 7=193, 8=143, 9=137, 10=158, 11=14, 12=229, 13=216, 14=177, 15=7, 16=255, 17=136, 18=251, 19=65, 20=52, 21=46, 22=135, code=[value=169, data=null, value=20, 0=253, 1=228, 2=162, 3=68, 4=142, 5=193, 6=143, 7=137, 8=158, 9=14, 10=229, 11=216, 12=177, 13=7, 14=255, 15=136, 16=251, 17=65, 18=52, 19=46, value=135, data=null], coinbase=false, hash=f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b, index=0
{"map":{"88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a":{"version":1,"hash":"88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a","height":1125623,"coinbase":false,"outputs":[null,{"offset":0,"size":0,"raw":null,"output":{"value":"0.002","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},"spent":false}]},"ac7a0198501fc3b6cb3c660db4981a2d3476c5b40f978904fe94e1b2f9e4f03e":{"version":1,"hash":"ac7a0198501fc3b6cb3c660db4981a2d3476c5b40f978904fe94e1b2f9e4f03e","height":1125623,"coinbase":false,"outputs":[{"offset":0,"size":0,"raw":null,"output":{"value":"0.002","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},"spent":false}]},"b7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed33679":{"version":1,"hash":"b7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed33679","height":1125583,"coinbase":false,"outputs":[{"offset":0,"size":0,"raw":null,"output":{"value":"0.0038","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},"spent":false}]},"f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b":{"version":1,"hash":"f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b","height":1125580,"coinbase":false,"outputs":[{"offset":0,"size":0,"raw":null,"output":{"value":"0.0001","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},"spent":false}]}},"undo":{"items":[]}}
2017-05-26T17:15:23.722Z - info: --------------- SIGNED NON FINAL TX: -------------------
{"hash":"e0febcc43099b505892ebfbfa89db1cb6960ed2f8fbce3abf6079ed0699c2065","witnessHash":"e0febcc43099b505892ebfbfa89db1cb6960ed2f8fbce3abf6079ed0699c2065","fee":"0.0019236","rate":"0.0025648","ps":1495818923,"version":1,"flag":1,"inputs":[{"prevout":{"hash":"3bfbec327610e3fdda38f8918dce16777919de3a60cfe6b2b009bf2c6ab02af4","index":0},"script":"004830450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"coin":{"version":1,"height":1125580,"value":"0.0001","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA","coinbase":false}},{"prevout":{"hash":"7936d31e866df04ea9f6bc6df92890e5d77844d4ff8c3ff8ea5f5ba0dbe3ceb7","index":0},"script":"00483045022100908db44b379bf4b4d561ace38995f76f0c55c748cdf8ed0b1bfd9a00b512662b022038f6350b101dfc02ac73cc407657d37d6190ef668be06fe04b0d2716d169a67a0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"coin":{"version":1,"height":1125583,"value":"0.0038","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA","coinbase":false}},{"prevout":{"hash":"4a1c513428082efe006c73ee8fb187d0ad6aced4bf7d71a6468f8b736eecb488","index":1},"script":"00483045022100f8420cb8a257043108deaa37e8d432cb8df9795704c06dbab950587457a7bc0e022035aea4a6c55155b6732e677e8865365f68e797ca7d24c452ff14bc66e1f332ab0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"coin":{"version":1,"height":1125623,"value":"0.002","script":"a914fde4a2448ec18f899e0ee5d8b107ff88fb41342e87","address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA","coinbase":false}}],"outputs":[{"value":"0.0037","script":"76a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac","address":"mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf"},{"value":"0.0002764","script":"76a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac","address":"mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf"}],"locktime":0}
-------------------------

<Script: OP_0 0x48 0x30450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd01 OP_0 OP_0 OP_PUSHDATA1 0x69 0x5221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae>
//modified script.js to print error...
{ [Error: SIG_NULLDUMMY (op=OP_CHECKMULTISIG, ip=5)]
  type: 'ScriptError',
  code: 'SIG_NULLDUMMY',
  message: 'SIG_NULLDUMMY (op=OP_CHECKMULTISIG, ip=5)',
  op: 174,
  ip: 5 }
2017-05-26T17:15:23.727Z - error: TX is not valid!!
2017-05-26T17:15:23.728Z - info: --------------- SIGNED FINAL TX: -------------------
{"hash":"e0febcc43099b505892ebfbfa89db1cb6960ed2f8fbce3abf6079ed0699c2065","witnessHash":"e0febcc43099b505892ebfbfa89db1cb6960ed2f8fbce3abf6079ed0699c2065","ps":1495818923,"version":1,"flag":1,"inputs":[{"prevout":{"hash":"3bfbec327610e3fdda38f8918dce16777919de3a60cfe6b2b009bf2c6ab02af4","index":0},"script":"004830450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},{"prevout":{"hash":"7936d31e866df04ea9f6bc6df92890e5d77844d4ff8c3ff8ea5f5ba0dbe3ceb7","index":0},"script":"00483045022100908db44b379bf4b4d561ace38995f76f0c55c748cdf8ed0b1bfd9a00b512662b022038f6350b101dfc02ac73cc407657d37d6190ef668be06fe04b0d2716d169a67a0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"},{"prevout":{"hash":"4a1c513428082efe006c73ee8fb187d0ad6aced4bf7d71a6468f8b736eecb488","index":1},"script":"00483045022100f8420cb8a257043108deaa37e8d432cb8df9795704c06dbab950587457a7bc0e022035aea4a6c55155b6732e677e8865365f68e797ca7d24c452ff14bc66e1f332ab0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253ae","witness":"00","sequence":4294967295,"address":"2NGPgqaN45VEihGsvbzjFuuzgKZf6H3TYCA"}],"outputs":[{"value":"0.0037","script":"76a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac","address":"mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf"},{"value":"0.0002764","script":"76a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac","address":"mwnf15rmXb6dDnBb4GJbJ7CAkWNdVgiLrf"}],"locktime":0}
-------------------------

--------------- SIGNED RAW FINAL TX: -------------------
0100000003f42ab06a2cbf09b0b2e6cf603ade19797716ce8d91f838dafde3107632ecfb3b00000000b7004830450221008cc474796527bccb32a92af08445e9f986f2d8bba6a72c1d2aa5c17ae97c335902201984de66f8b80bdddd77086781512162c4c5363b7060142b91dffa52919369dd0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffffb7cee3dba05b5feaf83f8cffd44478d7e59028f96dbcf6a94ef06d861ed3367900000000b700483045022100908db44b379bf4b4d561ace38995f76f0c55c748cdf8ed0b1bfd9a00b512662b022038f6350b101dfc02ac73cc407657d37d6190ef668be06fe04b0d2716d169a67a0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffff88b4ec6e738b8f46a6717dbfd4ce6aadd087b18fee736c00fe2e082834511c4a01000000b700483045022100f8420cb8a257043108deaa37e8d432cb8df9795704c06dbab950587457a7bc0e022035aea4a6c55155b6732e677e8865365f68e797ca7d24c452ff14bc66e1f332ab0100004c695221020f3a7fa2e0fba4880d99e9a3c298ff58cb99614ddd61021d69878ae741c8f84f21038988c8f665211d922b4152e3ffdf1fe37c6c8bbd6f7bf65199d98c382aa7a9682103ac766f81a96fd2f5aa24c0e4db959b9eb192be56656761ffff5bf4c9c04690a253aeffffffff0250a50500000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88acf86b0000000000001976a914b27a3b99a2bfc9848b699127b2e1481aa8bfab2f88ac00000000
-------------------------
chjj commented 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.

ghost commented 7 years ago

@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?

chjj commented 7 years ago

@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.

ghost commented 7 years ago

@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

ghost commented 7 years ago

@chjj sidenote on interop with Electrum. found this spesmilo/electrum#2478 it seem they use different sig slots and redeem scripts.