github.com/palcoin-project/palcd@v1.0.0/txscript/example_test.go (about)

     1  // Copyright (c) 2014-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package txscript_test
     6  
     7  import (
     8  	"encoding/hex"
     9  	"fmt"
    10  
    11  	"github.com/palcoin-project/palcd/btcec"
    12  	"github.com/palcoin-project/palcd/chaincfg"
    13  	"github.com/palcoin-project/palcd/chaincfg/chainhash"
    14  	"github.com/palcoin-project/palcd/txscript"
    15  	"github.com/palcoin-project/palcd/wire"
    16  	"github.com/palcoin-project/palcutil"
    17  )
    18  
    19  // This example demonstrates creating a script which pays to a bitcoin address.
    20  // It also prints the created script hex and uses the DisasmString function to
    21  // display the disassembled script.
    22  func ExamplePayToAddrScript() {
    23  	// Parse the address to send the coins to into a palcutil.Address
    24  	// which is useful to ensure the accuracy of the address and determine
    25  	// the address type.  It is also required for the upcoming call to
    26  	// PayToAddrScript.
    27  	addressStr := "12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV"
    28  	address, err := palcutil.DecodeAddress(addressStr, &chaincfg.MainNetParams)
    29  	if err != nil {
    30  		fmt.Println(err)
    31  		return
    32  	}
    33  
    34  	// Create a public key script that pays to the address.
    35  	script, err := txscript.PayToAddrScript(address)
    36  	if err != nil {
    37  		fmt.Println(err)
    38  		return
    39  	}
    40  	fmt.Printf("Script Hex: %x\n", script)
    41  
    42  	disasm, err := txscript.DisasmString(script)
    43  	if err != nil {
    44  		fmt.Println(err)
    45  		return
    46  	}
    47  	fmt.Println("Script Disassembly:", disasm)
    48  
    49  	// Output:
    50  	// Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac
    51  	// Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG
    52  }
    53  
    54  // This example demonstrates extracting information from a standard public key
    55  // script.
    56  func ExampleExtractPkScriptAddrs() {
    57  	// Start with a standard pay-to-pubkey-hash script.
    58  	scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac"
    59  	script, err := hex.DecodeString(scriptHex)
    60  	if err != nil {
    61  		fmt.Println(err)
    62  		return
    63  	}
    64  
    65  	// Extract and print details from the script.
    66  	scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs(
    67  		script, &chaincfg.MainNetParams)
    68  	if err != nil {
    69  		fmt.Println(err)
    70  		return
    71  	}
    72  	fmt.Println("Script Class:", scriptClass)
    73  	fmt.Println("Addresses:", addresses)
    74  	fmt.Println("Required Signatures:", reqSigs)
    75  
    76  	// Output:
    77  	// Script Class: pubkeyhash
    78  	// Addresses: [12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV]
    79  	// Required Signatures: 1
    80  }
    81  
    82  // This example demonstrates manually creating and signing a redeem transaction.
    83  func ExampleSignTxOutput() {
    84  	// Ordinarily the private key would come from whatever storage mechanism
    85  	// is being used, but for this example just hard code it.
    86  	privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
    87  		"d4f8720ee63e502ee2869afab7de234b80c")
    88  	if err != nil {
    89  		fmt.Println(err)
    90  		return
    91  	}
    92  	privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
    93  	pubKeyHash := palcutil.Hash160(pubKey.SerializeCompressed())
    94  	addr, err := palcutil.NewAddressPubKeyHash(pubKeyHash,
    95  		&chaincfg.MainNetParams)
    96  	if err != nil {
    97  		fmt.Println(err)
    98  		return
    99  	}
   100  
   101  	// For this example, create a fake transaction that represents what
   102  	// would ordinarily be the real transaction that is being spent.  It
   103  	// contains a single output that pays to address in the amount of 1 BTC.
   104  	originTx := wire.NewMsgTx(wire.TxVersion)
   105  	prevOut := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0))
   106  	txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0}, nil)
   107  	originTx.AddTxIn(txIn)
   108  	pkScript, err := txscript.PayToAddrScript(addr)
   109  	if err != nil {
   110  		fmt.Println(err)
   111  		return
   112  	}
   113  	txOut := wire.NewTxOut(100000000, pkScript)
   114  	originTx.AddTxOut(txOut)
   115  	originTxHash := originTx.TxHash()
   116  
   117  	// Create the transaction to redeem the fake transaction.
   118  	redeemTx := wire.NewMsgTx(wire.TxVersion)
   119  
   120  	// Add the input(s) the redeeming transaction will spend.  There is no
   121  	// signature script at this point since it hasn't been created or signed
   122  	// yet, hence nil is provided for it.
   123  	prevOut = wire.NewOutPoint(&originTxHash, 0)
   124  	txIn = wire.NewTxIn(prevOut, nil, nil)
   125  	redeemTx.AddTxIn(txIn)
   126  
   127  	// Ordinarily this would contain that actual destination of the funds,
   128  	// but for this example don't bother.
   129  	txOut = wire.NewTxOut(0, nil)
   130  	redeemTx.AddTxOut(txOut)
   131  
   132  	// Sign the redeeming transaction.
   133  	lookupKey := func(a palcutil.Address) (*btcec.PrivateKey, bool, error) {
   134  		// Ordinarily this function would involve looking up the private
   135  		// key for the provided address, but since the only thing being
   136  		// signed in this example uses the address associated with the
   137  		// private key from above, simply return it with the compressed
   138  		// flag set since the address is using the associated compressed
   139  		// public key.
   140  		//
   141  		// NOTE: If you want to prove the code is actually signing the
   142  		// transaction properly, uncomment the following line which
   143  		// intentionally returns an invalid key to sign with, which in
   144  		// turn will result in a failure during the script execution
   145  		// when verifying the signature.
   146  		//
   147  		// privKey.D.SetInt64(12345)
   148  		//
   149  		return privKey, true, nil
   150  	}
   151  	// Notice that the script database parameter is nil here since it isn't
   152  	// used.  It must be specified when pay-to-script-hash transactions are
   153  	// being signed.
   154  	sigScript, err := txscript.SignTxOutput(&chaincfg.MainNetParams,
   155  		redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
   156  		txscript.KeyClosure(lookupKey), nil, nil)
   157  	if err != nil {
   158  		fmt.Println(err)
   159  		return
   160  	}
   161  	redeemTx.TxIn[0].SignatureScript = sigScript
   162  
   163  	// Prove that the transaction has been validly signed by executing the
   164  	// script pair.
   165  	flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures |
   166  		txscript.ScriptStrictMultiSig |
   167  		txscript.ScriptDiscourageUpgradableNops
   168  	vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
   169  		flags, nil, nil, -1)
   170  	if err != nil {
   171  		fmt.Println(err)
   172  		return
   173  	}
   174  	if err := vm.Execute(); err != nil {
   175  		fmt.Println(err)
   176  		return
   177  	}
   178  	fmt.Println("Transaction successfully signed")
   179  
   180  	// Output:
   181  	// Transaction successfully signed
   182  }