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 }