Skip to content

Instantly share code, notes, and snippets.

@davecgh
Last active March 8, 2019 07:01
Show Gist options
  • Save davecgh/a5d6093c095ec8297e76 to your computer and use it in GitHub Desktop.
Save davecgh/a5d6093c095ec8297e76 to your computer and use it in GitHub Desktop.
Example of stepping through a script using the txscript API.
package main
import (
"encoding/hex"
"fmt"
"os"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
)
// createSpendTx generates a basic spending transaction given the passed
// signature and public key scripts.
func createSpendingTx(sigScript, pkScript []byte) (*wire.MsgTx, error) {
coinbaseTx := wire.NewMsgTx(wire.TxVersion)
outPoint := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0))
txIn := wire.NewTxIn(outPoint, []byte{txscript.OP_0, txscript.OP_0})
txOut := wire.NewTxOut(0, pkScript)
coinbaseTx.AddTxIn(txIn)
coinbaseTx.AddTxOut(txOut)
spendingTx := wire.NewMsgTx(wire.TxVersion)
coinbaseTxSha := coinbaseTx.TxHash()
outPoint = wire.NewOutPoint(&coinbaseTxSha, 0)
txIn = wire.NewTxIn(outPoint, sigScript)
txOut = wire.NewTxOut(0, nil)
spendingTx.AddTxIn(txIn)
spendingTx.AddTxOut(txOut)
return spendingTx, nil
}
func main() {
txscript.SetLogWriter(os.Stdout, "trace")
sigScript, err := hex.DecodeString("47304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f0143410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac")
if err != nil {
fmt.Println(err)
return
}
pkScript, err := hex.DecodeString("a91431edc23bdafda4639e669f89ad6b2318dd79d03287")
if err != nil {
fmt.Println(err)
return
}
tx, err := createSpendingTx(sigScript, pkScript)
if err != nil {
fmt.Println(err)
return
}
vm, err := txscript.NewEngine(pkScript, tx, 0, txscript.StandardVerifyFlags, nil)
if err != nil {
fmt.Println(err)
return
}
if err := vm.Execute(); err != nil {
fmt.Println(err)
return
}
// Alternatively, you can comment out the execute above, step through
// it manually, and examine the stack.
/*
done := false
for !done {
// Display the instruction and associated data at the program
// counter.
dis, err := vm.DisasmPC()
if err != nil {
fmt.Printf("stepping (%v)\n", err)
}
fmt.Printf("stepping %v\n", dis)
// Execute the next instruction.
done, err = vm.Step()
if err != nil {
fmt.Println(err)
return
}
// Display the stacks.
dataStack := vm.GetStack()
if len(dataStack) != 0 {
fmt.Println("Data stack:")
spew.Dump(dataStack)
fmt.Println("")
}
altStack := vm.GetAltStack()
if len(altStack) != 0 {
fmt.Println("Alternate stack:")
spew.Dump(altStack)
fmt.Println("")
}
}
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment