btcsuite / btcwallet

A secure bitcoin wallet daemon written in Go (golang)
ISC License
1.15k stars 590 forks source link

-25: TX rejected: failed to validate input c26....:0 which references output 37....:0 - OP_EQUALVERIFY failed (input witness [], input script bytes 473..., prev output script bytes 76a914...) #865

Closed lenhatquang97 closed 1 year ago

lenhatquang97 commented 1 year ago

Hello everyone, I am creating a simple transaction to send only some satoshis to another simnet P2PKH address but I cannot send.

Commands runs on terminal (Note, sender address is default account address)

Btcd

btcd --simnet --rpcuser=youruser --rpcpass=SomeDecentp4ssw0rd --miningaddr=SeZdpbs8WBuPHMZETPWajMeXZt1xzCJNAJ --txindex

Btcwallet

btcwallet --simnet --username=youruser --password=SomeDecentp4ssw0rd

Source code

package main

import (
    "fmt"

    "github.com/btcsuite/btcd/btcutil"
    "github.com/btcsuite/btcd/chaincfg"
    "github.com/btcsuite/btcd/chaincfg/chainhash"
    "github.com/btcsuite/btcd/rpcclient"
    "github.com/btcsuite/btcd/txscript"
    "github.com/btcsuite/btcd/wire"
)

func main() {
    client, err := GetBitcoinWalletRpcClient()
    if err != nil {
        fmt.Println(err)
        return
    }

    err = client.WalletPassphrase("12345", 5)
    if err != nil {
        fmt.Println(err)
        return
    }

    rawTx, err := CreateTx("SZnK16oMnqQt8Q1qLvrTpYLpkpkFG9eVRi", 1, client)

    if err != nil {
        fmt.Println(err)
        return
    }

    hash, err := client.SendRawTransaction(rawTx, false)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(hash)
}

func NewTx() (*wire.MsgTx, error) {
    return wire.NewMsgTx(wire.TxVersion), nil
}

func CreateTx(destination string, amount int64, client *rpcclient.Client) (*wire.MsgTx, error) {
    defaultAddress, err := client.GetAccountAddress("default")
    if err != nil {
        return nil, err
    }

    wif, err := client.DumpPrivKey(defaultAddress)
    if err != nil {
        return nil, err
    }

    utxos, err := client.ListUnspent()
    if err != nil {
        return nil, err
    }

    txid := utxos[0].TxID
    balance := utxos[0].Amount
    pkScript, _ := txscript.PayToAddrScript(defaultAddress)

    if err != nil {
        return nil, err
    }

    // checking for sufficiency of account
    if int64(balance) < amount {
        return nil, fmt.Errorf("the balance of the account is not sufficient")
    }

    // extracting destination address as []byte from function argument (destination string)
    destinationAddr, err := btcutil.DecodeAddress(destination, &chaincfg.SimNetParams)
    if err != nil {
        return nil, err
    }

    destinationAddrByte, err := txscript.PayToAddrScript(destinationAddr)
    if err != nil {
        return nil, err
    }

    redeemTx, err := NewTx()
    if err != nil {
        return nil, err
    }

    utxoHash, err := chainhash.NewHashFromStr(txid)
    if err != nil {
        return nil, err
    }

    outPoint := wire.NewOutPoint(utxoHash, 0)

    // making the input, and adding it to transaction
    txIn := wire.NewTxIn(outPoint, nil, nil)
    redeemTx.AddTxIn(txIn)

    // adding the destination address and the amount to
    // the transaction as output
    redeemTxOut := wire.NewTxOut(amount, destinationAddrByte)
    redeemTx.AddTxOut(redeemTxOut)

    // now sign the transaction
    finalRawTx, err := SignTx(wif, pkScript, redeemTx)
    if err != nil {
        return nil, err
    }

    return finalRawTx, nil
}

func SignTx(wif *btcutil.WIF, pkScript []byte, redeemTx *wire.MsgTx) (*wire.MsgTx, error) {
    signature, err := txscript.SignatureScript(redeemTx, 0, pkScript, txscript.SigHashAll, wif.PrivKey, true)
    if err != nil {
        return nil, err
    }

    redeemTx.TxIn[0].SignatureScript = signature

    return redeemTx, nil
}

Error

-25: TX rejected: failed to validate input c267017e0c76a213be4e3e2bc2d8d3b429a22eabfb4c91f949fb1a1161d67fdf:0 which references output 37264feddf67c2b867b0520dc6ff92f8fc6445ac7eac3145231931175ab2bdf8:0 - OP_EQUALVERIFY failed (input witness [], input script bytes 4730440220716f4f2b660215e877a256761a7f386d574e3ad3d78e8cccc17dad26c47e84d502203e571462da47f50d01965bcbae9bc8acfd363b136d21f9d64e63e07e27691770012102840c71eccbdcf002792c8e261795930fd127727e123efce3ccbde3dfd9fd7673, prev output script bytes 76a914bd6f166f34fa00ecc0010900ead95ba6cf9f2a8788ac)
guggero commented 1 year ago

You're signing the TX with the defaultAddress, which might not be the same as the one that you get in the utxo[0].

lenhatquang97 commented 1 year ago

Oh, I have fixed this completely. Thank you very much. In this code, I will write a function to get utxo based on address. I will close with my comment.