Bitcoinjs-lib: BitcoinJs-lib Multisig Multi-input Raw Transaction Creation

Created on 26 Mar 2018  路  12Comments  路  Source: bitcoinjs/bitcoinjs-lib

I can not construct this raw transaction correctly:

var keyPairs = [
    'cTFWphyQSKUp9RNEftrXgbgbiTg49wz4wfhrAzmutigyjxUw4DqD',
    'cQtNm3feFWK5hzR78wUtAowA8pqYDVJsdSVnm4b8qDExEmMvfCNs',
    'cTLCTCWSqoBziY51yHNx1uF2PpEGRZoQHdWsGGpjjmw15YpsFZ9B'
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet) })

var transvalue0=63000000;
var transvalue1=30500000;
var pubKeys = [
      '029d5ea4ef0bbf9adb9cda8ab2eacd5c440f4e36999582e7484f27fef871011c5f',
      '02bdffd977d271c0a72d2c9e563fdab34d94b7f7f9e69f64ca6cc0378bcbb18fa3',
      '02f5c569bf4fd8ebb861507c238e2c2300c152edc2544d068d83e8ce75411a683e'
    ].map(function (hex) { return Buffer.from(hex, 'hex') })

var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
var witnessScriptHash = bitcoin.crypto.sha256(witnessScript)

var redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)

var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)        


var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)

txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", 0);
txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98", 0);


txb.addOutput ("mqgSLgUyDSwPG387ePKKXSLMXnWKrxDur5", 94500000-1000);

txb.sign(0, keyPairs[0], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[1], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[2], redeemScript, null, transvalue0, witnessScript);

txb.sign(1, keyPairs[0], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[1], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[2], redeemScript, null, transvalue1, witnessScript);

var tx = txb.build();
var txhex = tx.toHex();

console.log (txhex);

I get this error when I go to broadcast this transaction:

Error sending transaction: Error running script for input 0 referencing 65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3 at 0: witness program does not match script hash.
I am pretty sure that It has something to do with the way that I am signing the transactions, since I can decode the transaction just fine. I tried to go off this example:
example

how to / question / docs

Most helpful comment

https://testnet.smartbit.com.au/tx/8e8e170ff788a60f793b902dc060e9cf0aa8f22d796785f9ffe31c91014a5110

Sent.

Reasons:

  1. addInput needed scriptPubkey
  2. the value for transvalue0 was incorrect (you wrote 0.63 but it was actually 0.64)

Below is the code I used to generate the valid transaction.

var bitcoin = require('bitcoinjs-lib')

var keyPairs = [
    'cTFWphyQSKUp9RNEftrXgbgbiTg49wz4wfhrAzmutigyjxUw4DqD',
    'cQtNm3feFWK5hzR78wUtAowA8pqYDVJsdSVnm4b8qDExEmMvfCNs',
    'cTLCTCWSqoBziY51yHNx1uF2PpEGRZoQHdWsGGpjjmw15YpsFZ9B'
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet) })

var transvalue0=64000000; // 65b...
//              ^^ This amount was originally 63, it should be 64
var transvalue1=30500000; // 246...
var pubKeys = [
      '029d5ea4ef0bbf9adb9cda8ab2eacd5c440f4e36999582e7484f27fef871011c5f',
      '02bdffd977d271c0a72d2c9e563fdab34d94b7f7f9e69f64ca6cc0378bcbb18fa3',
      '02f5c569bf4fd8ebb861507c238e2c2300c152edc2544d068d83e8ce75411a683e'
    ].map(function (hex) { return Buffer.from(hex, 'hex') })

var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
var witnessScriptHash = bitcoin.crypto.sha256(witnessScript)

var redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)

var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)        

console.log(P2SHaddress)

var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)

txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", 0, null, scriptPubKey);
txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98", 0, null, scriptPubKey);


txb.addOutput ("mqgSLgUyDSwPG387ePKKXSLMXnWKrxDur5", 94500000-1000);

txb.sign(0, keyPairs[0], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[1], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[2], redeemScript, null, transvalue0, witnessScript);

txb.sign(1, keyPairs[0], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[1], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[2], redeemScript, null, transvalue1, witnessScript);

var tx = txb.build();
var txhex = tx.toHex();

console.log (txhex);

All 12 comments

Pubkeys don鈥檛 match the privkeys

I think pubkeys are correct @dabura667 :

> bitcoin.ECPair.fromWIF ('cTFWphyQSKUp9RNEftrXgbgbiTg49wz4wfhrAzmutigyjxUw4DqD', bitcoin.networks.testnet).getPublicKeyBuffer().toString('hex')
'029d5ea4ef0bbf9adb9cda8ab2eacd5c440f4e36999582e7484f27fef871011c5f'
> bitcoin.ECPair.fromWIF ('cQtNm3feFWK5hzR78wUtAowA8pqYDVJsdSVnm4b8qDExEmMvfCNs', bitcoin.networks.testnet).getPublicKeyBuffer().toString('hex')
'02bdffd977d271c0a72d2c9e563fdab34d94b7f7f9e69f64ca6cc0378bcbb18fa3'
> bitcoin.ECPair.fromWIF ('cTLCTCWSqoBziY51yHNx1uF2PpEGRZoQHdWsGGpjjmw15YpsFZ9B', bitcoin.networks.testnet).getPublicKeyBuffer().toString('hex')
'02f5c569bf4fd8ebb861507c238e2c2300c152edc2544d068d83e8ce75411a683e'

Oh addInput are missing prevOutScript args.

Pass scriptPubKey

I tried this code:
txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", scriptPubKey, 0); txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98",scriptPubKey,0);
@dabura667 's suggestion. The transaction was not able to build. I tried several combinations also.

No.

Wrong order

txb.addInput(txid, vout, sequence, prevOutScript)

sequence can be null

@legenddgoon did that throw? It should have thrown a TypeError...

I tried this code:
txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", 0,null,scriptPubKey); txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98",0,null,scriptPubKey);
The transaction was able to build but gave me the same error when it was time to broadcast. Is there an example somewhere of a multisig of this type with multiple inputs? The wiki seems to only have single inputs. Thanks again for the help.

This code threw a type error
txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", 0,scriptPubKey); txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98",0,scriptPubKey);

https://testnet.smartbit.com.au/tx/8e8e170ff788a60f793b902dc060e9cf0aa8f22d796785f9ffe31c91014a5110

Sent.

Reasons:

  1. addInput needed scriptPubkey
  2. the value for transvalue0 was incorrect (you wrote 0.63 but it was actually 0.64)

Below is the code I used to generate the valid transaction.

var bitcoin = require('bitcoinjs-lib')

var keyPairs = [
    'cTFWphyQSKUp9RNEftrXgbgbiTg49wz4wfhrAzmutigyjxUw4DqD',
    'cQtNm3feFWK5hzR78wUtAowA8pqYDVJsdSVnm4b8qDExEmMvfCNs',
    'cTLCTCWSqoBziY51yHNx1uF2PpEGRZoQHdWsGGpjjmw15YpsFZ9B'
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet) })

var transvalue0=64000000; // 65b...
//              ^^ This amount was originally 63, it should be 64
var transvalue1=30500000; // 246...
var pubKeys = [
      '029d5ea4ef0bbf9adb9cda8ab2eacd5c440f4e36999582e7484f27fef871011c5f',
      '02bdffd977d271c0a72d2c9e563fdab34d94b7f7f9e69f64ca6cc0378bcbb18fa3',
      '02f5c569bf4fd8ebb861507c238e2c2300c152edc2544d068d83e8ce75411a683e'
    ].map(function (hex) { return Buffer.from(hex, 'hex') })

var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
var witnessScriptHash = bitcoin.crypto.sha256(witnessScript)

var redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)

var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)        

console.log(P2SHaddress)

var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)

txb.addInput("65b6f3b76e003a99df21ab66ffb7801196a39c4f9928c35b22edcb206279d5d3", 0, null, scriptPubKey);
txb.addInput("246b6859a969e3c406e167f72ff0b02e00c5576bfb0f69042317b997473dbe98", 0, null, scriptPubKey);


txb.addOutput ("mqgSLgUyDSwPG387ePKKXSLMXnWKrxDur5", 94500000-1000);

txb.sign(0, keyPairs[0], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[1], redeemScript, null, transvalue0, witnessScript);
txb.sign (0, keyPairs[2], redeemScript, null, transvalue0, witnessScript);

txb.sign(1, keyPairs[0], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[1], redeemScript, null, transvalue1, witnessScript);
txb.sign (1, keyPairs[2], redeemScript, null, transvalue1, witnessScript);

var tx = txb.build();
var txhex = tx.toHex();

console.log (txhex);

Thank you soo much.

Sorry to reopen this. Blockcypher also dose not broadcast these type of transactions on the testnet correctly yet. I had to use smart bit. Thanks for the help again.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thrastarson picture thrastarson  路  3Comments

askucher picture askucher  路  3Comments

itsMikeLowrey picture itsMikeLowrey  路  3Comments

rbndg picture rbndg  路  3Comments

hoshsadiq picture hoshsadiq  路  3Comments