0

This is a repost of a question which i posted directly on the repository of bitcoinjs-lib, which you can see here

I'm getting the following error when trying to push transactions:

Err: sendrawtransaction RPC error: {"code":-26,"message":"mandatory-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation)"}

I've done quite a bit of Googling and the only thing that it says is that my public and private keys do not match... which I'm not sure exactly how to remedy.

Here's debug information + code:

Debug Information

WIF: cN7j9B1H1YrZBufP5B43WcyX8U16XvJgeTdwLsS1ZrEkTEguy4FQ
Public: 036c99325f518d75088ed1ac950f0c37df0bf064e781f957c71d8f37e59f10cf83
Private: 0ff5f8231a280ab64d7498f27d0a49c736f710045aabe76ecc96b2f4758aa8ca
Example Transaction HEX: 020000000130a7c7195c23710e96e91f06ff87e264d98a5f9dbe4e34f89d6385b01dd2016c010000007000483045022100ae4b9bf764ecd9a54dd5cce1ff7092c6efda194789a632ebce0e5bc57f10e6d102207d3a1b68a3fb16c6ec86d74be2b825b298ce0c85dbbf05c5ed8084336c773dff01255121036c99325f518d75088ed1ac950f0c37df0bf064e781f957c71d8f37e59f10cf8351aeffffffff02a0860100000000001976a914344a0f48ca150ec2b903817660b9b68b13a6702688ac1be11200000000001976a9141c779cb2d3e6519d17fe1b8de8f7770765708ee888ac00000000

Decoded Transaction

{
    "addresses": [
        "mi7UWDi7iVB9GMXkRthjfTMv5UNybxmSJN",
        "mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt"
    ],
    "block_height": -1,
    "block_index": -1,
    "confirmations": 0,
    "double_spend": false,
    "fees": 250,
    "hash": "b43c7e23e58f40523555174f1d78147587729b5b320964b6157d5d737b60a510",
    "inputs": [
        {
            "addresses": [
                "mi7UWDi7iVB9GMXkRthjfTMv5UNybxmSJN"
            ],
            "age": 1977677,
            "output_index": 1,
            "output_value": 1337525,
            "prev_hash": "6c01d21db085639df8344ebe9d5f8ad964e287ff061fe9960e71235c19c7a730",
            "script": "00483045022100ae4b9bf764ecd9a54dd5cce1ff7092c6efda194789a632ebce0e5bc57f10e6d102207d3a1b68a3fb16c6ec86d74be2b825b298ce0c85dbbf05c5ed8084336c773dff01255121036c99325f518d75088ed1ac950f0c37df0bf064e781f957c71d8f37e59f10cf8351ae",
            "script_type": "pay-to-pubkey-hash",
            "sequence": 4294967295
        }
    ],
    "outputs": [
        {
            "addresses": [
                "mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt"
            ],
            "script": "76a914344a0f48ca150ec2b903817660b9b68b13a6702688ac",
            "script_type": "pay-to-pubkey-hash",
            "value": 100000
        },
        {
            "addresses": [
                "mi7UWDi7iVB9GMXkRthjfTMv5UNybxmSJN"
            ],
            "script": "76a9141c779cb2d3e6519d17fe1b8de8f7770765708ee888ac",
            "script_type": "pay-to-pubkey-hash",
            "value": 1237275
        }
    ],
    "preference": "low",
    "received": "2021-06-02T07:52:39.261650267Z",
    "relayed_by": "18.209.161.247",
    "size": 231,
    "total": 1337275,
    "ver": 2,
    "vin_sz": 1,
    "vout_sz": 2,
    "vsize": 231
}

Code

import * as bitcoin from 'bitcoinjs-lib';
import axios from 'axios';

const getAddress = async (node, network) => {
    return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address;
}

class BTCIntegration {
    #axios;
    constructor() {
        this.#axios = axios.create({
            baseURL: 'https://blockstream.info/testnet/api',
        })
    }

    async sendFunds(destination, amount, speed, wif) {
        const network = bitcoin.networks.testnet;
        const key = bitcoin.ECPair.fromWIF(wif, network);
        const fee = 250;
        const send = (amount * 100000000);
        const total = send + fee;
        const address = await getAddress(key, network);
        const txb = new bitcoin.Psbt({network});
        let txs = [];
        try {
            const {data} = await this.#axios.get(`/address/${address}/utxo`);
            txs = await Promise.all(data.filter((v) => {
                return (v.status.confirmed == true)
            }).map(async (v) => {
                const txr = await this.#axios.get(`/tx/${v.txid}/hex`);
                v.hex = txr.data;
                return v;
            }));
        }
        catch (err) {
            throw new Error('errors.unableToFetchAvailableFunds');
        }
        let input = 0;
        let available = 0;
        for (let i = 0; i < txs.length; i++) {
            const tx = txs[i];
            available += tx.value;
            if (input < send) {
                const pubkeys = [key.publicKey].map(hex => Buffer.from(hex, 'hex'));
                const p2shObj = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2ms({ m: 1, pubkeys, network })});
                const redeemScript = p2shObj.redeem.output;
                txb.addInput({
                    hash: tx.txid,
                    index: tx.vout,
                    nonWitnessUtxo: Buffer.from(tx.hex, 'hex'),
                    redeemScript,
                });
                input += tx.value;
            }
        }
        const change = input - total;
        if (send > available) {
            throw new Error('errors.insufficientFunds');
        }
        txb.addOutput({
            address: destination,
            value: send,
        });
        if (change > 0) {
            txb.addOutput({
                address,
                value: change,
            });
        }
        txb.signInput(0, key);
        txb.validateSignaturesOfAllInputs();
        txb.finalizeAllInputs();
        const ftx = txb.extractTransaction();
        const hex = ftx.toHex();

        let debug = '';
        debug += 'WIF: ' + wif + "\n";
        debug += 'Public: ' + Buffer.from(key.publicKey).toString('hex') + "\n";
        debug += 'Private: ' + Buffer.from(key.privateKey).toString('hex') + "\n";
        debug += 'THex: ' + hex + "\n";
        console.log(debug);

        try {
            const {data} = await this.#axios.post('/tx', hex);
            console.log(data);
        }
        catch (error) {
            if (error.response) {
                console.log('Err: ' + error.response.data)
                throw new Error(error.response.data);
            }
            console.error(error);
            throw new Error('errors.unableToSend');
        }
    }
}

export default BTCIntegration;

Where have I gone wrong?

I suspect that my issue is probably related to this:

const pubkeys = [key.publicKey].map(hex => Buffer.from(hex, 'hex'));
const p2shObj = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2ms({ m: 1, pubkeys, network })});
const redeemScript = p2shObj.redeem.output;
txb.addInput({
    hash: tx.txid,
    index: tx.vout,
    nonWitnessUtxo: Buffer.from(tx.hex, 'hex'),
    redeemScript,
});

But I honestly have no idea what I'm doing at this point.

2
  • 2
    You are spending a P2PKH output but the signature you've provided is for spending a P2SH output. Jun 2 at 8:29
  • Thanks. That actually helped me quite a bit.
    – JakGuru
    Jun 3 at 8:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.