123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // Copyright (c) 2014-2016 The btcsuite developers
- // Use of this source code is governed by an ISC
- // license that can be found in the LICENSE file.
- package txscript_test
- import (
- "encoding/hex"
- "fmt"
- "github.com/pkt-cash/pktd/btcutil/er"
- "github.com/pkt-cash/pktd/txscript/opcode"
- "github.com/pkt-cash/pktd/txscript/params"
- "github.com/pkt-cash/pktd/wire/constants"
- "github.com/pkt-cash/pktd/btcec"
- "github.com/pkt-cash/pktd/btcutil"
- "github.com/pkt-cash/pktd/chaincfg"
- "github.com/pkt-cash/pktd/chaincfg/chainhash"
- "github.com/pkt-cash/pktd/txscript"
- "github.com/pkt-cash/pktd/wire"
- )
- // This example demonstrates creating a script which pays to a bitcoin address.
- // It also prints the created script hex and uses the DisasmString function to
- // display the disassembled script.
- func ExamplePayToAddrScript() {
- // Parse the address to send the coins to into a btcutil.Address
- // which is useful to ensure the accuracy of the address and determine
- // the address type. It is also required for the upcoming call to
- // PayToAddrScript.
- addressStr := "12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV"
- address, err := btcutil.DecodeAddress(addressStr, &chaincfg.MainNetParams)
- if err != nil {
- fmt.Println(err)
- return
- }
- // Create a public key script that pays to the address.
- script, err := txscript.PayToAddrScript(address)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Printf("Script Hex: %x\n", script)
- disasm, err := txscript.DisasmString(script)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println("Script Disassembly:", disasm)
- // Output:
- // Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac
- // Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG
- }
- // This example demonstrates extracting information from a standard public key
- // script.
- func ExampleExtractPkScriptAddrs() {
- // Start with a standard pay-to-pubkey-hash script.
- scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac"
- script, errr := hex.DecodeString(scriptHex)
- if errr != nil {
- fmt.Println(errr)
- return
- }
- // Extract and print details from the script.
- scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs(
- script, &chaincfg.MainNetParams)
- if err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println("Script Class:", scriptClass)
- fmt.Println("Addresses:", addresses)
- fmt.Println("Required Signatures:", reqSigs)
- // Output:
- // Script Class: pubkeyhash
- // Addresses: [12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV]
- // Required Signatures: 1
- }
- // This example demonstrates manually creating and signing a redeem transaction.
- func ExampleSignTxOutput() {
- // Ordinarily the private key would come from whatever storage mechanism
- // is being used, but for this example just hard code it.
- privKeyBytes, errr := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
- "d4f8720ee63e502ee2869afab7de234b80c")
- if errr != nil {
- fmt.Println(errr)
- return
- }
- privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
- pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed())
- addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash,
- &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 := wire.NewMsgTx(constants.TxVersion)
- prevOut := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0))
- txIn := wire.NewTxIn(prevOut, []byte{opcode.OP_0, opcode.OP_0}, nil)
- 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(constants.TxVersion)
- // 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)
- txIn = wire.NewTxIn(prevOut, nil, 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, er.R) {
- // 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, params.SigHashAll,
- txscript.KeyClosure(lookupKey), nil, nil)
- 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.ScriptStrictMultiSig |
- txscript.ScriptDiscourageUpgradableNops
- vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
- flags, nil, nil, -1)
- if err != nil {
- fmt.Println(err)
- return
- }
- if err := vm.Execute(); err != nil {
- fmt.Println(err)
- return
- }
- fmt.Println("Transaction successfully signed")
- // Output:
- // Transaction successfully signed
- }
|