question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

TransactionBuilder.fromTransaction (Transaction.fromHex ()) and segwit input signing

See original GitHub issue

Version: Bitcoinjs-0.3.2 and also bitcoinjs/bitcoinjs-lib#fixes

I’m trying to integrate segwit in my walleting software, but I’m stuck in one problem. The flow is the following:

  1. I create a segwit address from 2of3 p2sh keys
  2. I send some testnet coin to this address
  3. I get the unspent tx
  4. I create the tx with this unspent as input
  5. I generate the incomplete hex, passing it to another software
  6. I then try to sign the transaction with the following code:
var signTxSegwit = function (txhex, pubkeys, privkey, utxos, n) {
var txb = new bitcoinjs.TransactionBuilder.fromTransaction (
	bitcoinjs.Transaction.fromHex (txhex), bitcoinjs.networks.testnet);
var upair = bitcoinjs.ECPair.fromWIF(privkey, bitcoinjs.networks.testnet);
var pubkeys_raw = pubkeys.map(function (hex) { return new Buffer(hex, 'hex'); });
var witnessScript = bitcoinjs.script.multisig.output.encode (n, pubkeys_raw);
var redeemScript = bitcoinjs.script.witnessScriptHash.output.encode (bitcoinjs.crypto.sha256(witnessScript));
var scriptPubKey = bitcoinjs.script.scriptHash.output.encode (bitcoinjs.crypto.hash160(redeemScript));
var address = bitcoinjs.address.fromOutputScript(scriptPubKey, bitcoinjs.networks.testnet);
	
for (var j = 0; j < txb.tx.ins.length; j++) {
	txb.sign (j, upair, redeemScript, null, parseInt (utxos[j].value * 100000000), witnessScript);
}

var tx = txb.build ();
return tx.toHex ();
}

The program fail at txb.sign, with this error:

   Message:
     Error: Expected property "2" of type Satoshi, got undefined
   Stacktrace:
     Error
    at TfTypeError.Error (native)
    at new TfTypeError (/home/dakk/Repositories/MyRepos/backend/node_modules/typeforce/errors.js:43:24)
    at typeforce (/home/dakk/Repositories/MyRepos/backend/node_modules/typeforce/index.js:193:11)
    at /home/dakk/Repositories/MyRepos/backend/node_modules/typeforce/index.js:152:18
    at Array.every (native)
    at _tuple (/home/dakk/Repositories/MyRepos/backend/node_modules/typeforce/index.js:150:20)
    at typeforce (/home/dakk/Repositories/MyRepos/backend/node_modules/typeforce/index.js:191:9)
    at Transaction.hashForWitnessV0 (/home/dakk/Repositories/MyRepos/backend/node_modules/bitcoinjs-lib/src/transaction.js:320:3)
    at TransactionBuilder.sign (/home/dakk/Repositories/MyRepos/backend/node_modules/bitcoinjs-lib/src/transaction_builder.js:692:29)
    at signTxSegwit (/home/dakk/Repositories/MyRepos/backend/tests/api/middlewares/wallet.js:79:7)

Then I jumped to bitcoinjs-lib/src/transaction_builder:692 and I found this:

signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, input.value, hashType)

Which is using input.value; so I guessed prepareInput should inject this field, and I’ve found that it injects input.value if witnessScript and reedemScript are not undefined; but they are defined in my example, right? I can’t figure out what’s the problem here

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
dcousenscommented, Sep 26, 2017

Reproduced with

// Bitcoin address : mhqo9zJRm4gBYFmBD6kCVCfZL3JS5UqLmj
let key1 = {
  priv: 'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
  pub: '03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877'
}
//  Bitcoin address : mpSAvmKXAE8B6H6bgLnGBG8iyC6tQgEy9D
let key2 = {
  priv: 'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
  pub: '020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0'
}
//  Bitcoin address : mq1HD5wiNLCNQv8u9wdwLvRH5JiMbxJHR4
let key3 = {
  priv: 'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF',
  pub: '02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149'
}

let bitcoin = require('./')
let keyPairs = [key1.priv, key2.priv, key3.priv].map(function (wif) {
  return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet)
})
let pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })

let itxhex
{
  let witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
  let witnessScriptHash = bitcoin.crypto.sha256(witnessScript)

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

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

  console.log(P2SHaddress)
  console.log(scriptPubKey)

  // 2Mv8kEd3D7PaYciMYMgQU3zGTv5RgsYDUDy
  let txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)

  txb.addInput('f3e785dff9694a463f5f17570c2940aa8e65117ae69184e5fa8de69ac4ae3481', 1)
  txb.addOutput(scriptPubKey, (1000000 - 10000) / 2)
  txb.addOutput('n2iptWzMeDb35222vkp3SA9ytsac3skwjU', (1000000 - 10000) / 2)

  txb.sign(0, keyPairs[0], redeemScript, null, 1000000, witnessScript)
  itxhex = txb.buildIncomplete().toHex()
}

{
  let txb = bitcoin.TransactionBuilder.fromTransaction(bitcoin.Transaction.fromHex(itxhex), bitcoin.networks.testnet)

  let witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
  let redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
//    let scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
//    let address = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)

  txb.sign(0, keyPairs[1], redeemScript, null, 1000000, witnessScript)

  let tx = txb.build()
  let txhex = tx.toHex()
  console.log(txhex)
}

Which isolates the variables with block scoping.

Will investigate.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to use the bitcoinjs-lib.TransactionBuilder function in ...
To help you get started, we've selected a few bitcoinjs-lib.TransactionBuilder examples, based on popular ways it is used in public projects.
Read more >
How do you switch your bitcoinjs integrationfrom ...
You're only signing the first input? tx.sign(0, owner); Usually ... Segwit inputs can be simpler but they can also be created using the...
Read more >
Creating and Signing a SegWit Transaction from Scratch
Step by Step. We previously created and signed a P2PKH transaction from scratch. This time we will create a SegWit transaction with 3...
Read more >
api documentation for bitcoinjs-lib (v3.0.2)
TransactionBuilder.prototype.sign (vin, keyPair, redeemScript, hashType, witnessValue, ... function bitcoinjs-lib.input.decode (buffer, allowIncomplete) ...
Read more >
A Beginner's Guide to Segregated Witness (SegWit)
By removing the signature data from the transaction input, more transactions can be stored within a single block. Transactions consist of two ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found