You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang实现比特币交易广播失败,Script验证错误求助

比特币测试网交易广播脚本验证失败问题

在比特币测试网广播交易时遭遇脚本验证失败,错误信息如下:

Error validating transaction: Error running script for input 0 referencing 78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18 at 0: Script was NOT verified successfully..

已尝试在TxIn中使用解码后的Asm PkScript替代PubKey,也查阅过Stack Overflow上的同类问题解决方案,但均未解决问题。本地虚拟机未检测到交易存在异常,现寻求帮助排查该交易的问题所在。


交易十六进制数据

0100000001181e15e7aa64ce9a21421e3b1dffe63418e6cf0959d1d847f732415e77dfb678000000008a47304402200aa339f80c705a22180c8edd4acc4baa5bc76c9e8f64852eb3cb507f027aee9c02206da34700e76df568ef018fe346bb5b9c4484506ee84740916d6c3b454c2e1d3f0141042a1b4d9533ff37cd290b95016056cacbdbbf99b5975345dc5837a95f698f8a26d74f726e2a1e62552107953595502c8078a84311690c61ace3f22644ae33a0abffffffff02d0070000000000001976a91437383464376cccaf2ae4c8a121805f45bf544e4488acc8320000000000001976a914a404271e971d58240add530813e514b0ffe45f3588ac00000000

解码后的交易信息

{
    "addresses": [
        "mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1",
        "mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX"
    ],
    "block_height": -1,
    "block_index": -1,
    "confirmations": 0,
    "double_spend": false,
    "fees": 5000,
    "hash": "410f8119e9c225fc197a21ede7f9e6902f85a36010a2776dd3fdc2663072a36c",
    "inputs": [
        {
            "addresses": [
                "mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"
            ],
            "age": 2345496,
            "output_index": 0,
            "output_value": 20000,
            "prev_hash": "78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18",
            "script": "47304402200aa339f80c705a22180c8edd4acc4baa5bc76c9e8f64852eb3cb507f027aee9c02206da34700e76df568ef018fe346bb5b9c4484506ee84740916d6c3b454c2e1d3f0141042a1b4d9533ff37cd290b95016056cacbdbbf99b5975345dc5837a95f698f8a26d74f726e2a1e62552107953595502c8078a84311690c61ace3f22644ae33a0ab",
            "script_type": "pay-to-pubkey-hash",
            "sequence": 4294967295
        }
    ],
    "outputs": [
        {
            "addresses": [
                "mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX"
            ],
            "script": "76a91437383464376cccaf2ae4c8a121805f45bf544e4488ac",
            "script_type": "pay-to-pubkey-hash",
            "value": 2000
        },
        {
            "addresses": [
                "mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"
            ],
            "script": "76a914a404271e971d58240add530813e514b0ffe45f3588ac",
            "script_type": "pay-to-pubkey-hash",
            "value": 13000
        }
    ],
    "preference": "low",
    "received": "2022-09-06T14:10:50.749940874Z",
    "relayed_by": "44.204.10.232",
    "size": 257,
    "total": 15000,
    "ver": 1,
    "vin_sz": 1,
    "vout_sz": 2,
    "vsize": 257
}

相关Golang代码

func main() {
    connCfg := &rpcclient.ConnConfig{ //smth here
    }
    client, err := rpcclient.New(connCfg, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Shutdown()
    utxoMap := make(map[string]string)
    utxoMap["mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1"] = "78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18"
    rawTx, err := CreateRawTx("mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1", "mkYvnmm3KUBkvVqUAYsG6A6amt5Dva4jzX", 2000, utxoMap, client)
    if err != nil {
        println(err.Error())
    }
    signedTx, err := Sign(rawTx, "private key here")
    if err != nil {
        println(err.Error())
    }
    fmt.Println(signedTx)
}

type UTXO struct {
    previousTxID string
    pubKeyScript string
    Asm          string
    Amount       decimal.Decimal
}

func GetUTXO(utxoMap map[string]string, address string, client *rpcclient.Client) (utxo UTXO, err error) {
    // unmarshal it, and extract necessary data
    hash, _ := chainhash.NewHashFromStr(utxoMap[address])
    tx, err := client.GetRawTransactionVerbose(hash)
    if err != nil {
        return utxo, errors.Wrapf(err, "GetUTXO.GetRawTransactionVerbose")
    }
    pubKeyScript := tx.Vout[0].ScriptPubKey.Hex
    previousTxID := utxoMap[address]
    amount := decimal.NewFromFloat(tx.Vout[0].Value)

    asm := tx.Vout[0].ScriptPubKey.Hex
    return UTXO{
        previousTxID: previousTxID,
        pubKeyScript: pubKeyScript,
        Asm:          asm,
        Amount:       amount,
    }, nil
}

func GetPayToAddrScript(address string) []byte {
    rcvAddress, _ := btcutil.DecodeAddress(address, &chaincfg.TestNet3Params)
    rcvScript, _ := txscript.PayToAddrScript(rcvAddress)
    return rcvScript
}

type TXRef struct {
    TXHash    string
    TXOutputN int
}

// get private key
func getKeyAddressFromPrivateKey(privateKey string, conf *chaincfg.Params) (*btcec.PrivateKey, string, error) {
    newWif, err := btcutil.DecodeWIF(privateKey)
    if err != nil {
        return nil, "", err
    }

    publicKey := newWif.PrivKey.PubKey().SerializeUncompressed()
    address, err := btcutil.NewAddressPubKeyHash(btcutil.Hash160(publicKey), conf)
    if err != nil {
        return nil, "", err
    }
    return newWif.PrivKey, address.EncodeAddress(), nil
}

// debug signing function
func Sign(rawTx, privateKey string) (string, error) {
    var signTx wire.MsgTx
    err := json.Unmarshal([]byte(rawTx), &signTx)
    if err != nil {
        return "", err
    }

    myPrivateKey, address, err := getKeyAddressFromPrivateKey(privateKey, &chaincfg.TestNet3Params)

    fmt.Println("address ", address)
    if err != nil {
        return "", err
    }
    txScript := GetPayToAddrScript(address)
    for i := 0; i < len(signTx.TxIn); i++ {
        sig, err := txscript.SignatureScript(
            &signTx,             // The tx to be signed.
            i,                   // The index of the txin the signature is for.
            txScript,            // The other half of the script from the PubKeyHash.
            txscript.SigHashAll, // The signature flags that indicate what the sig covers.
            myPrivateKey,        // The key to generate the signature with.
            false) // The compress sig flag. This saves space on the blockchain.

        if err != nil {
            return "", err
        }

        signTx.TxIn[i].SignatureScript = sig

        //Validate signature
        flags := txscript.StandardVerifyFlags
        vm, err := txscript.NewEngine(txScript, &signTx, i, flags, nil, nil, signTx.TxOut[0].Value, nil)
        if err != nil {
            return "", err
        }
        if err := vm.Execute(); err != nil {
            return "", err
        }
    }
    // return signed tx
    var signedTx bytes.Buffer
    signTx.Serialize(&signedTx)
    hexSignedTx := hex.EncodeToString(signedTx.Bytes())
    return hexSignedTx, nil
}

// CreateBtcRawTx create raw tx for sending btc
func CreateRawTx(from string, to string, amount int64, utxoMap map[string]string, client *rpcclient.Client) (string, error) {
    amountInt := amount
    var feeBitcoin int64 = 5000
    spendAmount := amountInt + feeBitcoin
    utxo, err := GetUTXO(utxoMap, from, client)
    changeAmount := utxo.Amount.Shift(8).IntPart() - spendAmount
    // create new empty transaction
    redemTx := wire.NewMsgTx(wire.TxVersion)
    // create multiple txIns
    hash, err := chainhash.NewHashFromStr(utxo.previousTxID)
    if err != nil {
        fmt.Printf("could not get hash from transaction ID: %v", err)
        return "", err
    }

    outPoint := wire.NewOutPoint(hash, 0)
    txIn := wire.NewTxIn(outPoint, nil, nil)

    redemTx.AddTxIn(txIn)

    // create TxOut
    rcvScript := GetPayToAddrScript(to)
    txOut := wire.NewTxOut(amountInt, rcvScript)
    redemTx.AddTxOut(txOut)
    // create TxOut for change address, in this case, change address is sender itself
    if changeAmount > 0 {
        // return change BTC to its own address
        rcvChangeAddressScript := GetPayToAddrScript(from)
        txOut := wire.NewTxOut(changeAmount, rcvChangeAddressScript)
        redemTx.AddTxOut(txOut)
    }

    encodedTx, err := json.Marshal(redemTx)
    if err != nil {
        return "", err
    }
    // return raw tx in hex format
    return string(encodedTx), nil
}

补充信息

  • 钱包地址:mvUC64ETwYLbTjH38ZVigDwMBtCS9TbuT1
  • 关联UTXO交易哈希:78b6df775e4132f747d8d15909cfe61834e6ff1d3b1e42219ace64aae7151e18

内容的提问来源于stack exchange,提问作者JkLondon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:10:28