Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save farukterzioglu/ce43f6263d087b5cd2bc5f9d3569bcd3 to your computer and use it in GitHub Desktop.

Select an option

Save farukterzioglu/ce43f6263d087b5cd2bc5f9d3569bcd3 to your computer and use it in GitHub Desktop.

Revisions

  1. @davecgh davecgh revised this gist Dec 12, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion example_txscript_signtxoutput.go
    Original file line number Diff line number Diff line change
    @@ -111,7 +111,7 @@ func main() {
    txscript.ScriptStrictMultiSig |
    txscript.ScriptDiscourageUpgradableNops
    vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
    flags)
    flags, nil)
    if err != nil {
    fmt.Println(err)
    return
  2. @davecgh davecgh created this gist Feb 9, 2015.
    124 changes: 124 additions & 0 deletions example_txscript_signtxoutput.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,124 @@
    package main

    import (
    "encoding/hex"
    "fmt"

    "github.com/btcsuite/btcd/btcec"
    "github.com/btcsuite/btcd/chaincfg"
    "github.com/btcsuite/btcd/txscript"
    "github.com/btcsuite/btcd/wire"
    "github.com/btcsuite/btcutil"
    )

    // createFakeOriginTx creates a fake coinbase transaction that is used in the
    // example as a stand-in for what ordinarily be the real transaction that is
    // being spent.
    func createFakeOriginTx(addr btcutil.Address) (*wire.MsgTx, error) {
    tx := wire.NewMsgTx()
    prevOut := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0))
    txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0})
    tx.AddTxIn(txIn)

    pkScript, err := txscript.PayToAddrScript(addr)
    if err != nil {
    return nil, err
    }
    txOut := wire.NewTxOut(100000000, pkScript)
    tx.AddTxOut(txOut)
    return tx, nil
    }

    func main() {
    // Ordinarily the private key would come from whatever storage mechanism
    // is being used, but for this example just hard code it.
    privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
    "d4f8720ee63e502ee2869afab7de234b80c")
    if err != nil {
    fmt.Println(err)
    return
    }
    privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
    addr, err := btcutil.NewAddressPubKey(pubKey.SerializeCompressed(),
    &chaincfg.MainNetParams)
    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 BTC.
    originTx, err := createFakeOriginTx(addr.AddressPubKeyHash())
    if err != nil {
    fmt.Println(err)
    return
    }

    // 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.
    originTxHash := originTx.TxSha()
    prevOut := wire.NewOutPoint(&originTxHash, 0)
    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 btcutil.Address) (*btcec.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
    }
    sigScript, err := txscript.SignTxOutput(&chaincfg.MainNetParams,
    redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
    txscript.KeyClosure(lookupKey), nil, nil)
    if err != nil {
    fmt.Println(err)
    return
    }
    redeemTx.TxIn[0].SignatureScript = sigScript

    // Print the scripts involved for illustrative purposes.
    pkScriptDisasm, _ := txscript.DisasmString(originTx.TxOut[0].PkScript)
    sigScriptDisasm, _ := txscript.DisasmString(redeemTx.TxIn[0].SignatureScript)
    fmt.Println("pkScript:", pkScriptDisasm)
    fmt.Println("sigScript:", sigScriptDisasm)

    // Prove that the transaction has been validly signed by executing the
    // scripts.
    flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures |
    txscript.ScriptStrictMultiSig |
    txscript.ScriptDiscourageUpgradableNops
    vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
    flags)
    if err != nil {
    fmt.Println(err)
    return
    }
    if err := vm.Execute(); err != nil {
    fmt.Println(err)
    return
    }
    fmt.Println("Successfully signed transaction!")
    }