是否有任何可行的 testnet3 比特幣解決方案用於使用 Golang 創建、簽名、廣播正常交易?
目前我正在嘗試使用 btcsuite 創建、簽名和廣播比特幣交易。首先,我已經有了 testnet3 地址及其相關的用於測試的私鑰。但是,通過以下文章和文章進行搜尋:-
上面提出的解決方案不完整,對於第一個,它只涵蓋直到簽名(我知道作者聲稱它不可廣播,除非你提供我做的 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 > 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 > 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>,我在我的項目中使用它,如果您有任何問題,請留言。