bitcoinjs-lib: Error: Input #0 has witnessUtxo but non-segwit script:

I’m trying to sign a transaction but I’m getting below error:

Error: Input #0 has witnessUtxo but non-segwit script: a91455e9fceb916ad6cc5fc23b3a8bd2cc8955a436ed87

Below is my code:

const bitcoin = require('bitcoinjs-lib');
const request = require('request-promise-native');
// const net = bitcoin.networks.bitcoin;
const net = bitcoin.networks.testnet;

const API = net === bitcoin.networks.testnet
    ? 'https://test-insight.swap.online/insight-api'
    : 'https://insight.bitpay.com/api'

const fetchUnspents = (address) =>
    request(`${API}/addr/${address}/utxo/`).then(JSON.parse)


(async () => {
    const psbt = new bitcoin.Psbt({ network: net });
    const alice_pair = bitcoin.ECPair.fromWIF('cR6RdGAojE4TuzRSY16a92vPfKgdjUj3tjHmoaPRcHvxRpTMr8gy', net);
    const pubkeys = [alice_pair.publicKey].map(hex => Buffer.from(hex, 'hex'));
    const { address } = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2ms({ m: 1, pubkeys, network: net })});

    const unspents = await fetchUnspents(address);
    const totalAmount = unspents.reduce((summ, { satoshis }) => summ + satoshis, 0);
    const withdrawAmount = 0.001 * 100000000;
    const fee = 0.00001 * 100000000;
    const change = totalAmount - (withdrawAmount + fee);

    unspents.forEach(element => {
        psbt.addInput({
            hash: element.txid,
            index: element.vout,
            witnessUtxo: {
                script: Buffer.from(element.scriptPubKey, 'hex'),
                value: element.amount * 100000000
            },
            // redeemScript:Buffer.from(element.scriptPubKey)
        })
    });

    psbt.addOutput({
        address: '2NBJtjiL8kHb3vGW4b945rgSbh9zasAq7qB',
        value: withdrawAmount
    });

    psbt.addOutput({
        address: address,
        value: change
    });

    psbt.signInput(0, alice_pair);

    console.log('valid signature: ', psbt.validateSignaturesOfAllInputs());
    psbt.finalizeAllInputs();
    const rawHex = psbt.extractTransaction().toHex();
    console.log(rawHex);
})()

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (12 by maintainers)

Most upvoted comments

Hello,

I’m trying to do the same thing, but I have a mistake, if you have an idea : “Redeem script for input #0 doesn’t match the scriptPubKey in the prevout”

function scriptCheckerFactory(payment, paymentScriptName) {
   ...
    if (!scriptPubKey.equals(redeemScriptOutput)) {
      throw new Error(
        `${paymentScriptName} for input #${inputIndex} doesn't match the scriptPubKey in the prevout`,
      );
    }
}
scriptPubKey.toString("hex") -> "a914e1767896d84c2489a26666873fc29c864a03b82c87"
redeemScriptOutput.toString("hex") -> "a914f451b792d3f8cd8ba83ef6bed905a3c228dc2dd287"

My code:

    const idx = addrs.indexOf(input.address)
    //QhA84yRpiKszJSvKaDxa9GHwBRTsKHnQ7C
    const ecpair = Bitcoin.ECPair.fromWIF(addrsWallet[idx].private_key, this.network) 
    const pubkeys = [ecpair.publicKey]
    const p2shObj = Bitcoin.payments.p2sh({ redeem: Bitcoin.payments.p2ms(
        { m: 1, pubkeys, network: this.network })
    })
    const redeemScript = p2shObj.redeem.output      
    let rawTx="01000000000101282a14a07aa0ca74aa9db4918bb5dc75576795e985d44cea8c94e00189f8d67401000000171600148031e4abb080a77925c3e7818d7dc5787ffda60dffffffff0280841e000000000017a914b232f46999952516ef3c11c070d9a2af8cba1256874a324e3b0000000017a914e1767896d84c2489a26666873fc29c864a03b82c870247304402200f5c5943918ddbd8ffbf112008527c6dd92d0d65beac6556a7c1b4037dc9155702206362d1adf42c750c486970845a85b7cc6e3d3a10453e8bb001960397365fbc81012103dc63d1938cfa6574239042136990c5dfb2987a465fca2b567ac0fdee2bc60efd00000000"
    psbt.addInput({
        hash: input.txid,
        index: input.vout,                 
        witnessUtxo: {
            script: Buffer.from(input.scriptPubKey, 'hex'),
            value: input.value
        },
        //nonWitnessUtxo:  Buffer.from(rawTx, 'hex'),
        redeemScript: redeemScript,                   
    })
    psbt.signInput(0, ecpair)

if you have any suggestions… thanks

remove witnessUtxo you don’t need it. nonWitnessUtxo has all the info you need.

@rohitsahu21

const pubkeys = [alice_pair.publicKey].map(hex => Buffer.from(hex, 'hex'));

.publicKey already Buffer so above code will raise error. You can write like this

const pubkeys = [alice_pair.publicKey]

Above utxos is not witnessUtxo so you should use nonWitnessUtxo instead. Value of nonWitnessUtxo is Buffer of hex of previous raw tx

A sample inputData is

const p2shObj = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2ms({ m: 1, pubkeys, network: net })});
const redeemScript = p2shObj.redeem.output;
psbt.addInput({
  hash: 'db87829c15a5e3100c41563bad05d65c129f637f91705628afb16a2b33c50d27',
  index: 1,
  nonWitnessUtxo: Buffer.from('02000000000101eb64c7ac988c0e3564c35c618127d398835f7176cd6089ef445b14bddf88321c04000000171600144e386df71c94aca6f4304e427e5f326685371ae1feffffff02ba4c2f000000000017a91437bf7c47aa84767161d4f70ed07e4b2d7ddb4ad08740420f000000000017a91455e9fceb916ad6cc5fc23b3a8bd2cc8955a436ed870247304402200a30031e9b85e56a79ec995b31fe83cfcad3aba9188dfc87d5d3f84c252b1c28022045925955d54cdc23866bd16ba0e565a6203406367b1a118667d2327fe210096401210265eb47ee4d7c71385abb4343a150c1d8713303c18bfb9a3b7be3f0ea2c760b323b8e1800', 'hex'),
  redeemScript: redeemScript,
});

psbt.signInput(0, alice_pair);
console.log('valid signature: ', psbt.validateSignaturesOfAllInputs()) // return true