Currently I'm trying to create, sign & broadcast bitcoin transaction using btcsuite. For start, I've already had testnet3 address & its associated privatekey for testing. However, hunting through the post and articles like below:-
The solution proposed above its not complete, for first one, it only covers until signing (i knew the author claimed its not broadcastable unless you provide the utxo which i did if i'm right) but when tried to braodcast it failed with message
"Error validating transaction: Transaction be9b294695bfb201a5cff32af074a4bf72b073e3c9dad1969111165bf118a622 orphaned, missing reference f0c0d3b3eecf911ede996a74ceadc9366068791450c9e6bacee9ae202f3690d1."
I have no idea what's going on and I suspect its script is incompatible.
So, the bottom line is I just want a workable example in bitcoin testnet3 that shows "from 1 address transfer some bitcoin to other address" by showing the process of creating raw transaction, sign it with private key, turn it to raw transaction in hex format & broadcast it using something like https://live.blockcypher.com/btc/pushtx/ (BTC testnet)
currently my code is as follow:-
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()
}
the txhash was from previous transaction where i got the testnet bitcoin from faucet & nothing else..
- Sender address: mpYGA8wRCArpGTs6aJMmZRWyUuPoZmeLJv
- Sender public key: 02217deb8b3782236fa8214da94bd5a9338f2eeb3299c39c057fb68ada63d93df7
Sender private key: cNjXNxcfawzyfGUxaG94rKqayAL2n7QWioKhCkHbQsBRT7SbDyGu
Target address: n2kRiAkW1xr5DVy7QKVGaYiZbwpS7j23jJ
Please advice what is wrong with the code above, really appreciate it if someone can point it out.