Skip to content

Commit

Permalink
create and send transaction on testnet
Browse files Browse the repository at this point in the history
  • Loading branch information
hlongvu committed Nov 24, 2018
1 parent 25b2bf8 commit 3e4d42e
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ main
.idea/misc.xml
.idea/modules.xml
.idea/workspace.xml
vcs.xml
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/hlongvu/golang_ecdsa

require (
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a
github.com/davecgh/go-spew v1.1.1 // indirect
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869
)
151 changes: 151 additions & 0 deletions transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package main

import (
"bytes"
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec"
"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"
"log"
)

const test3_privKey = "291ad7996fa06e26379ce3640ca8752ae9ed7b87e27d2143f44ec1510ede3d74"
const my_address = "myeZPsW8yv8u9yy4gEG2ADuiczpf2257Vt"
const receiver_address = "mv4rnyY3Su5gjcDNzbMLKBQkBicCtHUtFB"

// https://tchain.btc.com/myeZPsW8yv8u9yy4gEG2ADuiczpf2257Vt

type utxo struct {
Address string
TxID string
OutputIndex uint32
Script []byte
Satoshis int64
}

func main() {

// 1. Get address from your private key
myPrivateKey, fromAddress := GetKeyAddressFromPrivateKey(test3_privKey)
fmt.Printf("TestNet3 Address: %s\n", fromAddress)
if fromAddress != my_address{
log.Fatal("Wrong private key and address pair. Please recheck!")
}

// 2. Get some test-net-3 btc at https://coinfaucet.eu/en/btc-testnet/
// 3. Create transaction
// We will send back the bitcoin to faucet address: mv4rnyY3Su5gjcDNzbMLKBQkBicCtHUtFB
// My balance is 0.00340000 BTC, we will send an amount less than that and leave some fee for the miners
//

unspentTx := utxo{
Address: my_address,
TxID: "b8d84fbcce0914ddc6688db53ef0dc6509833bf292189eb245a791a8415f9a58",
OutputIndex: 0,
Script: GetPayToAddrScript(my_address),
Satoshis: 200000,
}

// create new empty transaction

redemTx := wire.NewMsgTx(wire.TxVersion)

hash, err := chainhash.NewHashFromStr(unspentTx.TxID)
if err != nil {
log.Fatalf("could not get hash from transaction ID: %v", err)
}

// create TxIn

outPoint := wire.NewOutPoint(hash, unspentTx.OutputIndex)
txIn := wire.NewTxIn(outPoint, nil, nil)
redemTx.AddTxIn(txIn)

// create TxOut
rcv_script := GetPayToAddrScript(receiver_address)
outCoin := unspentTx.Satoshis

txOut := wire.NewTxOut(outCoin, rcv_script)
redemTx.AddTxOut(txOut)

// sign transaction

sig, err := txscript.SignatureScript(
redemTx, // The tx to be signed.
0, // The index of the txin the signature is for.
unspentTx.Script, // 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 {
log.Fatalf("could not generate signature: %v", err)
}

redemTx.TxIn[0].SignatureScript = sig

//Validate signature
flags := txscript.StandardVerifyFlags
vm, err := txscript.NewEngine(unspentTx.Script, redemTx, 0, flags, nil, nil, outCoin)
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(redemTx))
}


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

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

func GenerateKeyAddress() ([]byte, string){
key, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
fmt.Printf("failed to make privKey for %s: %v" , err)
}

pk := (*btcec.PublicKey)(&key.PublicKey).
SerializeUncompressed()
address, err := btcutil.NewAddressPubKeyHash(
btcutil.Hash160(pk), &chaincfg.TestNet3Params)
keyBytes := key.Serialize()
//keyHex := hex.EncodeToString(keyBytes)

fmt.Printf("PrivateKey: %x \n", keyBytes)
fmt.Printf("Address: %q\n", address.EncodeAddress())

return keyBytes, address.EncodeAddress()
}

func GetKeyAddressFromPrivateKey(privKey string) (*btcec.PrivateKey, string){
privByte, err := hex.DecodeString(privKey)

if err!=nil{
log.Panic(err)
}

priv, pubKey := btcec.PrivKeyFromBytes( btcec.S256(), privByte) //secp256k1

address, err := btcutil.NewAddressPubKeyHash(
btcutil.Hash160(pubKey.SerializeUncompressed()), &chaincfg.TestNet3Params)

return priv, address.EncodeAddress()
}

0 comments on commit 3e4d42e

Please sign in to comment.