example_test.go 6.1 KB

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