bitcoinjs-lib: Can't sign P2SH(P2WPKH) transaction built with CoinSelect and TransactionBuilder not working

I am trying to build a transaction and everything seems to be working well up until the point where I sign the transaction. I keep getting “scripthash not supported” but I am not sure what I am doing wrong. I followed the example from here https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions.js#L143 closely, with the main difference being that I am using CoinSelect to choose the utxos for me. I’ve posted my code below, any help would be greatly appreciated 😃

`const bitcoin = require(‘bitcoinjs-lib’) let network = bitcoin.networks.bitcoin

        const getUtxos =
            util
                .promisify(this.network.provider.insight.getUtxos)
                .bind(this.network.provider.insight)
        const utxos = await to(
            getUtxos({addresses: from, minconf: this.network.provider.minConf})
        )

        if (utxos.data.length === 0)
            return({success: false, error: `No confirmed unspent transactions found: ${from}`})

        let jsonUtxos = []
        utxos.data.forEach(utxo => {
            let jsonUtxo = utxo.toJSON()
            jsonUtxo.value = utxo.satoshis
            jsonUtxos.push(jsonUtxo)
        })

        let keyPair = bitcoin.ECPair.fromWIF(key, network)
        const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network })
        const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network })

        let amountInSatoshis = this.network.provider.bitcore.Unit.fromBTC(amount).toSatoshis()

        let coinSelect = require('coinselect')
        let feeRate = 110

        let targets = [{
                address: _to,
                value: amountInSatoshis
            }]

        let { inputs, outputs, fee} = coinSelect(jsonUtxos, targets, feeRate)
        if (!inputs || !outputs) return

        let txb = new bitcoin.TransactionBuilder(network)

        inputs.forEach(input => txb.addInput(input.txid, input.vout))
        outputs.forEach(output => {
            if (!output.address) {
                output.address = from
            }
            txb.addOutput(output.address, output.value)
        })

        txb.sign(0, keyPair, p2sh.redeem.output, null, inputs.value) // <-- scripthash not supported
        
        const tx = txb.build()
        const txid = tx.toHex()`

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 18 (10 by maintainers)

Most upvoted comments

If I do this it seems to work:

txb.sign(0, keyPair, p2sh.redeem.output, null, inputs[0].value)
txb.sign(1, keyPair, p2sh.redeem.output, null, inputs[1].value)

I could handle this with a loop of course, but is it correct to sign for each UTXO input like this?

yes. you must loop over the inputs.

check the input a bunch of places and see where the input loses input.value…

Maybe insight is giving a bad value for inputs.value???

shouldn’t it be inputs[0].value?