Client

是否有任何可行的 testnet3 比特幣解決方案用於使用 Golang 創建、簽名、廣播正常交易?

  • January 2, 2022

目前我正在嘗試使用 btcsuite 創建、簽名和廣播比特幣交易。首先,我已經有了 testnet3 地址及其相關的用於測試的私鑰。但是,通過以下文章和文章進行搜尋:-

  1. 這裡
  2. 這裡
  3. 這裡

上面提出的解決方案不完整,對於第一個,它只涵蓋直到簽名(我知道作者聲稱它不可廣播,除非你提供我做的 utxo,如果我是對的)但是當嘗試廣播時它失敗並顯示消息

“驗證交易時出錯:交易 be9b294695bfb201a5cff32af074a4bf72b073e3c9dad1969111165bf118a622 孤立,缺少參考 f0c0d3b3eecf911ede996a74ceadc9366068791450c9e6bacee9ae202f39。”

我不知道發生了什麼,我懷疑它的腳本不兼容。

所以,底線是我只想要一個在比特幣 testnet3 中的可行範例,通過顯示創建原始交易的過程,顯示“從 1 個地址將一些比特幣轉移到其他地址”,用私鑰對其進行簽名,將其轉換為十六進制的原始交易使用<https://live.blockcypher.com/btc/pushtx/>(BTC 測試網)之類的格式和廣播它

目前我的程式碼如下: -

package main
import (
   "fmt"
   "encoding/hex"
   "bytes"
   "github.com/btcsuite/btcutil"
   btcchain "github.com/btcsuite/btcd/chaincfg"
   "github.com/btcsuite/btcd/chaincfg/chainhash"
   "github.com/btcsuite/btcd/txscript"
   "github.com/btcsuite/btcd/wire"
)
func txToHex(tx *wire.MsgTx) string {
   buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
   tx.Serialize(buf)
   return hex.EncodeToString(buf.Bytes())
}

func stkbtc(){
 pvkey := "cNjXNxcfawzyfGUxaG94rKqayAL2n7QWioKhCkHbQsBRT7SbDyGu"
 txHash := "e028b5bf030a24986a03b03b89dec037e8462ae32bc93679cb49d7c779685987"
 destination := "n2kRiAkW1xr5DVy7QKVGaYiZbwpS7j23jJ"
 var amount int64 = 100000000
 txFee := int64(500000)

 //try send btc
 decodedwif,err := btcutil.DecodeWIF(pvkey)
 if err != nil {
   fmt.Printf("decodedwif error: %v\n",err)
 }
 fmt.Printf("decodedwif       : %v\n",decodedwif)

 addresspubkey, _ := btcutil.NewAddressPubKey(decodedwif.PrivKey.PubKey().SerializeUncompressed(), &btcchain.TestNet3Params)
 sourceTx := wire.NewMsgTx(wire.TxVersion)
 sourceUtxoHash, _ := chainhash.NewHashFromStr(txHash)

 sourceUtxo := wire.NewOutPoint(sourceUtxoHash, 0)

 sourceTxIn := wire.NewTxIn(sourceUtxo, nil, nil)
 destinationAddress, _ := btcutil.DecodeAddress(destination, &btcchain.TestNet3Params)

 sourceAddress, err := btcutil.DecodeAddress(addresspubkey.EncodeAddress(), &btcchain.TestNet3Params)
 if err != nil {
   fmt.Printf("sourceAddress err: %v\n",err)
 }

 destinationPkScript, _ := txscript.PayToAddrScript(destinationAddress)

 sourcePkScript, _ := txscript.PayToAddrScript(sourceAddress)
 sourceTxOut := wire.NewTxOut(amount, sourcePkScript)

 sourceTx.AddTxIn(sourceTxIn)
 sourceTx.AddTxOut(sourceTxOut)
 sourceTxHash := sourceTx.TxHash()

 redeemTx := wire.NewMsgTx(wire.TxVersion)
 prevOut := wire.NewOutPoint(&sourceTxHash, 0)
 redeemTxIn := wire.NewTxIn(prevOut, nil, nil)
 redeemTx.AddTxIn(redeemTxIn)
 redeemTxOut := wire.NewTxOut((amount - txFee), destinationPkScript)
 redeemTx.AddTxOut(redeemTxOut)

 sigScript, err := txscript.SignatureScript(redeemTx, 0, sourceTx.TxOut[0].PkScript, txscript.SigHashAll, decodedwif.PrivKey, false)
 if err != nil {
   fmt.Printf("sigScript err: %v\n",err)
 }
 redeemTx.TxIn[0].SignatureScript = sigScript
 fmt.Printf("sigScript: %v\n",hex.EncodeToString(sigScript))


 //Validate signature
 flags := txscript.StandardVerifyFlags
 vm, err := txscript.NewEngine(sourceTx.TxOut[0].PkScript, redeemTx, 0, flags, nil, nil, amount)
 if err != nil {
   fmt.Printf("err != nil: %v\n",err)
 }
 if err := vm.Execute(); err != nil {
   fmt.Printf("vm.Execute &gt; err != nil: %v\n",err)
 }

 fmt.Printf("redeemTx: %v\n",txToHex(redeemTx))
}

func main(){
   stkbtc()
}

txhash 來自之前的交易,我從 faucet 獲得了 testnet 比特幣,僅此而已..

  • 發件人地址:mpYGA8wRCArpGTs6aJMmZRWyUuPoZmeLJv
  • 發件人公鑰:02217deb8b3782236fa8214da94bd5a9338f2eeb3299c39c057fb68ada63d93df7
  • 發件人私鑰:cNjXNxcfawzyfGUxaG94rKqayAL2n7QWioKhCkHbQsBRT7SbDyGu
  • 目標地址:n2kRiAkW1xr5DVy7QKVGaYiZbwpS7j23jJ

請指教上面的程式碼有什麼問題,如果有人能指出的話,真的很感激。

我想我發現了問題:程式碼生成了一個創建 UTXO 的假交易,並引用了它的 TXID 而不是真實交易的 TXID。

新程式碼:

package main

import (
   "bytes"
   "encoding/hex"
   "fmt"
   btcchain "github.com/btcsuite/btcd/chaincfg"
   "github.com/btcsuite/btcd/chaincfg/chainhash"
   "github.com/btcsuite/btcd/txscript"
   "github.com/btcsuite/btcd/wire"
   "github.com/btcsuite/btcutil"
)

func txToHex(tx *wire.MsgTx) string {
   buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
   tx.Serialize(buf)
   return hex.EncodeToString(buf.Bytes())
}

func stkbtc() {
   pvkey := "cNjXNxcfawzyfGUxaG94rKqayAL2n7QWioKhCkHbQsBRT7SbDyGu"
   txHash := "e028b5bf030a24986a03b03b89dec037e8462ae32bc93679cb49d7c779685987"
   destination := "n2kRiAkW1xr5DVy7QKVGaYiZbwpS7j23jJ"
   var amount int64 = 100000000
   txFee := int64(500000)

   //try send btc
   decodedwif, err := btcutil.DecodeWIF(pvkey)
   if err != nil {
       fmt.Printf("decodedwif error: %v\n", err)
   }
   fmt.Printf("decodedwif       : %v\n", decodedwif)

   addresspubkey, _ := btcutil.NewAddressPubKey(decodedwif.PrivKey.PubKey().SerializeUncompressed(), &btcchain.TestNet3Params)
   sourceUtxoHash, _ := chainhash.NewHashFromStr(txHash)

   sourceUtxo := wire.NewOutPoint(sourceUtxoHash, 0)

   sourceTxIn := wire.NewTxIn(sourceUtxo, nil, nil)
   destinationAddress, _ := btcutil.DecodeAddress(destination, &btcchain.TestNet3Params)

   sourceAddress, err := btcutil.DecodeAddress(addresspubkey.EncodeAddress(), &btcchain.TestNet3Params)
   if err != nil {
       fmt.Printf("sourceAddress err: %v\n", err)
   }

   destinationPkScript, _ := txscript.PayToAddrScript(destinationAddress)

   sourcePkScript, _ := txscript.PayToAddrScript(sourceAddress)
   sourceTxOut := wire.NewTxOut(amount, sourcePkScript)

   redeemTx := wire.NewMsgTx(wire.TxVersion)
   redeemTx.AddTxIn(sourceTxIn)
   redeemTxOut := wire.NewTxOut((amount - txFee), destinationPkScript)
   redeemTx.AddTxOut(redeemTxOut)

   sigScript, err := txscript.SignatureScript(redeemTx, 0, sourceTxOut.PkScript, txscript.SigHashAll, decodedwif.PrivKey, false)
   if err != nil {
       fmt.Printf("sigScript err: %v\n", err)
   }
   redeemTx.TxIn[0].SignatureScript = sigScript
   fmt.Printf("sigScript: %v\n", hex.EncodeToString(sigScript))

   //Validate signature
   flags := txscript.StandardVerifyFlags
   vm, err := txscript.NewEngine(sourceTxOut.PkScript, redeemTx, 0, flags, nil, nil, amount)
   if err != nil {
       fmt.Printf("err != nil: %v\n", err)
   }
   if err := vm.Execute(); err != nil {
       fmt.Printf("vm.Execute &gt; err != nil: %v\n", err)
   }

   fmt.Printf("redeemTx: %v\n", txToHex(redeemTx))
}

func main() {
   stkbtc()
}

差異總結:

(我還沒有發布新的交易)

你好我有編寫golang程式碼與比特幣互動的經驗,如果你想建立交易並簽署交易,這真的很棘手,我建議你使用bitcoind rpc來做。這是一個可行的 golang rpc 包裝器(也適用於 testnet3 和 mainnet)<https://github.com/huahuayu/go-bitcoind>,我在我的項目中使用它,如果您有任何問題,請留言。

引用自:https://bitcoin.stackexchange.com/questions/77145