1

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:-

  1. here
  2. here
  3. here

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.

4
  • It seems the the UTXO couldn't be found: blocktrail.com/tBTC/address/mpYGA8wRCArpGTs6aJMmZRWyUuPoZmeLJv/…
    – MCCCS
    Commented Jul 15, 2018 at 6:05
  • hi, can you explain in detail what couldn't be found? the address mpYGA8wRCArpGTs6aJMmZRWyUuPoZmeLJv was funded by faucet, thus the unspent should be there as shown. live.blockcypher.com/btc-testnet/address/…. care to elaborate more? Commented Jul 16, 2018 at 7:13
  • The UTXO wasn't there yesterday, so please try it again.
    – MCCCS
    Commented Jul 16, 2018 at 7:15
  • i've tried, its still the same. it still return Error validating transaction: Transaction 58521a5f97cbb02e4967132f872edbe7c60677da9ef4d018f4feeca0847ce2a2 orphaned, missing reference f12111c6bc76aa6d8346ab20e7e767118b6fafc9cde14366b19d77937b09daaf. Commented Jul 16, 2018 at 8:27

1 Answer 1

1

I guess I found the problem: The code generated a fake transaction that created the UTXO, and referenced its TXID instead of the TXID of the real transaction.

The new code:

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()
}

Summary of the differences:

(I haven't published the new transaction)

1
  • 1
    i've tried generating the raw tx based on the updated code you presented, good thing is there's no validation error on console, but upon broadcast to blockcypher btc testnet, it's still throw error "Error validating transaction: Error running script for input 0 referencing e028b5bf030a24986a03b03b89dec037e8462ae32bc93679cb49d7c779685987 at 0: Script was NOT verified successfully.." improvement is, its a different error.. but now it's much more less information to troubleshoot; any suggestions? perhaps the code itself is already incorrect? what would be the proper way to do it? please advice Commented Jul 16, 2018 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.