Skip to content

Instantly share code, notes, and snippets.

@peterzen
Last active June 5, 2017 09:44
Show Gist options
  • Save peterzen/dbf3e9ec7a7e6736facb8b78cc7c9365 to your computer and use it in GitHub Desktop.
Save peterzen/dbf3e9ec7a7e6736facb8b78cc7c9365 to your computer and use it in GitHub Desktop.
SignTxOutput.go
package main
import (
"encoding/hex"
"fmt"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainec"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/txscript"
"github.com/decred/dcrd/wire"
"github.com/decred/dcrutil"
)
func main() {
privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
"d4f8720ee63e502ee2869afab7de234b80c")
if err != nil {
fmt.Println(err)
return
}
privKey, pubKey := chainec.Secp256k1.PrivKeyFromBytes(privKeyBytes)
pubKeyHash := dcrutil.Hash160(pubKey.SerializeCompressed())
addr, err := dcrutil.NewAddressPubKeyHash(pubKeyHash,
&chaincfg.MainNetParams, chainec.ECTypeSecp256k1)
if err != nil {
fmt.Println(err)
return
}
// For this example, create a fake transaction that represents what
// would ordinarily be the real transaction that is being spent. It
// contains a single output that pays to address in the amount of 1 DCR.
originTx := wire.NewMsgTx()
prevOut := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0), wire.TxTreeRegular)
txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0})
originTx.AddTxIn(txIn)
pkScript, err := txscript.PayToAddrScript(addr)
if err != nil {
fmt.Println(err)
return
}
txOut := wire.NewTxOut(100000000, pkScript)
originTx.AddTxOut(txOut)
originTxHash := originTx.TxHash()
// Create the transaction to redeem the fake transaction.
redeemTx := wire.NewMsgTx()
// Add the input(s) the redeeming transaction will spend. There is no
// signature script at this point since it hasn't been created or signed
// yet, hence nil is provided for it.
prevOut = wire.NewOutPoint(&originTxHash, 0, wire.TxTreeRegular)
txIn = wire.NewTxIn(prevOut, nil)
redeemTx.AddTxIn(txIn)
// Ordinarily this would contain that actual destination of the funds,
// but for this example don't bother.
txOut = wire.NewTxOut(0, nil)
redeemTx.AddTxOut(txOut)
// Sign the redeeming transaction.
lookupKey := func(a dcrutil.Address) (chainec.PrivateKey, bool, error) {
// Ordinarily this function would involve looking up the private
// key for the provided address, but since the only thing being
// signed in this example uses the address associated with the
// private key from above, simply return it with the compressed
// flag set since the address is using the associated compressed
// public key.
//
// NOTE: If you want to prove the code is actually signing the
// transaction properly, uncomment the following line which
// intentionally returns an invalid key to sign with, which in
// turn will result in a failure during the script execution
// when verifying the signature.
//
// privKey.D.SetInt64(12345)
//
return privKey, true, nil
}
// Notice that the script database parameter is nil here since it isn't
// used. It must be specified when pay-to-script-hash transactions are
// being signed.
sigScript, err := txscript.SignTxOutput(&chaincfg.MainNetParams,
redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
txscript.KeyClosure(lookupKey), nil, nil, chainec.ECTypeSecp256k1)
// ./generate-tx.go:89: cannot convert lookupKey (type func("github.com/decred/dcrutil".Address) (chainec.PrivateKey, bool, error)) to type txscript.KeyClosure
if err != nil {
fmt.Println(err)
return
}
redeemTx.TxIn[0].SignatureScript = sigScript
// Prove that the transaction has been validly signed by executing the
// script pair.
flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures |
txscript.ScriptDiscourageUpgradableNops
vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
flags, 0, nil)
if err != nil {
fmt.Println(err)
return
}
if err := vm.Execute(); err != nil {
fmt.Println(err)
return
}
fmt.Println("Transaction successfully signed")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment