bitcoin-ruby 0.0.18 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +8 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +46 -0
  5. data/.travis.yml +5 -1
  6. data/Gemfile +11 -9
  7. data/Gemfile.lock +64 -12
  8. data/README.rdoc +17 -4
  9. data/Rakefile +58 -83
  10. data/bitcoin-ruby.gemspec +5 -2
  11. data/lib/bitcoin.rb +31 -14
  12. data/lib/bitcoin/bech32.rb +126 -132
  13. data/lib/bitcoin/bloom_filter.rb +24 -21
  14. data/lib/bitcoin/builder.rb +168 -126
  15. data/lib/bitcoin/connection.rb +21 -24
  16. data/lib/bitcoin/contracthash.rb +20 -24
  17. data/lib/bitcoin/dogecoin.rb +79 -77
  18. data/lib/bitcoin/electrum/mnemonic.rb +28 -25
  19. data/lib/bitcoin/ext_key.rb +3 -3
  20. data/lib/bitcoin/ffi/bitcoinconsensus.rb +17 -13
  21. data/lib/bitcoin/ffi/openssl.rb +355 -338
  22. data/lib/bitcoin/ffi/secp256k1.rb +97 -64
  23. data/lib/bitcoin/protocol.rb +6 -3
  24. data/lib/bitcoin/protocol/address.rb +15 -13
  25. data/lib/bitcoin/protocol/aux_pow.rb +12 -15
  26. data/lib/bitcoin/protocol/block.rb +102 -76
  27. data/lib/bitcoin/protocol/handler.rb +2 -4
  28. data/lib/bitcoin/protocol/parser.rb +108 -92
  29. data/lib/bitcoin/protocol/partial_merkle_tree.rb +59 -47
  30. data/lib/bitcoin/protocol/reject.rb +26 -28
  31. data/lib/bitcoin/protocol/script_witness.rb +3 -8
  32. data/lib/bitcoin/protocol/tx.rb +250 -137
  33. data/lib/bitcoin/protocol/txin.rb +44 -38
  34. data/lib/bitcoin/protocol/txout.rb +27 -20
  35. data/lib/bitcoin/protocol/version.rb +47 -34
  36. data/lib/bitcoin/script.rb +18 -17
  37. data/lib/bitcoin/trezor/mnemonic.rb +113 -98
  38. data/lib/bitcoin/version.rb +1 -1
  39. data/spec/examples.txt +399 -0
  40. data/spec/{bitcoin/fixtures → fixtures}/000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json +0 -0
  41. data/spec/{bitcoin/fixtures → fixtures}/03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99.json +0 -0
  42. data/spec/{bitcoin/fixtures → fixtures}/0961c660358478829505e16a1f028757e54b5bbf9758341a7546573738f31429.json +0 -0
  43. data/spec/{bitcoin/fixtures → fixtures}/0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae.json +0 -0
  44. data/spec/{bitcoin/fixtures → fixtures}/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +0 -0
  45. data/spec/{bitcoin/fixtures → fixtures}/23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63.json +0 -0
  46. data/spec/{bitcoin/fixtures → fixtures}/315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json +0 -0
  47. data/spec/{bitcoin/fixtures → fixtures}/35e2001b428891fefa0bfb73167c7360669d3cbd7b3aa78e7cad125ddfc51131.json +0 -0
  48. data/spec/{bitcoin/fixtures → fixtures}/3a17dace09ffb919ed627a93f1873220f4c975c1248558b18d16bce25d38c4b7.json +0 -0
  49. data/spec/{bitcoin/fixtures → fixtures}/3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json +0 -0
  50. data/spec/{bitcoin/fixtures → fixtures}/514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58.json +0 -0
  51. data/spec/{bitcoin/fixtures → fixtures}/51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e.json +0 -0
  52. data/spec/{bitcoin/fixtures → fixtures}/60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1.json +0 -0
  53. data/spec/{bitcoin/fixtures → fixtures}/69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json +0 -0
  54. data/spec/{bitcoin/fixtures → fixtures}/7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json +0 -0
  55. data/spec/{bitcoin/fixtures → fixtures}/761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6.json +0 -0
  56. data/spec/{bitcoin/fixtures → fixtures}/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +0 -0
  57. data/spec/{bitcoin/fixtures → fixtures}/aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4.json +0 -0
  58. data/spec/{bitcoin/fixtures → fixtures}/base58_keys_invalid.json +0 -0
  59. data/spec/{bitcoin/fixtures → fixtures}/base58_keys_valid.json +0 -0
  60. data/spec/{bitcoin/fixtures → fixtures}/bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json +0 -0
  61. data/spec/{bitcoin/fixtures → fixtures}/bd1715f1abfdc62bea3f605bdb461b3ba1f2cca6ec0d73a18a548b7717ca8531.json +0 -0
  62. data/spec/{bitcoin/fixtures → fixtures}/block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin +0 -0
  63. data/spec/{bitcoin/fixtures → fixtures}/cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2.json +0 -0
  64. data/spec/{bitcoin/fixtures → fixtures}/ce5fad9b4ef094d8f4937b0707edaf0a6e6ceeaf67d5edbfd51f660eac8f398b.json +0 -0
  65. data/spec/{bitcoin/fixtures → fixtures}/coinbase-toshi.json +0 -0
  66. data/spec/{bitcoin/fixtures → fixtures}/coinbase.json +0 -0
  67. data/spec/{bitcoin/fixtures → fixtures}/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  68. data/spec/{bitcoin/fixtures → fixtures}/f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b.json +0 -0
  69. data/spec/{bitcoin/fixtures → fixtures}/filteredblock-0.bin +0 -0
  70. data/spec/{bitcoin/fixtures → fixtures}/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.bin +0 -0
  71. data/spec/{bitcoin/fixtures → fixtures}/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.json +0 -0
  72. data/spec/{bitcoin/fixtures → fixtures}/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.bin +0 -0
  73. data/spec/{bitcoin/fixtures → fixtures}/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.json +0 -0
  74. data/spec/{bitcoin/fixtures → fixtures}/litecoin-tx-f5aa30f574e3b6f1a3d99c07a6356ba812aabb9661e1d5f71edff828cbd5c996.json +0 -0
  75. data/spec/{bitcoin/fixtures → fixtures}/rawblock-0.bin +0 -0
  76. data/spec/{bitcoin/fixtures → fixtures}/rawblock-0.json +0 -0
  77. data/spec/{bitcoin/fixtures → fixtures}/rawblock-1.bin +0 -0
  78. data/spec/{bitcoin/fixtures → fixtures}/rawblock-1.json +0 -0
  79. data/spec/{bitcoin/fixtures → fixtures}/rawblock-131025.bin +0 -0
  80. data/spec/{bitcoin/fixtures → fixtures}/rawblock-131025.json +0 -0
  81. data/spec/{bitcoin/fixtures → fixtures}/rawblock-170.bin +0 -0
  82. data/spec/{bitcoin/fixtures → fixtures}/rawblock-9.bin +0 -0
  83. data/spec/{bitcoin/fixtures → fixtures}/rawblock-auxpow.bin +0 -0
  84. data/spec/{bitcoin/fixtures → fixtures}/rawblock-testnet-1151351.bin +0 -0
  85. data/spec/{bitcoin/fixtures → fixtures}/rawblock-testnet-26478.bin +0 -0
  86. data/spec/{bitcoin/fixtures → fixtures}/rawblock-testnet-26478.json +0 -0
  87. data/spec/{bitcoin/fixtures → fixtures}/rawblock-testnet-265322.bin +0 -0
  88. data/spec/{bitcoin/fixtures → fixtures}/rawtx-01-toshi.json +0 -0
  89. data/spec/{bitcoin/fixtures → fixtures}/rawtx-01.bin +0 -0
  90. data/spec/{bitcoin/fixtures → fixtures}/rawtx-01.json +0 -0
  91. data/spec/{bitcoin/fixtures → fixtures}/rawtx-02-toshi.json +0 -0
  92. data/spec/{bitcoin/fixtures → fixtures}/rawtx-02.bin +0 -0
  93. data/spec/{bitcoin/fixtures → fixtures}/rawtx-02.json +0 -0
  94. data/spec/{bitcoin/fixtures → fixtures}/rawtx-03-toshi.json +0 -0
  95. data/spec/{bitcoin/fixtures → fixtures}/rawtx-03.bin +0 -0
  96. data/spec/{bitcoin/fixtures → fixtures}/rawtx-03.json +0 -0
  97. data/spec/{bitcoin/fixtures → fixtures}/rawtx-04.json +0 -0
  98. data/spec/{bitcoin/fixtures → fixtures}/rawtx-0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9.bin +0 -0
  99. data/spec/{bitcoin/fixtures → fixtures}/rawtx-05.json +0 -0
  100. data/spec/{bitcoin/fixtures → fixtures}/rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin +0 -0
  101. data/spec/{bitcoin/fixtures → fixtures}/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin +0 -0
  102. data/spec/{bitcoin/fixtures → fixtures}/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.json +0 -0
  103. data/spec/{bitcoin/fixtures → fixtures}/rawtx-406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602.json +0 -0
  104. data/spec/{bitcoin/fixtures → fixtures}/rawtx-52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2.bin +0 -0
  105. data/spec/{bitcoin/fixtures → fixtures}/rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin +0 -0
  106. data/spec/{bitcoin/fixtures → fixtures}/rawtx-ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5.json +0 -0
  107. data/spec/{bitcoin/fixtures → fixtures}/rawtx-c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73.json +0 -0
  108. data/spec/{bitcoin/fixtures → fixtures}/rawtx-de35d060663750b3975b7997bde7fb76307cec5b270d12fcd9c4ad98b279c28c.json +0 -0
  109. data/spec/{bitcoin/fixtures → fixtures}/rawtx-f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.bin +0 -0
  110. data/spec/{bitcoin/fixtures → fixtures}/rawtx-p2wpkh.bin +0 -0
  111. data/spec/{bitcoin/fixtures → fixtures}/rawtx-p2wpkh.json +0 -0
  112. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  113. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  114. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  115. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  116. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-a220adf1902c46a39db25a24bc4178b6a88440f977a7e2cabfdd8b5c1dd35cfb.json +0 -0
  117. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  118. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.bin +0 -0
  119. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.json +0 -0
  120. data/spec/{bitcoin/fixtures → fixtures}/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  121. data/spec/{bitcoin/fixtures → fixtures}/script_tests.json +0 -0
  122. data/spec/{bitcoin/fixtures → fixtures}/sighash.json +0 -0
  123. data/spec/{bitcoin/fixtures → fixtures}/tx-0295028ef826b2a188409cb905b631faebb9bb3cdf14510571c5f4bd8591338f.json +0 -0
  124. data/spec/{bitcoin/fixtures → fixtures}/tx-03339a725007a279484fb6f5361f522dd1cf4d0923d30e6b973290dba4275f92.json +0 -0
  125. data/spec/{bitcoin/fixtures → fixtures}/tx-0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3.json +0 -0
  126. data/spec/{bitcoin/fixtures → fixtures}/tx-0ce7e5238fbdb6c086cf1b384b21b827e91cc23f360417265874a5a0d86ce367.json +0 -0
  127. data/spec/{bitcoin/fixtures → fixtures}/tx-0ef34c49f630aea17df0080728b0fc67bf5f87fbda936934a4b11b4a69d7821e.json +0 -0
  128. data/spec/{bitcoin/fixtures → fixtures}/tx-1129d2a8bd5bb3a81e54dc96a90f1f6b2544575748caa17243470935c5dd91b7.json +0 -0
  129. data/spec/{bitcoin/fixtures → fixtures}/tx-19aa42fee0fa57c45d3b16488198b27caaacc4ff5794510d0c17f173f05587ff.json +0 -0
  130. data/spec/{bitcoin/fixtures → fixtures}/tx-1a4f3b9dc4494aeedeb39f30dd37e60541b2abe3ed4977992017cc0ad4f44956.json +0 -0
  131. data/spec/{bitcoin/fixtures → fixtures}/tx-1f9191dcf2b1844ca28c6ef4b969e1d5fab70a5e3c56b7007949e55851cb0c4f.json +0 -0
  132. data/spec/{bitcoin/fixtures → fixtures}/tx-22cd5fef23684d7b304e119bedffde6f54538d3d54a5bfa237e20dc2d9b4b5ad.json +0 -0
  133. data/spec/{bitcoin/fixtures → fixtures}/tx-28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f.json +0 -0
  134. data/spec/{bitcoin/fixtures → fixtures}/tx-2958fb00b4fd6fe0353503b886eb9a193d502f4fd5fc042d5e03216ba918bbd6.json +0 -0
  135. data/spec/{bitcoin/fixtures → fixtures}/tx-29f277145749ad6efbed3ae6ce301f8d33c585ec26b7c044ad93c2f866e9e942.json +0 -0
  136. data/spec/{bitcoin/fixtures → fixtures}/tx-2c5e5376c20e9cc78d0fb771730e5d840cc2096eff0ef045b599fe92475ace1c.json +0 -0
  137. data/spec/{bitcoin/fixtures → fixtures}/tx-2c63aa814701cef5dbd4bbaddab3fea9117028f2434dddcdab8339141e9b14d1.json +0 -0
  138. data/spec/{bitcoin/fixtures → fixtures}/tx-313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0.json +0 -0
  139. data/spec/{bitcoin/fixtures → fixtures}/tx-326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e.json +0 -0
  140. data/spec/{bitcoin/fixtures → fixtures}/tx-345bed8785c3282a264ffb0dbee61cde54854f10e16f1b3e75b7f2d9f62946f2.json +0 -0
  141. data/spec/{bitcoin/fixtures → fixtures}/tx-39ba7440b7103557560cc8ce258009936796485aaf8b478e66ab4cb97c66e31b.json +0 -0
  142. data/spec/{bitcoin/fixtures → fixtures}/tx-3a04d57a833367f1655cc5ec3beb587888ef4977a86caa8c8ad4ba7cc717eae7.json +0 -0
  143. data/spec/{bitcoin/fixtures → fixtures}/tx-3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae.json +0 -0
  144. data/spec/{bitcoin/fixtures → fixtures}/tx-4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9.json +0 -0
  145. data/spec/{bitcoin/fixtures → fixtures}/tx-44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a.json +0 -0
  146. data/spec/{bitcoin/fixtures → fixtures}/tx-46224764c7870f95b58f155bce1e38d4da8e99d42dbb632d0dd7c07e092ee5aa.json +0 -0
  147. data/spec/{bitcoin/fixtures → fixtures}/tx-5df1375ffe61ac35ca178ebb0cab9ea26dedbd0e96005dfcee7e379fa513232f.json +0 -0
  148. data/spec/{bitcoin/fixtures → fixtures}/tx-62d9a565bd7b5344c5352e3e9e5f40fa4bbd467fa19c87357216ec8777ba1cce.json +0 -0
  149. data/spec/{bitcoin/fixtures → fixtures}/tx-6327783a064d4e350c454ad5cd90201aedf65b1fc524e73709c52f0163739190.json +0 -0
  150. data/spec/{bitcoin/fixtures → fixtures}/tx-6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba.json +0 -0
  151. data/spec/{bitcoin/fixtures → fixtures}/tx-6aaf18b9f1283b939d8e5d40ff5f8a435229f4178372659cc3a0bce4e262bf78.json +0 -0
  152. data/spec/{bitcoin/fixtures → fixtures}/tx-6b48bba6f6d2286d7ec0883c0fc3085955090813a4c94980466611c798b868cc.json +0 -0
  153. data/spec/{bitcoin/fixtures → fixtures}/tx-70cfbc6690f9ab46712db44e3079ac227962b2771a9341d4233d898b521619ef.json +0 -0
  154. data/spec/{bitcoin/fixtures → fixtures}/tx-7a1a9db42f065f75110fcdb1bc415549c8ef7670417ba1d35a67f1b8adc562c1.json +0 -0
  155. data/spec/{bitcoin/fixtures → fixtures}/tx-9a768fc7d0c4bdc86e25154357ef7c0063ca21310e5740a2f12f90b7455184a7.json +0 -0
  156. data/spec/{bitcoin/fixtures → fixtures}/tx-9cad8d523a0694f2509d092c39cebc8046adae62b4e4297102d568191d9478d8.json +0 -0
  157. data/spec/{bitcoin/fixtures → fixtures}/tx-9e052eb694bd7e15906433f064dff0161a12fd325c1124537766377004023c6f.json +0 -0
  158. data/spec/{bitcoin/fixtures → fixtures}/tx-9fb65b7304aaa77ac9580823c2c06b259cc42591e5cce66d76a81b6f51cc5c28.json +0 -0
  159. data/spec/{bitcoin/fixtures → fixtures}/tx-a6ce7081addade7676cd2af75c4129eba6bf5e179a19c40c7d4cf6a5fe595954.json +0 -0
  160. data/spec/{bitcoin/fixtures → fixtures}/tx-a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944.json +0 -0
  161. data/spec/{bitcoin/fixtures → fixtures}/tx-aab7ef280abbb9cc6fbaf524d2645c3daf4fcca2b3f53370e618d9cedf65f1f8.json +0 -0
  162. data/spec/{bitcoin/fixtures → fixtures}/tx-ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742.json +0 -0
  163. data/spec/{bitcoin/fixtures → fixtures}/tx-ad4bcf3241e5d2ad140564e20db3567d41594cf4c2012433fe46a2b70e0d87b8.json +0 -0
  164. data/spec/{bitcoin/fixtures → fixtures}/tx-b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9.json +0 -0
  165. data/spec/{bitcoin/fixtures → fixtures}/tx-b8fd633e7713a43d5ac87266adc78444669b987a56b3a65fb92d58c2c4b0e84d.json +0 -0
  166. data/spec/{bitcoin/fixtures → fixtures}/tx-bbca0628c42cb8bf7c3f4b2ad688fa56da5308dd2a10255da89fb1f46e6e413d.json +0 -0
  167. data/spec/{bitcoin/fixtures → fixtures}/tx-bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224.json +0 -0
  168. data/spec/{bitcoin/fixtures → fixtures}/tx-c192b74844e4837a34c4a5a97b438f1c111405b01b99e2d12b7c96d07fc74c04.json +0 -0
  169. data/spec/{bitcoin/fixtures → fixtures}/tx-d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830.json +0 -0
  170. data/spec/{bitcoin/fixtures → fixtures}/tx-e335562f7e297aadeed88e5954bc4eeb8dc00b31d829eedb232e39d672b0c009.json +0 -0
  171. data/spec/{bitcoin/fixtures → fixtures}/tx-eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb.json +0 -0
  172. data/spec/{bitcoin/fixtures → fixtures}/tx-fee1b9b85531c8fb6cd7831f83490c7f2aa768b6eefe29854ef5e89ce7b9ecb1.json +0 -0
  173. data/spec/{bitcoin/fixtures → fixtures}/txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin +0 -0
  174. data/spec/helpers/block_helpers.rb +58 -0
  175. data/spec/helpers/fixture_helpers.rb +20 -0
  176. data/spec/helpers/library_helpers.rb +15 -0
  177. data/spec/spec_helper.rb +109 -0
  178. data/spec/unit/bitcoin/bech32_spec.rb +187 -0
  179. data/spec/unit/bitcoin/bitcoin_spec.rb +1079 -0
  180. data/spec/unit/bitcoin/bloom_filter_spec.rb +33 -0
  181. data/spec/unit/bitcoin/builder_spec.rb +559 -0
  182. data/spec/unit/bitcoin/contracthash_spec.rb +52 -0
  183. data/spec/unit/bitcoin/ext_key_spec.rb +281 -0
  184. data/spec/unit/bitcoin/key_spec.rb +457 -0
  185. data/spec/unit/bitcoin/network_spec.rb +71 -0
  186. data/spec/unit/bitcoin/protocol/addr_spec.rb +90 -0
  187. data/spec/unit/bitcoin/protocol/aux_pow_spec.rb +45 -0
  188. data/spec/unit/bitcoin/protocol/bip143_spec.rb +334 -0
  189. data/spec/unit/bitcoin/protocol/block_spec.rb +280 -0
  190. data/spec/unit/bitcoin/protocol/getblocks_spec.rb +44 -0
  191. data/spec/unit/bitcoin/protocol/inv_spec.rb +166 -0
  192. data/spec/unit/bitcoin/protocol/notfound_spec.rb +44 -0
  193. data/spec/unit/bitcoin/protocol/parser_spec.rb +69 -0
  194. data/spec/unit/bitcoin/protocol/partial_merkle_tree_spec.rb +47 -0
  195. data/spec/unit/bitcoin/protocol/ping_spec.rb +62 -0
  196. data/spec/unit/bitcoin/protocol/tx_spec.rb +1515 -0
  197. data/spec/unit/bitcoin/protocol/txin_spec.rb +47 -0
  198. data/spec/unit/bitcoin/protocol/txout_spec.rb +36 -0
  199. data/spec/unit/bitcoin/protocol/version_spec.rb +121 -0
  200. data/spec/unit/bitcoin/script/opcodes_spec.rb +864 -0
  201. data/spec/unit/bitcoin/script/script_spec.rb +1610 -0
  202. data/spec/unit/bitcoin/secp256k1_spec.rb +138 -0
  203. data/spec/unit/bitcoin/trezor/mnemonic_spec.rb +193 -0
  204. data/spec/unit/integrations/dogecoin_spec.rb +215 -0
  205. metadata +381 -372
  206. data/lib/bitcoin/logger.rb +0 -86
  207. data/lib/bitcoin/protocol/alert.rb +0 -46
  208. data/spec/bitcoin/bech32_spec.rb +0 -160
  209. data/spec/bitcoin/bitcoin_spec.rb +0 -666
  210. data/spec/bitcoin/bloom_filter_spec.rb +0 -23
  211. data/spec/bitcoin/builder_spec.rb +0 -375
  212. data/spec/bitcoin/contracthash_spec.rb +0 -45
  213. data/spec/bitcoin/dogecoin_spec.rb +0 -176
  214. data/spec/bitcoin/ext_key_spec.rb +0 -180
  215. data/spec/bitcoin/ffi_openssl.rb +0 -45
  216. data/spec/bitcoin/fixtures/rawblock-170.json +0 -68
  217. data/spec/bitcoin/fixtures/rawblock-9.json +0 -39
  218. data/spec/bitcoin/fixtures/reorg/blk_0_to_4.dat +0 -0
  219. data/spec/bitcoin/fixtures/reorg/blk_3A.dat +0 -0
  220. data/spec/bitcoin/fixtures/reorg/blk_4A.dat +0 -0
  221. data/spec/bitcoin/fixtures/reorg/blk_5A.dat +0 -0
  222. data/spec/bitcoin/fixtures/testnet/block_0.bin +0 -0
  223. data/spec/bitcoin/fixtures/testnet/block_1.bin +0 -0
  224. data/spec/bitcoin/fixtures/testnet/block_2.bin +0 -0
  225. data/spec/bitcoin/fixtures/testnet/block_3.bin +0 -0
  226. data/spec/bitcoin/fixtures/testnet/block_4.bin +0 -0
  227. data/spec/bitcoin/fixtures/testnet/block_5.bin +0 -0
  228. data/spec/bitcoin/fixtures/txdp-1.txt +0 -32
  229. data/spec/bitcoin/fixtures/txdp-2-signed.txt +0 -19
  230. data/spec/bitcoin/fixtures/txdp-2-unsigned.txt +0 -14
  231. data/spec/bitcoin/helpers/fake_blockchain.rb +0 -183
  232. data/spec/bitcoin/key_spec.rb +0 -326
  233. data/spec/bitcoin/network_spec.rb +0 -50
  234. data/spec/bitcoin/performance/storage_spec.rb +0 -41
  235. data/spec/bitcoin/protocol/addr_spec.rb +0 -82
  236. data/spec/bitcoin/protocol/alert_spec.rb +0 -22
  237. data/spec/bitcoin/protocol/aux_pow_spec.rb +0 -45
  238. data/spec/bitcoin/protocol/bip143_spec.rb +0 -116
  239. data/spec/bitcoin/protocol/block_spec.rb +0 -208
  240. data/spec/bitcoin/protocol/getblocks_spec.rb +0 -32
  241. data/spec/bitcoin/protocol/inv_spec.rb +0 -134
  242. data/spec/bitcoin/protocol/notfound_spec.rb +0 -31
  243. data/spec/bitcoin/protocol/parser_spec.rb +0 -50
  244. data/spec/bitcoin/protocol/partial_merkle_tree_spec.rb +0 -38
  245. data/spec/bitcoin/protocol/ping_spec.rb +0 -51
  246. data/spec/bitcoin/protocol/reject.rb +0 -17
  247. data/spec/bitcoin/protocol/tx_spec.rb +0 -894
  248. data/spec/bitcoin/protocol/txin_spec.rb +0 -45
  249. data/spec/bitcoin/protocol/txout_spec.rb +0 -33
  250. data/spec/bitcoin/protocol/version_spec.rb +0 -110
  251. data/spec/bitcoin/script/opcodes_spec.rb +0 -773
  252. data/spec/bitcoin/script/script_spec.rb +0 -977
  253. data/spec/bitcoin/secp256k1_spec.rb +0 -78
  254. data/spec/bitcoin/spec_helper.rb +0 -108
  255. data/spec/bitcoin/trezor/mnemonic_spec.rb +0 -161
@@ -0,0 +1,1610 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Bitcoin::Script do
7
+ SCRIPT = [
8
+ '410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0' \
9
+ 'eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac',
10
+ '47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd' \
11
+ '410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901',
12
+ '76a91417977bca1b6287a5e6559c57ef4b6525e9d7ded688ac',
13
+ '524104573b6e9f3a714440048a7b87d606bcbf9e45b8586e70a67a3665ea720c09565847' \
14
+ '1a523e5d923f3f3e015626e7c900bd08560ddffeb17d33c5b52c96edb875954104039c2f' \
15
+ '4e413a26901e67ad4adbb6a4759af87bc16c7120459ecc9482fed3dd4a4502947f7b4c77' \
16
+ '82dcadc2bed513ed14d5e770452b97ae246ac2030f13b80a5141048b0f9d04e495c3c754' \
17
+ 'f8c3c109196d713d0778882ef098f785570ee6043f8c192d8f84df43ebafbcc168f5d95a' \
18
+ '074dc4010b62c003e560abc163c312966b74b653ae', # multisig 2 of 3
19
+ '5141040ee607b584b36e995f2e96dec35457dbb40845d0ce0782c84002134e816a6b8cbc' \
20
+ '65e9eed047ae05e10760e4113f690fd49ad73b86b04a1d7813d843f8690ace4104220a78' \
21
+ 'f5f6741bb0739675c2cc200643516b02cfdfda5cba21edeaa62c0f954936b30dfd956e3e' \
22
+ '99af0a8e7665cff6ac5b429c54c418184c81fbcd4bde4088f552ae', # multisig 1 of 2
23
+ 'a9149471864495192e39f5f74574b6c8c513588a820487', # p2sh
24
+ '6a04deadbeef', # OP_RETURN deadbeef
25
+ '00141e205151c90c16475363d11b7b8c235cf6c7d695', # p2wpkh
26
+ '00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0' # p2wsh
27
+ ].map { |s| [s].pack('H*') }.freeze
28
+ PUBKEYS = [
29
+ '04fb0123fe2c399981bc77d522e2ae3268d2ab15e9a84ae49338a4b1db3886a1ea04' \
30
+ 'cdab955d81e9fa1fcb0c062cb9a5af1ad5dd5064f4afcca322402b07030ec2',
31
+ '0423b8161514560bc8638054b6637ab78f400b24e5694ec8061db635d1f28a17902b' \
32
+ '14dbf4f80780da659ab24f11ded3095c780452a4004c30ab58dffac33d839a',
33
+ '04f43e76afac66bf3927638b6c4f7e324513ce56d2d658ac9d24c420d09993a4464e' \
34
+ 'ea6141a68a4748c092ad0e8f4ac29c4a2f661ef4d22b21f20110f42fcd6f6d'
35
+ ].freeze
36
+
37
+ # Build a pay-to-script hash (P2SH) multisig transaction.
38
+ #
39
+ # @param num_to_unlock [Integer] number of key holders required to unlock
40
+ # funds.
41
+ # @param keys [Array<Bitcoin::Key>] key pairs for unlocking funds.
42
+ # @return [Array] previous transaction, transaction, redeem script, and sig
43
+ # hash.
44
+ def build_p2sh_multisig_tx(num_to_unlock, *keys)
45
+ redeem_script = Bitcoin::Script.to_multisig_script(
46
+ num_to_unlock, *keys.map(&:pub)
47
+ )
48
+ p2sh_address = Bitcoin.hash160_to_p2sh_address(
49
+ Bitcoin.hash160(redeem_script.hth)
50
+ )
51
+
52
+ prev_tx = build_tx do |t|
53
+ t.input(&:coinbase)
54
+ t.output do |o|
55
+ o.to p2sh_address
56
+ o.value 50e8
57
+ end
58
+ end
59
+
60
+ tx = build_tx do |t|
61
+ t.input { |i| i.prev_out prev_tx, 0 }
62
+ t.output do |o|
63
+ o.to Bitcoin::Key.generate.addr
64
+ o.value 50e8
65
+ end
66
+ end
67
+
68
+ sig_hash = tx.signature_hash_for_input(0, redeem_script)
69
+
70
+ [prev_tx, tx, redeem_script, sig_hash]
71
+ end
72
+
73
+ describe 'serialization' do
74
+ it '#to_string' do
75
+ expect(Bitcoin::Script.new(SCRIPT[0]).to_string)
76
+ .to eq('0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a69' \
77
+ '09a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f6' \
78
+ '56b412a3 OP_CHECKSIG')
79
+
80
+ expect(Bitcoin::Script.new(SCRIPT[1]).to_string)
81
+ .to eq('304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548' \
82
+ 'ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622' \
83
+ '082221a8768d1d0901')
84
+
85
+ # Bitcoin::Script.new([123].pack('C')).to_string.should == '(opcode 123)'
86
+ expect(Bitcoin::Script.new([176].pack('C')).to_string).to eq('OP_NOP1')
87
+ expect(Bitcoin::Script.from_string('1 OP_DROP 2').to_string).to eq('1 OP_DROP 2')
88
+
89
+ expect(Bitcoin::Script.from_string('4b').to_string).to eq('4b')
90
+ expect(Bitcoin::Script.from_string('4b').to_payload).to eq("\x01\x4b")
91
+ expect(Bitcoin::Script.from_string('ff').to_string).to eq('ff')
92
+ expect(Bitcoin::Script.from_string('ff').to_payload).to eq("\x01\xff")
93
+ expect(Bitcoin::Script.from_string('ffff').to_string).to eq('ffff')
94
+
95
+ expect(
96
+ Bitcoin::Script.from_string('ff' * (Bitcoin::Script::OP_PUSHDATA1 - 1))
97
+ .to_payload[0]
98
+ ).to eq([Bitcoin::Script::OP_PUSHDATA1 - 1].pack('C*'))
99
+ expect(
100
+ Bitcoin::Script.from_string('ff' * Bitcoin::Script::OP_PUSHDATA1)
101
+ .to_payload[0..1]
102
+ ).to eq([Bitcoin::Script::OP_PUSHDATA1, Bitcoin::Script::OP_PUSHDATA1].pack('C*'))
103
+ expect(
104
+ Bitcoin::Script.from_string('ff' * (Bitcoin::Script::OP_PUSHDATA1 + 1))
105
+ .to_payload[0..1]
106
+ ).to eq([Bitcoin::Script::OP_PUSHDATA1, Bitcoin::Script::OP_PUSHDATA1 + 1].pack('C*'))
107
+ expect(Bitcoin::Script.from_string('ff' * 0xff).to_payload[0..1])
108
+ .to eq([Bitcoin::Script::OP_PUSHDATA1, 0xff].pack('C*'))
109
+ expect(Bitcoin::Script.from_string('ff' * (0xff + 1)).to_payload[0..2])
110
+ .to eq([Bitcoin::Script::OP_PUSHDATA2, 0x00, 0x01].pack('C*'))
111
+ expect(Bitcoin::Script.from_string('ff' * 0xffff).to_payload[0..2])
112
+ .to eq([Bitcoin::Script::OP_PUSHDATA2, 0xff, 0xff].pack('C*'))
113
+ expect(Bitcoin::Script.from_string('ff' * (0xffff + 1)).to_payload[0..4])
114
+ .to eq([Bitcoin::Script::OP_PUSHDATA4, 0x00, 0x00, 0x01, 0x00].pack('C*'))
115
+
116
+ expect(Bitcoin::Script.from_string('16').to_string).to eq('16')
117
+ expect(Bitcoin::Script::OP_2_16).to include(Bitcoin::Script.from_string('16').chunks.first)
118
+ expect(Bitcoin::Script.from_string('16').to_payload).to eq("\x60")
119
+ expect(Bitcoin::Script.new("\x60").to_string).to eq('16')
120
+
121
+ expect(Bitcoin::Script.from_string('0:1:16').to_string).to eq('0:1:16')
122
+ expect(Bitcoin::Script::OP_2_16)
123
+ .not_to include(Bitcoin::Script.from_string('0:1:16').chunks.first)
124
+ expect(Bitcoin::Script.from_string('0:1:16').to_payload).to eq("\x01\x16")
125
+ expect(Bitcoin::Script.new("\x01\x16").to_string).to eq('0:1:16')
126
+
127
+ expect(Bitcoin::Script.new("\x4d\x01\x00\x02").to_string).to eq('77:1:02')
128
+ expect(Bitcoin::Script.from_string('77:1:02').to_payload).to eq("\x4d\x01\x00\x02")
129
+ expect(Bitcoin::Script.from_string('77:1:01').to_string).to eq('77:1:01')
130
+ expect(Bitcoin::Script.from_string('77:2:0101').to_string).to eq('77:2:0101')
131
+ expect(Bitcoin::Script.from_string('78:1:01').to_string).to eq('78:1:01')
132
+ expect(Bitcoin::Script.from_string('78:2:0101').to_string).to eq('78:2:0101')
133
+ expect(Bitcoin::Script.new("\x4e\x01\x00\x00\x00\x02").to_string).to eq('78:1:02')
134
+ expect(Bitcoin::Script.from_string('78:1:02').to_payload)
135
+ .to eq("\x4e\x01\x00\x00\x00\x02")
136
+
137
+ expect(Bitcoin::Script.new("\x4d\x01\x00").to_string).to eq('77:1:')
138
+ expect(Bitcoin::Script.from_string('77:1:').to_payload).to eq("\x4d\x01\x00")
139
+
140
+ # data below taken from the outputs of mainnet tx:
141
+ # ebc9fa1196a59e192352d76c0f6e73167046b9d37b8302b6bb6968dfd279b767
142
+ [
143
+ ["\x01", '238:1:01', true],
144
+ ["\x02\x01", '238:2:0201', true],
145
+ ['L', '238:1:4c', true],
146
+ ["L\x02\x01", '76:2:01', nil],
147
+ ['M', '238:1:4d', true],
148
+ ["M\xff\xff\x01", '238:4:4dffff01', true],
149
+ ['N', '238:1:4e', true],
150
+ ["N\xff\xff\xff\xff\x01", '238:6:4effffffff01', true]
151
+ ].each do |payload, string, parse_invalid|
152
+ expect(Bitcoin::Script.new(payload).to_string).to eq(string)
153
+ expect(Bitcoin::Script.new(payload).instance_eval { @parse_invalid })
154
+ .to eq(parse_invalid)
155
+ expect(Bitcoin::Script.from_string(string).to_payload).to eq(payload)
156
+ end
157
+
158
+ expect(Bitcoin::Script.from_string('(opcode-230) 4 1 2').to_string)
159
+ .to eq('(opcode-230) 4 1 2')
160
+ expect(Bitcoin::Script.from_string('(opcode 230) 4 1 2').to_string)
161
+ .to eq('(opcode-230) 4 1 2')
162
+ expect(Bitcoin::Script.from_string('(opcode-65449) 4 1 2').to_string)
163
+ .to eq('OP_INVALIDOPCODE OP_HASH160 4 1 2')
164
+
165
+ # data below found in transactions in testnet3 block
166
+ # 0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab
167
+ expect(Bitcoin::Script.new("\xff\xff\xff\xff").to_string)
168
+ .to eq('OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE')
169
+ expect(Bitcoin::Script.from_string(Bitcoin::Script.new("\xff\xff\xff\xff").to_string).raw)
170
+ .to eq("\xFF\xFF\xFF\xFF")
171
+ expect(Bitcoin::Script.new("\xff\xff\xff").to_string)
172
+ .to eq('OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE')
173
+ expect(Bitcoin::Script.from_string(Bitcoin::Script.new("\xff\xff\xff").to_string).raw)
174
+ .to eq("\xFF\xFF\xFF")
175
+ end
176
+
177
+ it 'Script#binary_from_string' do
178
+ str = Bitcoin::Script.new(SCRIPT[0]).to_string
179
+ expect(Bitcoin::Script.binary_from_string(str).unpack('H*')[0])
180
+ .to eq(SCRIPT[0].unpack('H*')[0])
181
+ expect(Bitcoin::Script.new(Bitcoin::Script.binary_from_string(str)).to_string).to eq(str)
182
+
183
+ str = Bitcoin::Script.new(SCRIPT[1]).to_string
184
+ expect(Bitcoin::Script.binary_from_string(str).unpack('H*')[0])
185
+ .to eq(SCRIPT[1].unpack('H*')[0])
186
+ expect(Bitcoin::Script.new(Bitcoin::Script.binary_from_string(str)).to_string).to eq(str)
187
+
188
+ # TODO: make tests for OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4 cases
189
+
190
+ string = '2 OP_TOALTSTACK 0 OP_TOALTSTACK OP_TUCK OP_CHECKSIG OP_SWAP ' \
191
+ 'OP_HASH160 3cd1def404e12a85ead2b4d3f5f9f817fb0d46ef OP_EQUAL ' \
192
+ 'OP_BOOLAND OP_FROMALTSTACK OP_ADD'
193
+ expect(Bitcoin::Script.from_string(string).to_string).to eq(string)
194
+ expect(Bitcoin::Script.from_string('0 OP_DROP 2 3 4').to_string)
195
+ .to eq('0 OP_DROP 2 3 4')
196
+ expect(Bitcoin::Script.from_string('OP_EVAL').to_string).to eq('OP_NOP1')
197
+ # test opcodes_alias table
198
+ expect(Bitcoin::Script.from_string('OP_NOP1').to_string).to eq('OP_NOP1')
199
+ expect(Bitcoin::Script.from_string('OP_NOP').to_string).to eq('OP_NOP')
200
+ expect(Bitcoin::Script.from_string('1').to_string).to eq('1')
201
+
202
+ expect(
203
+ Bitcoin::Script
204
+ .from_string('0 ffff OP_CODESEPARATOR 1 ffff 1 OP_CHECKMULTISIG')
205
+ .to_string
206
+ ).to eq('0 ffff OP_CODESEPARATOR 1 ffff 1 OP_CHECKMULTISIG')
207
+
208
+ [1, 2, 4].each do |n|
209
+ script = "OP_PUSHDATA#{n} 01 ff"
210
+ expect(Bitcoin::Script.binary_from_string(script))
211
+ .to eq(Bitcoin::Script.binary_from_string(
212
+ Bitcoin::Script.from_string(script).to_string
213
+ ))
214
+ end
215
+
216
+ # expect(Bitcoin::Script.from_string('-100').to_string).to eq('OP_NOP')
217
+ # expect(Bitcoin::Script.from_string('100').to_string).to eq('100')
218
+
219
+ expect do
220
+ Bitcoin::Script.from_string('OP_NOP OP_UNKOWN')
221
+ end.to raise_error(Bitcoin::Script::ScriptOpcodeError,
222
+ 'OP_UNKOWN not defined!')
223
+ end
224
+ end
225
+
226
+ describe 'get keys/addresses' do
227
+ it '#get_pubkey' do
228
+ expect(Bitcoin::Script.new(SCRIPT[0]).get_pubkey)
229
+ .to eq('0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a69' \
230
+ '09a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f6' \
231
+ '56b412a3')
232
+ end
233
+
234
+ it '#get_pubkey_address' do
235
+ expect(Bitcoin::Script.new(SCRIPT[0]).get_pubkey_address)
236
+ .to eq('12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S')
237
+ end
238
+
239
+ it '#get_hash160' do
240
+ expect(Bitcoin::Script.new(SCRIPT[2]).get_hash160)
241
+ .to eq('17977bca1b6287a5e6559c57ef4b6525e9d7ded6')
242
+
243
+ expect(
244
+ Bitcoin::Script
245
+ .from_string('OP_DUP OP_HASH160 0 OP_EQUALVERIFY OP_CHECKSIG')
246
+ .get_hash160
247
+ ).to be_nil
248
+
249
+ expect(Bitcoin::Script.new(SCRIPT[7]).get_hash160)
250
+ .to eq('1e205151c90c16475363d11b7b8c235cf6c7d695')
251
+ end
252
+
253
+ it '#get_hash160_address' do
254
+ expect(Bitcoin::Script.new(SCRIPT[2]).get_hash160_address)
255
+ .to eq('139k1g5rtTsL4aGZbcASH3Fv3fUh9yBEdW')
256
+ end
257
+
258
+ it '#get_multisig_pubkeys' do
259
+ expected = [
260
+ '04573b6e9f3a714440048a7b87d606bcbf9e45b8586e70a67a3665ea720c09565847' \
261
+ '1a523e5d923f3f3e015626e7c900bd08560ddffeb17d33c5b52c96edb87595',
262
+ '04039c2f4e413a26901e67ad4adbb6a4759af87bc16c7120459ecc9482fed3dd4a45' \
263
+ '02947f7b4c7782dcadc2bed513ed14d5e770452b97ae246ac2030f13b80a51',
264
+ '048b0f9d04e495c3c754f8c3c109196d713d0778882ef098f785570ee6043f8c192d' \
265
+ '8f84df43ebafbcc168f5d95a074dc4010b62c003e560abc163c312966b74b6'
266
+ ].map { |pk| [pk].pack('H*') }
267
+ expect(Bitcoin::Script.new(SCRIPT[3]).get_multisig_pubkeys).to eq(expected)
268
+
269
+ expected = [
270
+ '04fb0123fe2c399981bc77d522e2ae3268d2ab15e9a84ae49338a4b1db3886a1ea04' \
271
+ 'cdab955d81e9fa1fcb0c062cb9a5af1ad5dd5064f4afcca322402b07030ec2',
272
+ '0423b8161514560bc8638054b6637ab78f400b24e5694ec8061db635d1f28a17902b' \
273
+ '14dbf4f80780da659ab24f11ded3095c780452a4004c30ab58dffac33d839a',
274
+ '04f43e76afac66bf3927638b6c4f7e324513ce56d2d658ac9d24c420d09993a4464e' \
275
+ 'ea6141a68a4748c092ad0e8f4ac29c4a2f661ef4d22b21f20110f42fcd6f6d'
276
+ ].map { |k| [k].pack('H*') }
277
+ expect(
278
+ Bitcoin::Script
279
+ .from_string("3 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG")
280
+ .get_multisig_pubkeys
281
+ ).to eq(expected)
282
+ end
283
+
284
+ it '#get_multisig_addresses' do
285
+ expected = %w[
286
+ 1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj
287
+ 19Fm2gY7qDTXriNTEhFY2wjxbHna3Gvenk
288
+ 1B6k6g1d2L975i7beAbiBRxfBWhxomPxvy
289
+ ]
290
+ expect(Bitcoin::Script.new(SCRIPT[3]).get_multisig_addresses).to eq(expected)
291
+
292
+ expected = %w[
293
+ 1F2Nnyn7niMcheiYhkHrkc18aDxEkFowy5
294
+ 1EE7JGimkV7QqyHwXDJvk3b1yEN4ZUWeqx
295
+ ]
296
+ expect(Bitcoin::Script.new(SCRIPT[4]).get_multisig_addresses).to eq(expected)
297
+
298
+ # from tx
299
+ # 274f8be3b7b9b1a220285f5f71f61e2691dd04df9d69bb02a8b3b85f91fb1857, second
300
+ # pubkey has invalid encoding.
301
+ output =
302
+ '1 0351efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da78' \
303
+ ' 00f2b7816db49d55d24df7bdffdbc1e203b424e8cd39f5651ab938e5e4a193569e ' \
304
+ '2 OP_CHECKMULTISIG'
305
+ expect(
306
+ Bitcoin::Script.from_string(output).get_multisig_addresses
307
+ ).to eq(['1NdB761LmTmrJixxp93nz7pEiCx5cKPW44', nil])
308
+ end
309
+
310
+ it '#get_p2sh_address' do
311
+ expect(Bitcoin::Script.new(SCRIPT[5]).get_p2sh_address)
312
+ .to eq('3FDuvkgzsW7LpzL9RBjtjvL7bFXCEeZ7xi')
313
+ end
314
+
315
+ it '#get_address' do
316
+ expect(Bitcoin::Script.new(SCRIPT[0]).get_address)
317
+ .to eq('12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S')
318
+ expect(Bitcoin::Script.new(SCRIPT[1]).get_address).to be_nil
319
+ expect(Bitcoin::Script.new(SCRIPT[2]).get_address)
320
+ .to eq('139k1g5rtTsL4aGZbcASH3Fv3fUh9yBEdW')
321
+ expect(Bitcoin::Script.new(SCRIPT[3]).get_address)
322
+ .to eq('1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj')
323
+ expect(Bitcoin::Script.new(SCRIPT[4]).get_address)
324
+ .to eq('1F2Nnyn7niMcheiYhkHrkc18aDxEkFowy5')
325
+ expect(Bitcoin::Script.new(SCRIPT[5]).get_address)
326
+ .to eq('3FDuvkgzsW7LpzL9RBjtjvL7bFXCEeZ7xi')
327
+ expect(Bitcoin::Script.new(SCRIPT[7]).get_address)
328
+ .to eq('bc1qrcs9z5wfpstyw5mr6ydhhrprtnmv0454y6laym')
329
+ expect(Bitcoin::Script.new(SCRIPT[8]).get_address)
330
+ .to eq('bc1qt5d4dd3aw98whe2zxz2jtayykl5ada5xkdupkmmpa7f96ekk76sqvmrunq')
331
+ end
332
+
333
+ it '#get_addresses' do
334
+ expect(Bitcoin::Script.new(SCRIPT[0]).get_addresses)
335
+ .to eq(['12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S'])
336
+ expect(Bitcoin::Script.new(SCRIPT[3]).get_addresses)
337
+ .to eq(%w[1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj
338
+ 19Fm2gY7qDTXriNTEhFY2wjxbHna3Gvenk
339
+ 1B6k6g1d2L975i7beAbiBRxfBWhxomPxvy])
340
+ expect(Bitcoin::Script.new(SCRIPT[7]).get_addresses)
341
+ .to eq(['bc1qrcs9z5wfpstyw5mr6ydhhrprtnmv0454y6laym'])
342
+ end
343
+
344
+ it 'should get op_return data' do
345
+ expect(Bitcoin::Script.new(SCRIPT[6]).get_op_return_data).to eq('deadbeef')
346
+ expect(Bitcoin::Script.new(SCRIPT[1]).get_op_return_data).to be_nil
347
+ expect(Bitcoin::Script.from_string('OP_RETURN').get_op_return_data).to be_nil
348
+ expect(Bitcoin::Script.from_string('OP_RETURN dead beef').get_op_return_data)
349
+ .to be_nil
350
+ expect(Bitcoin::Script.from_string('OP_RETURN deadbeef').get_op_return_data)
351
+ .to eq('deadbeef')
352
+ expect(Bitcoin::Script.from_string('OP_RETURN OP_CHECKSIG').get_op_return_data)
353
+ .to eq('ac00')
354
+ end
355
+ end
356
+
357
+ describe 'determine type' do
358
+ it '#is_standard?' do
359
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_standard?).to be true
360
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_standard?).to be false
361
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_standard?).to be true
362
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_standard?).to be true
363
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_standard?).to be true
364
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_standard?).to be true
365
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_standard?).to be true
366
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_standard?).to be true
367
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_standard?).to be true
368
+ end
369
+
370
+ it '#is_pubkey?' do
371
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_pubkey?).to be true
372
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_pubkey?).to be false
373
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_pubkey?).to be false
374
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_pubkey?).to be false
375
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_send_to_ip?).to be false
376
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_pubkey?).to be false
377
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_pubkey?).to be false
378
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_pubkey?).to be false
379
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_pubkey?).to be false
380
+
381
+ # testnet aba0441c4c9933dcd7db789c39053739ec435ab742ed2c23c05f22f1488c0bfd
382
+ expect(Bitcoin::Script.from_string('0 OP_CHECKSIG').is_pubkey?)
383
+ .to be false
384
+ end
385
+
386
+ it '#is_hash160?' do
387
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_hash160?).to be false
388
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_pubkey?).to be false
389
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_hash160?).to be true
390
+ expect(
391
+ Bitcoin::Script.from_string('OP_DUP OP_HASH160 0 OP_EQUALVERIFY OP_CHECKSIG')
392
+ .is_hash160?
393
+ ).to be false
394
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_hash160?).to be false
395
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_hash160?).to be false
396
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_hash160?).to be false
397
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_hash160?).to be false
398
+ end
399
+
400
+ it '#is_multisig?' do
401
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_multisig?).to be true
402
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_multisig?).to be true
403
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_multisig?).to be false
404
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_multisig?).to be false
405
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_multisig?).to be false
406
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_multisig?).to be false
407
+ expect(
408
+ Bitcoin::Script.new("OP_DUP OP_DROP 2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG")
409
+ .is_multisig?
410
+ ).to be false
411
+ expect(Bitcoin::Script.new('OP_DROP OP_CHECKMULTISIG').is_multisig?)
412
+ .to be false
413
+ expect(
414
+ Bitcoin::Script.from_string(
415
+ 'd366fb5cbf048801b1bf0742bb0d873f65afb406f41756bd4a31865870f6a928 ' \
416
+ 'OP_DROP 2 ' \
417
+ '02aae4b5cd593da83679a9c5cadad4c180c008a40dd3ed240cceb2933b9912da36 ' \
418
+ '03a5aebd8b1b6eec06abc55fb13c72a9ed2143f9eed7d665970e38853d564bf1ab ' \
419
+ 'OP_CHECKMULTISIG'
420
+ ).is_multisig?
421
+ ).to be false
422
+ end
423
+
424
+ it '#is_p2sh?' do
425
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_p2sh?).to be false
426
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_p2sh?).to be false
427
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_p2sh?).to be false
428
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_p2sh?).to be false
429
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_p2sh?).to be false
430
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_p2sh?).to be true
431
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_p2sh?).to be false
432
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_p2sh?).to be false
433
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_p2sh?).to be false
434
+ expect(
435
+ Bitcoin::Script.from_string(
436
+ 'OP_DUP OP_HASH160 b689ebc262f50297139e7d16c4f8909e14ed4322 ' \
437
+ 'OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_HASH160 ' \
438
+ '1b6246121883816fc0637e4aa280aca1df219b1a OP_EQUAL'
439
+ ).is_p2sh?
440
+ ).to be false
441
+ end
442
+
443
+ it '#is_op_return?' do
444
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_op_return?).to be false
445
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_op_return?).to be false
446
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_op_return?).to be false
447
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_op_return?).to be false
448
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_op_return?).to be false
449
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_op_return?).to be false
450
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_op_return?).to be true
451
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_op_return?).to be false
452
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_op_return?).to be false
453
+ expect(Bitcoin::Script.from_string('OP_RETURN dead beef').is_op_return?)
454
+ .to be false
455
+ expect(Bitcoin::Script.from_string('OP_RETURN deadbeef').is_op_return?)
456
+ .to be true
457
+ expect(Bitcoin::Script.from_string('OP_RETURN OP_CHECKSIG').is_op_return?)
458
+ .to be true
459
+ end
460
+
461
+ it '#is_witness_v0_keyhash?' do
462
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_witness_v0_keyhash?).to be false
463
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_witness_v0_keyhash?).to be false
464
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_witness_v0_keyhash?).to be false
465
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_witness_v0_keyhash?).to be false
466
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_witness_v0_keyhash?).to be false
467
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_witness_v0_keyhash?).to be false
468
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_witness_v0_keyhash?).to be false
469
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_witness_v0_keyhash?).to be true
470
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_witness_v0_keyhash?).to be false
471
+ end
472
+
473
+ it '#is_witness_v0_scripthash?' do
474
+ expect(Bitcoin::Script.new(SCRIPT[0]).is_witness_v0_scripthash?).to be false
475
+ expect(Bitcoin::Script.new(SCRIPT[1]).is_witness_v0_scripthash?).to be false
476
+ expect(Bitcoin::Script.new(SCRIPT[2]).is_witness_v0_scripthash?).to be false
477
+ expect(Bitcoin::Script.new(SCRIPT[3]).is_witness_v0_scripthash?).to be false
478
+ expect(Bitcoin::Script.new(SCRIPT[4]).is_witness_v0_scripthash?).to be false
479
+ expect(Bitcoin::Script.new(SCRIPT[5]).is_witness_v0_scripthash?).to be false
480
+ expect(Bitcoin::Script.new(SCRIPT[6]).is_witness_v0_scripthash?).to be false
481
+ expect(Bitcoin::Script.new(SCRIPT[7]).is_witness_v0_scripthash?).to be false
482
+ expect(Bitcoin::Script.new(SCRIPT[8]).is_witness_v0_scripthash?).to be true
483
+ end
484
+
485
+ it '#type' do
486
+ expect(Bitcoin::Script.new(SCRIPT[0]).type).to eq(:pubkey)
487
+ expect(Bitcoin::Script.new(SCRIPT[1]).type).to eq(:unknown)
488
+ expect(Bitcoin::Script.new(SCRIPT[2]).type).to eq(:hash160)
489
+ expect(Bitcoin::Script.new(SCRIPT[3]).type).to eq(:multisig)
490
+ expect(Bitcoin::Script.new(SCRIPT[4]).type).to eq(:multisig)
491
+ expect(Bitcoin::Script.new(SCRIPT[5]).type).to eq(:p2sh)
492
+ expect(Bitcoin::Script.new(SCRIPT[6]).type).to eq(:op_return)
493
+ expect(Bitcoin::Script.new(SCRIPT[7]).type).to eq(:witness_v0_keyhash)
494
+ expect(Bitcoin::Script.new(SCRIPT[8]).type).to eq(:witness_v0_scripthash)
495
+ expect(Bitcoin::Script.from_string('OP_RETURN OP_CHECKSIG').type)
496
+ .to eq(:op_return)
497
+ expect(Bitcoin::Script.from_string('OP_RETURN dead beef').type)
498
+ .to eq(:unknown)
499
+ end
500
+ end
501
+
502
+ describe 'generate scripts' do
503
+ it 'should generate pubkey script' do
504
+ expect(Bitcoin::Script.to_pubkey_script(PUBKEYS[0]))
505
+ .to eq(Bitcoin::Script.from_string("#{PUBKEYS[0]} OP_CHECKSIG").raw)
506
+ expect(Bitcoin::Script.to_pubkey_script(PUBKEYS[1]))
507
+ .to eq(Bitcoin::Script.from_string("#{PUBKEYS[1]} OP_CHECKSIG").raw)
508
+ end
509
+
510
+ it 'should generate hash160 script' do
511
+ expect(
512
+ Bitcoin::Script.to_address_script('16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9')
513
+ ).to eq(['76a9143be0c2daaabbf3d53e47352c19d1e8f047e2f94188ac'].pack('H*'))
514
+
515
+ hash160 = Bitcoin.hash160_from_address('16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9')
516
+ expect(Bitcoin::Script.to_hash160_script(hash160))
517
+ .to eq(
518
+ Bitcoin::Script.from_string(
519
+ "OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG"
520
+ ).raw
521
+ )
522
+ expect(Bitcoin::Script.to_address_script('mr1jU3Adw2pkvxTLvQA4MKpXB9Dynj9cXF'))
523
+ .to be_nil
524
+ end
525
+
526
+ it 'should generate multisig script' do
527
+ expect(Bitcoin::Script.to_multisig_script(2, *PUBKEYS[0..2]))
528
+ .to eq(
529
+ Bitcoin::Script.from_string(
530
+ "2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG"
531
+ ).raw
532
+ )
533
+ expect(Bitcoin::Script.to_multisig_script(1, *PUBKEYS[0..1]))
534
+ .to eq(
535
+ Bitcoin::Script.from_string(
536
+ "1 #{PUBKEYS[0..1].join(' ')} 2 OP_CHECKMULTISIG"
537
+ ).raw
538
+ )
539
+
540
+ m = n = 16
541
+ expect(
542
+ Bitcoin::Script.new(
543
+ Bitcoin::Script.to_multisig_script(m, *(['a'] * n))
544
+ ).to_string
545
+ ).to eq('16 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 16 ' \
546
+ 'OP_CHECKMULTISIG')
547
+
548
+ m = n = 17
549
+ expect(
550
+ Bitcoin::Script.new(
551
+ Bitcoin::Script.to_multisig_script(m, *(['a'] * n))
552
+ ).to_string
553
+ ).to eq('0:1:11 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 ' \
554
+ '0:1:11 OP_CHECKMULTISIG')
555
+
556
+ m = n = 20
557
+ expect(
558
+ Bitcoin::Script.new(
559
+ Bitcoin::Script.to_multisig_script(m, *(['a'] * n))
560
+ ).to_string
561
+ ).to eq('0:1:14 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 ' \
562
+ 'a0 a0 0:1:14 OP_CHECKMULTISIG')
563
+ end
564
+
565
+ it 'should generate p2sh script' do
566
+ address = '3CkxTG25waxsmd13FFgRChPuGYba3ar36B'
567
+ hash160 = Bitcoin.hash160_from_address address
568
+ expect(Bitcoin::Script.to_p2sh_script(hash160))
569
+ .to eq(Bitcoin::Script.from_string("OP_HASH160 #{hash160} OP_EQUAL").raw)
570
+ end
571
+
572
+ it 'to_witness_hash160_script' do
573
+ hash160 = Bitcoin.hash160(
574
+ '025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357'
575
+ )
576
+ expect(Bitcoin::Script.to_witness_hash160_script(hash160))
577
+ .to eq(Bitcoin::Script.new('00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1'.htb).raw)
578
+ end
579
+
580
+ it 'should generate p2wsh script' do
581
+ witness_script =
582
+ '21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880a' \
583
+ 'eadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d021' \
584
+ '5ea465ac'
585
+ sha256 = Bitcoin.sha256(witness_script)
586
+ expect(Bitcoin::Script.to_witness_p2sh_script(sha256))
587
+ .to eq(Bitcoin::Script.new('00205d1b56b63d714eebe542309525f484b7e9d6f686b3781' \
588
+ 'b6f61ef925d66d6f6a0'.htb).raw)
589
+ end
590
+
591
+ it 'should generate op_return script' do
592
+ expect(Bitcoin::Script.to_op_return_script('deadbeef')).to eq(SCRIPT[6])
593
+ expect(Bitcoin::Script.to_op_return_script)
594
+ .to eq(Bitcoin::Script.from_string('OP_RETURN').raw)
595
+ end
596
+
597
+ it 'should determine type for address script' do
598
+ address = '16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9'
599
+ hash160 = Bitcoin.hash160_from_address address
600
+ expect(Bitcoin::Script.to_address_script(address))
601
+ .to eq(
602
+ Bitcoin::Script.from_string(
603
+ "OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG"
604
+ ).raw
605
+ )
606
+
607
+ address = '3CkxTG25waxsmd13FFgRChPuGYba3ar36B'
608
+ hash160 = Bitcoin.hash160_from_address address
609
+ expect(Bitcoin::Script.to_p2sh_script(hash160))
610
+ .to eq(Bitcoin::Script.from_string("OP_HASH160 #{hash160} OP_EQUAL").raw)
611
+ end
612
+ end
613
+
614
+ describe 'generate script sigs' do
615
+ let(:sig) do
616
+ '3045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e054' \
617
+ '2f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08f' \
618
+ 'ec'.htb
619
+ end
620
+
621
+ it 'should generate pubkey script sig' do
622
+ pub =
623
+ '04bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5' \
624
+ 'f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
625
+ expected_script =
626
+ '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051' \
627
+ 'e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086e' \
628
+ 'e0a08fec014104bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda' \
629
+ '3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2e' \
630
+ 'ed983c'.htb
631
+
632
+ expect(Bitcoin::Script.to_pubkey_script_sig(sig, pub))
633
+ .to eq(expected_script)
634
+ end
635
+
636
+ it 'should accept a compressed public key as input' do
637
+ pub =
638
+ '02bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'.htb
639
+ expected_script =
640
+ '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a0' \
641
+ '51e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe' \
642
+ '086ee0a08fec012102bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab' \
643
+ '98acda3c4bf45e41'.htb
644
+
645
+ expect(Bitcoin::Script.to_pubkey_script_sig(sig, pub))
646
+ .to eq(expected_script)
647
+ end
648
+
649
+ it 'should reject an improperly encoding public key' do
650
+ pub = '02bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'
651
+
652
+ expect do
653
+ Bitcoin::Script.to_pubkey_script_sig(sig, pub)
654
+ end.to raise_error(RuntimeError, 'pubkey is not in binary form')
655
+ end
656
+
657
+ it 'should support different hash types' do
658
+ hash_type = Bitcoin::Script::SIGHASH_TYPE[:single]
659
+ pub =
660
+ '04bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5' \
661
+ 'f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
662
+ expected_script =
663
+ '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051' \
664
+ 'e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086e' \
665
+ 'e0a08fec034104bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda' \
666
+ '3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2e' \
667
+ 'ed983c'.htb
668
+
669
+ expect(Bitcoin::Script.to_pubkey_script_sig(sig, pub, hash_type))
670
+ .to eq(expected_script)
671
+ end
672
+
673
+ it 'should generate multisig script sig' do
674
+ hash_type = Bitcoin::Script::SIGHASH_TYPE[:none]
675
+ expected_script =
676
+ '00483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a' \
677
+ '051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe' \
678
+ '086ee0a08fec02483045022062437a8f60651cd968137355775fa8bdb83d4ca717f' \
679
+ 'dbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484' \
680
+ 'd6335874edfe086ee0a08fec02'.htb
681
+
682
+ expect(Bitcoin::Script.to_multisig_script_sig(sig, sig, hash_type))
683
+ .to eq(expected_script)
684
+ end
685
+ end
686
+
687
+ describe 'signatures_count' do
688
+ it 'should be zero in data-only scripts' do
689
+ [false, true].each do |accurate|
690
+ expect(Bitcoin::Script.from_string('').sigops_count_accurate(accurate))
691
+ .to eq(0)
692
+ expect(
693
+ Bitcoin::Script.from_string('DEADBEEF').sigops_count_accurate(accurate)
694
+ ).to eq(0)
695
+ expect(
696
+ Bitcoin::Script.from_string('DEAD BEEF').sigops_count_accurate(accurate)
697
+ ).to eq(0)
698
+ expect(
699
+ Bitcoin::Script.from_string('DE AD BE EF').sigops_count_accurate(accurate)
700
+ ).to eq(0)
701
+ expect(
702
+ Bitcoin::Script.from_string('OP_NOP').sigops_count_accurate(accurate)
703
+ ).to eq(0)
704
+ expect(
705
+ Bitcoin::Script.from_string('0').sigops_count_accurate(accurate)
706
+ ).to eq(0)
707
+ expect(
708
+ Bitcoin::Script.from_string('0 1').sigops_count_accurate(accurate)
709
+ ).to eq(0)
710
+ expect(
711
+ Bitcoin::Script.from_string('0 1 2 3').sigops_count_accurate(accurate)
712
+ ).to eq(0)
713
+ end
714
+ end
715
+
716
+ it 'should count sigops' do
717
+ [false, true].each do |accurate|
718
+ expect(
719
+ Bitcoin::Script.from_string('OP_CHECKSIG').sigops_count_accurate(accurate)
720
+ ).to eq(1)
721
+ expect(
722
+ Bitcoin::Script.from_string('OP_CHECKSIGVERIFY')
723
+ .sigops_count_accurate(accurate)
724
+ ).to eq(1)
725
+ expect(
726
+ Bitcoin::Script.from_string('OP_CHECKSIG OP_CHECKSIGVERIFY')
727
+ .sigops_count_accurate(accurate)
728
+ ).to eq(2)
729
+ expect(
730
+ Bitcoin::Script.from_string(
731
+ 'OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG'
732
+ ).sigops_count_accurate(accurate)
733
+ ).to eq(4)
734
+ expect(
735
+ Bitcoin::Script.from_string(
736
+ '1 OP_CHECKSIG 2 OP_CHECKSIG DEADBEEF OP_CHECKSIG 3 OP_CHECKSIG 4'
737
+ ).sigops_count_accurate(accurate)
738
+ ).to eq(4)
739
+ end
740
+ end
741
+
742
+ it 'should count multisig as 20 sigops in legact inaccurate mode' do
743
+ expect(
744
+ Bitcoin::Script.from_string('OP_CHECKMULTISIG')
745
+ .sigops_count_accurate(false)
746
+ ).to eq(20)
747
+ expect(
748
+ Bitcoin::Script.from_string('OP_CHECKMULTISIGVERIFY')
749
+ .sigops_count_accurate(false)
750
+ ).to eq(20)
751
+ expect(
752
+ Bitcoin::Script.from_string('OP_CHECKMULTISIG OP_CHECKMULTISIGVERIFY')
753
+ .sigops_count_accurate(false)
754
+ ).to eq(40)
755
+ expect(
756
+ Bitcoin::Script.from_string('1 OP_CHECKMULTISIG')
757
+ .sigops_count_accurate(false)
758
+ ).to eq(20)
759
+ expect(
760
+ Bitcoin::Script.from_string('5 OP_CHECKMULTISIG')
761
+ .sigops_count_accurate(false)
762
+ ).to eq(20)
763
+ expect(
764
+ Bitcoin::Script.from_string('40 OP_CHECKMULTISIG')
765
+ .sigops_count_accurate(false)
766
+ ).to eq(20)
767
+ end
768
+
769
+ it 'should count multisig accurately using number of pubkeys' do
770
+ expect(
771
+ Bitcoin::Script.from_string('1 OP_CHECKMULTISIG')
772
+ .sigops_count_accurate(true)
773
+ ).to eq(1)
774
+ expect(
775
+ Bitcoin::Script.from_string('1 OP_CHECKMULTISIGVERIFY')
776
+ .sigops_count_accurate(true)
777
+ ).to eq(1)
778
+ expect(
779
+ Bitcoin::Script.from_string('2 OP_CHECKMULTISIG')
780
+ .sigops_count_accurate(true)
781
+ ).to eq(2)
782
+ expect(
783
+ Bitcoin::Script.from_string('2 OP_CHECKMULTISIGVERIFY')
784
+ .sigops_count_accurate(true)
785
+ ).to eq(2)
786
+ expect(
787
+ Bitcoin::Script.from_string('15 OP_CHECKMULTISIG')
788
+ .sigops_count_accurate(true)
789
+ ).to eq(15)
790
+ expect(
791
+ Bitcoin::Script.from_string('15 OP_CHECKMULTISIGVERIFY')
792
+ .sigops_count_accurate(true)
793
+ ).to eq(15)
794
+ expect(
795
+ Bitcoin::Script.from_string('16 OP_CHECKMULTISIG')
796
+ .sigops_count_accurate(true)
797
+ ).to eq(16)
798
+ expect(
799
+ Bitcoin::Script.from_string('16 OP_CHECKMULTISIGVERIFY')
800
+ .sigops_count_accurate(true)
801
+ ).to eq(16)
802
+ expect(
803
+ Bitcoin::Script.from_string('4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY')
804
+ .sigops_count_accurate(true)
805
+ ).to eq(11)
806
+ end
807
+
808
+ it 'should count multisig as 20 sigops in accurate mode when the pubkey count is missing' do
809
+ expect(
810
+ Bitcoin::Script.from_string('OP_CHECKMULTISIG')
811
+ .sigops_count_accurate(true)
812
+ ).to eq(20)
813
+ expect(
814
+ Bitcoin::Script.from_string('OP_CHECKMULTISIGVERIFY')
815
+ .sigops_count_accurate(true)
816
+ ).to eq(20)
817
+ end
818
+
819
+ it 'should count multisig as 20 sigops when pubkey count is not ' \
820
+ 'OP_{1,...,16}, but bignum as pushdata' do
821
+ expect(
822
+ Bitcoin::Script.from_string(
823
+ "#{Bitcoin::Script::OP_PUSHDATA1}:1:01 OP_CHECKMULTISIG"
824
+ ).sigops_count_accurate(true)
825
+ ).to eq(20)
826
+ expect(
827
+ Bitcoin::Script.from_string(
828
+ "#{Bitcoin::Script::OP_PUSHDATA1}:1:02 OP_CHECKMULTISIGVERIFY"
829
+ ).sigops_count_accurate(true)
830
+ ).to eq(20)
831
+ end
832
+
833
+ it 'should count multisig as 20 sigops in accurate mode when the pubkey ' \
834
+ 'count is out of bounds' do
835
+ expect(
836
+ Bitcoin::Script.from_string('0 OP_CHECKMULTISIG')
837
+ .sigops_count_accurate(true)
838
+ ).to eq(20)
839
+ expect(
840
+ Bitcoin::Script.from_string('0 OP_CHECKMULTISIGVERIFY')
841
+ .sigops_count_accurate(true)
842
+ ).to eq(20)
843
+ expect(
844
+ Bitcoin::Script.from_string('0 OP_CHECKMULTISIG 0 OP_CHECKMULTISIGVERIFY')
845
+ .sigops_count_accurate(true)
846
+ ).to eq(40)
847
+ expect(
848
+ Bitcoin::Script.from_string('DEADBEEF OP_CHECKMULTISIG')
849
+ .sigops_count_accurate(true)
850
+ ).to eq(20)
851
+ expect(
852
+ Bitcoin::Script.from_string(
853
+ "#{Bitcoin::Script::OP_PUSHDATA1}:1:11 OP_CHECKMULTISIG"
854
+ ).sigops_count_accurate(true)
855
+ ).to eq(20)
856
+ end
857
+
858
+ it 'should extract signature count from P2SH scriptSig' do
859
+ # Given a P2SH input script (the one with the signatures and a serialized script inside)
860
+ # This should count as 12 sigops (1 + 4 + 7)
861
+ script = Bitcoin::Script.from_string(
862
+ 'OP_CHECKSIG 4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY'
863
+ )
864
+
865
+ # Serialize the script to be used as a plain pushdata (which will be decoded as a script).
866
+ serialized_script =
867
+ Bitcoin::Script.new('').append_pushdata(script.to_binary)
868
+
869
+ # If empty should return 0.
870
+ expect(Bitcoin::Script.from_string('').sigops_count_for_p2sh).to eq(0)
871
+
872
+ # If ends with OP_N
873
+ expect(Bitcoin::Script.from_string('0').sigops_count_for_p2sh).to eq(0)
874
+ expect(Bitcoin::Script.from_string('1').sigops_count_for_p2sh).to eq(0)
875
+ expect(Bitcoin::Script.from_string('5').sigops_count_for_p2sh).to eq(0)
876
+ expect(Bitcoin::Script.from_string('16').sigops_count_for_p2sh).to eq(0)
877
+
878
+ # If ends with opcode
879
+ expect(Bitcoin::Script.from_string('OP_NOP').sigops_count_for_p2sh)
880
+ .to eq(0)
881
+ expect(Bitcoin::Script.from_string('OP_HASH160').sigops_count_for_p2sh)
882
+ .to eq(0)
883
+ expect(Bitcoin::Script.from_string('OP_CHECKSIG').sigops_count_for_p2sh)
884
+ .to eq(0)
885
+ expect(Bitcoin::Script.from_string('DEADBEEF OP_NOP').sigops_count_for_p2sh)
886
+ .to eq(0)
887
+ expect(
888
+ Bitcoin::Script.from_string('DEADBEEF OP_HASH160').sigops_count_for_p2sh
889
+ ).to eq(0)
890
+ expect(
891
+ Bitcoin::Script.from_string('DEADBEEF OP_CHECKSIG').sigops_count_for_p2sh
892
+ ).to eq(0)
893
+
894
+ # If only has the script, should parse it well
895
+ expect(serialized_script.sigops_count_for_p2sh).to eq(12)
896
+
897
+ # If ends with the script, should also parse well.
898
+ expect(
899
+ Bitcoin::Script.new(
900
+ Bitcoin::Script.from_string('DEADBEEF CAFEBABE').to_binary +
901
+ serialized_script.to_binary
902
+ ).sigops_count_for_p2sh
903
+ ).to eq(12)
904
+ expect(
905
+ Bitcoin::Script.new(
906
+ Bitcoin::Script.from_string('DEADBEEF 1').to_binary +
907
+ serialized_script.to_binary
908
+ ).sigops_count_for_p2sh
909
+ ).to eq(12)
910
+
911
+ # If has the script, but ends with non-script, should return 0 DEADBEEF is
912
+ # a script with OP_CHECKSIGVERIFY in it, so we wrap it in a serialized
913
+ # script with plain pushdata to have 0 count.
914
+ expect(
915
+ Bitcoin::Script.new(
916
+ serialized_script.to_binary +
917
+ Bitcoin::Script.new('').append_pushdata(
918
+ Bitcoin::Script.from_string('DEADBEEF').to_binary
919
+ ).to_binary
920
+ ).sigops_count_for_p2sh
921
+ ).to eq(0)
922
+ expect(
923
+ Bitcoin::Script.new(
924
+ serialized_script.to_binary +
925
+ Bitcoin::Script.from_string('1').to_binary
926
+ ).sigops_count_for_p2sh
927
+ ).to eq(0)
928
+ end
929
+
930
+ it 'should count sigops up until an invalid OP_PUSHDATA' do
931
+ script_binary = Bitcoin::Protocol.read_binary_file(
932
+ fixtures_path(
933
+ 'txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin'
934
+ )
935
+ )
936
+ expect(
937
+ Bitcoin::Script.new(script_binary).sigops_count_accurate(false)
938
+ ).to eq(39_998)
939
+ end
940
+ end
941
+
942
+ it '#run' do
943
+ script = SCRIPT[1] + SCRIPT[0]
944
+ expect(Bitcoin::Script.new(script).run).to be true
945
+
946
+ expect(Bitcoin::Script.from_string('1 OP_DUP OP_DROP 1 OP_EQUAL').run)
947
+ .to be true
948
+ expect(Bitcoin::Script.from_string('1 OP_DUP OP_DROP 1 OP_EQUAL').run)
949
+ .to be true
950
+ expect(Bitcoin::Script.from_string('foo OP_DUP OP_DROP foo OP_EQUAL').run)
951
+ .to be true
952
+ expect(Bitcoin::Script.from_string('bar foo OP_DUP OP_DROP bar OP_EQUAL').run)
953
+ .to be false
954
+
955
+ expect(Bitcoin::Script.from_string('1 OP_DROP 2').run).to be true
956
+
957
+ # testnet3 tx:
958
+ # 5dea81f9d9d2ea6d06ce23ff225d1e240392519017643f75c96fa2e4316d948a
959
+ script =
960
+ Bitcoin::Script.new(['0063bac0d0e0f0f1f2f3f3f4ff675168'].pack('H*'))
961
+ expect(script.to_string)
962
+ .to eq('0 OP_IF (opcode-186) (opcode-192) (opcode-208) (opcode-224) ' \
963
+ '(opcode-240) (opcode-241) (opcode-242) (opcode-243) ' \
964
+ '(opcode-243) (opcode-244) OP_INVALIDOPCODE OP_ELSE 1 OP_ENDIF')
965
+ expect(script.run).to be true
966
+
967
+ # mainnet tx:
968
+ # 61a078472543e9de9247446076320499c108b52307d8d0fafbe53b5c4e32acc4 redeeming
969
+ # output from
970
+ # 5342c96b946ea2c5e497de5dbf7762021f94aba2c8222c17ed28492fdbb4a6d9
971
+ script = Bitcoin::Script.from_string(
972
+ '16cfb9bc7654ef1d7723e5c2722fc0c3d505045e OP_SIZE OP_DUP 1 ' \
973
+ 'OP_GREATERTHAN OP_VERIFY OP_NEGATE OP_HASH256 OP_HASH160 OP_SHA256 ' \
974
+ 'OP_SHA1 OP_RIPEMD160 OP_EQUAL'
975
+ )
976
+ expect(script.run).to be true
977
+
978
+ # mainnet tx:
979
+ # 340aa9f72206d600b7e89c9137e4d2d77a920723f83e34707ff452121fd48492 redeeming
980
+ # output from
981
+ # f2d72a7bf22e29e3f2dc721afbf0a922860f81db9fc7eb397937f9d7e87cc438
982
+ script = Bitcoin::Script.from_string(
983
+ '027ce87f6f41dd4d7d874b40889f7df6b288f77f OP_DEPTH OP_HASH256 ' \
984
+ 'OP_HASH160 OP_SHA256 OP_SHA1 OP_RIPEMD160 OP_EQUAL'
985
+ )
986
+ expect(script.run).to be true
987
+ end
988
+
989
+ it 'should run op_checkmultisig p2sh script with empty signature' do
990
+ # mainnet tx:
991
+ # b78706427923f73b334fd68040f35900503da33c671723c41ca845f6fba6c29c
992
+ tx1 = Bitcoin::Protocol::Tx.new(
993
+ '01000000023904cd3644c6d440a6d752c95f07737c46f5e70fb6fbb28f00aa17e28186' \
994
+ '8b7b010000006b483045022100ac455750dc430957942e9766f88aecfe6eb17d4244eb' \
995
+ '2cb50ca4a25336fd4dd702202640cc943f4fe8f2166b03005bed3bd024f4762767322b' \
996
+ '60bf471ecf8e3f3ede012102348d4cad0084f88c4c02bdc1bf90cc6c0893a0b97af76e' \
997
+ 'f644daf72e6786b4afffffffffb84057ae61ad22ac17c02635ee1b37d170ef785847ec' \
998
+ '28efe848a5607331568e020000006b483045022100d7fee595d7a1f9969767098f8582' \
999
+ 'e7a563f08437f461f0a25395f35c1833839302205f565ab12d343478471a78669c4c34' \
1000
+ '76714032f7758a781d7deab19f160784e0012102ea69c47753d8e0228c0c426294a6b4' \
1001
+ 'dc926aebbeb8561248d40be37d257d94e0ffffffff01a08601000000000017a9143843' \
1002
+ '0c4d1c214bf11d2c0c3dea8e5e9a5d11aab08700000000'.htb
1003
+ )
1004
+ # mainnet tx:
1005
+ # 136becd0892fa38c5aca8104db8b90b3a0e6b40912b7d1462aed583c067054cd
1006
+ tx2 = Bitcoin::Protocol::Tx.new(
1007
+ '01000000019cc2a6fbf645a81cc42317673ca33d500059f34080d64f333bf723794206' \
1008
+ '87b70000000008000051005102ae91ffffffff0150c300000000000002ae9100000000'.htb
1009
+ )
1010
+ expect(tx2.verify_input_signature(0, tx1)).to be true
1011
+ end
1012
+
1013
+ it 'should debug script branches (OP_IF/NOTIF/ELSE/ENDIF) correctly' do
1014
+ script = Bitcoin::Script.from_string('1 OP_NOTIF OP_RETURN OP_ENDIF')
1015
+ script.run {}
1016
+ expected = [
1017
+ [], 'OP_1',
1018
+ [1], 'OP_NOTIF',
1019
+ [], 'OP_ENDIF',
1020
+ [], 'RESULT'
1021
+ ]
1022
+ expect(script.debug).to eq(expected)
1023
+
1024
+ script = Bitcoin::Script.from_string('1 OP_IF OP_RETURN OP_ENDIF')
1025
+ script.run {}
1026
+ expected = [
1027
+ [], 'OP_1',
1028
+ [1], 'OP_IF',
1029
+ [], 'OP_RETURN',
1030
+ [], 'INVALID TRANSACTION', 'RESULT'
1031
+ ]
1032
+ expect(script.debug).to eq(expected)
1033
+
1034
+ script = Bitcoin::Script.from_string(
1035
+ '1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL'
1036
+ )
1037
+ script.run {}
1038
+ expected = [
1039
+ [], 'OP_1',
1040
+ [1], 'OP_IF',
1041
+ [], 'OP_2',
1042
+ [2], 'OP_ELSE',
1043
+ [2], 'OP_ENDIF',
1044
+ [2], 'OP_2',
1045
+ [2, 2], 'OP_EQUAL',
1046
+ [1], 'RESULT'
1047
+ ]
1048
+ expect(script.debug).to eq(expected)
1049
+
1050
+ script = Bitcoin::Script.from_string(
1051
+ '0 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL'
1052
+ )
1053
+ script.run {}
1054
+ expected = [
1055
+ [], 'OP_0',
1056
+ [['']], 'OP_IF',
1057
+ [], 'OP_ELSE',
1058
+ [], 'OP_3',
1059
+ [3], 'OP_ENDIF',
1060
+ [3], 'OP_2',
1061
+ [3, 2], 'OP_EQUAL',
1062
+ [0], 'RESULT'
1063
+ ]
1064
+ expect(script.debug).to eq(expected)
1065
+
1066
+ script = Bitcoin::Script.from_string(
1067
+ '0 OP_IF deadbeef OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL'
1068
+ )
1069
+ script.run {}
1070
+ expected = [
1071
+ [], 'OP_0',
1072
+ [['']], 'OP_IF',
1073
+ [], 'OP_ELSE',
1074
+ [], 'OP_3',
1075
+ [3], 'OP_ENDIF',
1076
+ [3], 'OP_2',
1077
+ [3, 2], 'OP_EQUAL',
1078
+ [0], 'RESULT'
1079
+ ]
1080
+ expect(script.debug).to eq(expected)
1081
+
1082
+ script = Bitcoin::Script.from_string(
1083
+ '1 OP_IF 2 OP_ELSE 3 OP_ENDIF 2 OP_EQUAL'
1084
+ )
1085
+ script.run {}
1086
+ expected = [
1087
+ [], 'OP_1',
1088
+ [1], 'OP_IF',
1089
+ [], 'OP_2',
1090
+ [2], 'OP_ELSE',
1091
+ [2], 'OP_ENDIF',
1092
+ [2], 'OP_2',
1093
+ [2, 2], 'OP_EQUAL',
1094
+ [1], 'RESULT'
1095
+ ]
1096
+ expect(script.debug).to eq(expected)
1097
+
1098
+ script = Bitcoin::Script.from_string(
1099
+ '0 ' \
1100
+ '3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6' \
1101
+ 'c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f7' \
1102
+ '4501 ' \
1103
+ '304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b2' \
1104
+ '8a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72f' \
1105
+ 'c301 ' \
1106
+ '1 ' \
1107
+ '635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfb' \
1108
+ 'fc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd' \
1109
+ '52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d57' \
1110
+ '8853 ' \
1111
+ 'OP_IF ' \
1112
+ '2 ' \
1113
+ '022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc ' \
1114
+ '02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd ' \
1115
+ '2 ' \
1116
+ 'OP_CHECKMULTISIG ' \
1117
+ 'OP_ELSE ' \
1118
+ '2 ' \
1119
+ '025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d57885348 ' \
1120
+ '02b18808b3e6857e396167890a52f898cbd5215354f027b89fed895058e49a158b ' \
1121
+ '2 ' \
1122
+ 'OP_CHECKMULTISIG ' \
1123
+ 'OP_ENDIF'
1124
+ )
1125
+ script.run {}
1126
+ expected = [
1127
+ [], 'OP_0',
1128
+ [['']], 'PUSH DATA 3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542' \
1129
+ 'cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef' \
1130
+ '388ad211505cd32e2ad3adebe5f74501',
1131
+ [[''], ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bca' \
1132
+ 'c18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad21150' \
1133
+ '5cd32e2ad3adebe5f74501']],
1134
+ 'PUSH DATA 304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205' \
1135
+ 'b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4' \
1136
+ '948b3eb0e72fc301',
1137
+ [[''],
1138
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1139
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1140
+ 'ebe5f74501'],
1141
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1142
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1143
+ 'b0e72fc301']],
1144
+ 'OP_1',
1145
+ [[''],
1146
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1147
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1148
+ 'ebe5f74501'],
1149
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1150
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1151
+ 'b0e72fc301'],
1152
+ 1],
1153
+ 'PUSH DATA 635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3' \
1154
+ 'b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c' \
1155
+ '79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d8' \
1156
+ '75c35873d3d578853',
1157
+ [[''],
1158
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1159
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1160
+ 'ebe5f74501'],
1161
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1162
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1163
+ 'b0e72fc301'],
1164
+ 1,
1165
+ ['635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964' \
1166
+ 'bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1ab' \
1167
+ 'dea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c3' \
1168
+ '5873d3d578853']],
1169
+ 'OP_IF',
1170
+ [[''],
1171
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1172
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1173
+ 'ebe5f74501'],
1174
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1175
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1176
+ 'b0e72fc301'],
1177
+ 1],
1178
+ 'OP_2',
1179
+ [[''],
1180
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1181
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1182
+ 'ebe5f74501'],
1183
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1184
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1185
+ 'b0e72fc301'],
1186
+ 1,
1187
+ 2],
1188
+ 'PUSH DATA 022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc',
1189
+ [[''],
1190
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1191
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1192
+ 'ebe5f74501'],
1193
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1194
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1195
+ 'b0e72fc301'],
1196
+ 1,
1197
+ 2,
1198
+ ['022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc']],
1199
+ 'PUSH DATA 02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd',
1200
+ [[''],
1201
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1202
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1203
+ 'ebe5f74501'],
1204
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1205
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1206
+ 'b0e72fc301'],
1207
+ 1,
1208
+ 2,
1209
+ ['022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc'],
1210
+ ['02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd']],
1211
+ 'OP_2',
1212
+ [[''],
1213
+ ['3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed6' \
1214
+ '9f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3ad' \
1215
+ 'ebe5f74501'],
1216
+ ['304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f' \
1217
+ '3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3e' \
1218
+ 'b0e72fc301'],
1219
+ 1,
1220
+ 2,
1221
+ ['022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc'],
1222
+ ['02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd'],
1223
+ 2],
1224
+ 'OP_CHECKMULTISIG',
1225
+ [[''], 0], 'OP_ELSE',
1226
+ [[''], 0], 'OP_ENDIF',
1227
+ [[''], 0], 'RESULT'
1228
+ ]
1229
+ expect(script.debug).to eq(expected)
1230
+ end
1231
+
1232
+ it 'should not execute p2sh recursively' do
1233
+ # this script_sig includes a pattern that matches the p2sh template
1234
+ script_sig = '0 a914b472a266d0bd89c13706a4132ccfb16f7c3b9fcb87'
1235
+ pk_script = 'OP_HASH160 92a04bc86e23f169691bd6926d11853cc61e1852 OP_EQUAL'
1236
+ script = Bitcoin::Script.from_string(script_sig + ' ' + pk_script)
1237
+ expect(script.run).to be true
1238
+ end
1239
+
1240
+ it '#sort_p2sh_multisig_signatures 3-of-3' do
1241
+ keys = Array.new(3) { Bitcoin::Key.generate }
1242
+
1243
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(3, *keys)
1244
+ sigs = keys.map { |k| k.sign(sig_hash) }
1245
+
1246
+ # add sigs in all possible orders, sort them, and see if they are valid
1247
+ [0, 1, 2].permutation do |order|
1248
+ script_sig = Bitcoin::Script.to_p2sh_multisig_script_sig(redeem_script)
1249
+ order.each do |i|
1250
+ script_sig = Bitcoin::Script.add_sig_to_multisig_script_sig(
1251
+ sigs[i], script_sig
1252
+ )
1253
+ end
1254
+ script_sig = Bitcoin::Script.sort_p2sh_multisig_signatures(
1255
+ script_sig, sig_hash
1256
+ )
1257
+ tx.in[0].script_sig = script_sig
1258
+ expect(tx.verify_input_signature(0, prev_tx)).to be true
1259
+ end
1260
+ end
1261
+
1262
+ it '#sort_p2sh_multisig_signatures 2-of-3' do
1263
+ keys = Array.new(3) { Bitcoin::Key.generate }
1264
+
1265
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(2, *keys)
1266
+ sigs = keys.map { |k| k.sign(sig_hash) }
1267
+
1268
+ # add sigs in all possible orders, sort them, and see if they are valid
1269
+ [0, 1, 2].permutation(2) do |order|
1270
+ script_sig = Bitcoin::Script.to_p2sh_multisig_script_sig(redeem_script)
1271
+ order.each do |i|
1272
+ script_sig = Bitcoin::Script.add_sig_to_multisig_script_sig(
1273
+ sigs[i], script_sig
1274
+ )
1275
+ end
1276
+ script_sig = Bitcoin::Script.sort_p2sh_multisig_signatures(
1277
+ script_sig, sig_hash
1278
+ )
1279
+ tx.in[0].script_sig = script_sig
1280
+ expect(tx.verify_input_signature(0, prev_tx)).to be true
1281
+ end
1282
+ end
1283
+
1284
+ describe 'Implements BIP62' do
1285
+ it 'tests for incorrectly encoded S-values in signatures' do
1286
+ # TX 3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae
1287
+ sig_orig = [
1288
+ '304502210088984573e3e4f33db7df6aea313f1ce67a3ef3532ea89991494c7f0182' \
1289
+ '58371802206ceefc9291450dbd40d834f249658e0f64662d52a41cf14e20c9781144' \
1290
+ 'f2fe0701'
1291
+ ].pack('H*')
1292
+
1293
+ expect(Bitcoin::Script.is_low_der_signature?(sig_orig)).to be true
1294
+
1295
+ # Set the start of the S-value to 0xff so it's well above the order of the
1296
+ # curve divided by two
1297
+ sig = sig_orig.unpack('C*')
1298
+ length_r = sig[3]
1299
+ sig[6 + length_r] = 0xff
1300
+
1301
+ expect(Bitcoin::Script.is_low_der_signature?(sig.pack('C*'))).to be false
1302
+ end
1303
+
1304
+ it 'enforces rules 3 and 4' do
1305
+ expect(
1306
+ Bitcoin::Script.new([75].pack('C') + 'A' * 75).pushes_are_canonical?
1307
+ ).to be true
1308
+ expect(
1309
+ Bitcoin::Script.new(
1310
+ [Bitcoin::Script::OP_PUSHDATA1, 75].pack('CC') + 'A' * 75
1311
+ ).pushes_are_canonical?
1312
+ ).to be false
1313
+ expect(
1314
+ Bitcoin::Script.new(
1315
+ [Bitcoin::Script::OP_PUSHDATA2, 255].pack('Cv') + 'A' * 255
1316
+ ).pushes_are_canonical?
1317
+ ).to be false
1318
+ expect(
1319
+ Bitcoin::Script.new(
1320
+ [Bitcoin::Script::OP_PUSHDATA4, 1645].pack('CV') + 'A' * 1645
1321
+ ).pushes_are_canonical?
1322
+ ).to be false
1323
+ end
1324
+ end
1325
+
1326
+ describe 'Implements BIP66' do
1327
+ # see: https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki#examples
1328
+ # see also: https://github.com/bitcoin/bitcoin/pull/5713/files
1329
+ let(:p1) do
1330
+ '038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508'
1331
+ end
1332
+ let(:p2) do
1333
+ '03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640'
1334
+ end
1335
+
1336
+ def build_crediting_tx(script_pk)
1337
+ tx = Bitcoin::Protocol::Tx.new
1338
+ input = Bitcoin::Protocol::TxIn.new(
1339
+ nil, 0xffffffff, 2, "\x00\x00"
1340
+ )
1341
+ output = Bitcoin::Protocol::TxOut.new(0, script_pk)
1342
+ tx.add_in(input)
1343
+ tx.add_out(output)
1344
+ Bitcoin::Protocol::Tx.new(tx.to_payload)
1345
+ end
1346
+
1347
+ def build_spending_tx(script_sig, tx_credit)
1348
+ tx = Bitcoin::Protocol::Tx.new
1349
+ input = Bitcoin::Protocol::TxIn.new(
1350
+ tx_credit.binary_hash, 0, 2, script_sig
1351
+ )
1352
+ output = Bitcoin::Protocol::TxOut.new(0, '')
1353
+ tx.add_in(input)
1354
+ tx.add_out(output)
1355
+ Bitcoin::Protocol::Tx.new(tx.to_payload)
1356
+ end
1357
+
1358
+ # essentially DoTest() from script_tests.cpp
1359
+ def run_script_test(script_sig_str, script_pk_str, opts = {})
1360
+ script_sig = Bitcoin::Script.from_string(script_sig_str)
1361
+ script_pk = Bitcoin::Script.from_string(script_pk_str)
1362
+ tx_credit = build_crediting_tx(script_pk.raw)
1363
+ tx = build_spending_tx(script_sig.raw, tx_credit)
1364
+ tx.verify_input_signature(0, tx_credit, Time.now.to_i, opts)
1365
+ end
1366
+
1367
+ it 'overly long signature fails with DERSIG passes without' do
1368
+ script_sig =
1369
+ '0000000000000000000000000000000000000000000000000000000000000000000' \
1370
+ '0000000000000000000000000000000000000000000000000000000000000000000' \
1371
+ '00000000000000'
1372
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1373
+ expect(
1374
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1375
+ ).to be false
1376
+ expect(run_script_test(script_sig, script_pk)).to be true
1377
+ end
1378
+
1379
+ it 'missing S fails with DERSIG passes without' do
1380
+ script_sig =
1381
+ '3022022000000000000000000000000000000000000000000000000000000000000000000'
1382
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1383
+ expect(
1384
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1385
+ ).to be false
1386
+ expect(run_script_test(script_sig, script_pk)).to be true
1387
+ end
1388
+
1389
+ it 'S with invalid fails with DERSIG passes without' do
1390
+ script_sig =
1391
+ '3024021077777777777777777777777777777777020a7777777777777777777777777777777701'
1392
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1393
+ expect(
1394
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1395
+ ).to be false
1396
+ expect(run_script_test(script_sig, script_pk)).to be true
1397
+ end
1398
+
1399
+ it 'non-integer R fails with DERSIG passes without' do
1400
+ script_sig =
1401
+ '302403107777777777777777777777777777777702107777777777777777777777777777777701'
1402
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1403
+ expect(
1404
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1405
+ ).to be false
1406
+ expect(run_script_test(script_sig, script_pk)).to be true
1407
+ end
1408
+
1409
+ it 'non-integer S fails with DERSIG passes without' do
1410
+ script_sig =
1411
+ '302402107777777777777777777777777777777703107777777777777777777777777777777701'
1412
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1413
+ expect(
1414
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1415
+ ).to be false
1416
+ expect(run_script_test(script_sig, script_pk)).to be true
1417
+ end
1418
+
1419
+ it 'zero length R fails with DERSIG passes without' do
1420
+ script_sig = '3014020002107777777777777777777777777777777701'
1421
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1422
+ expect(
1423
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1424
+ ).to be false
1425
+ expect(run_script_test(script_sig, script_pk)).to be true
1426
+ end
1427
+
1428
+ it 'zero length S fails with DERSIG passes without' do
1429
+ script_sig = '3014021077777777777777777777777777777777020001'
1430
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1431
+ expect(
1432
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1433
+ ).to be false
1434
+ expect(run_script_test(script_sig, script_pk)).to be true
1435
+ end
1436
+
1437
+ it 'negative S fails with DERSIG passes without' do
1438
+ script_sig =
1439
+ '30240210777777777777777777777777777777770210877777777777777777777777' \
1440
+ '7777777701'
1441
+ script_pk = '0 OP_CHECKSIG OP_NOT'
1442
+ expect(
1443
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1444
+ ).to be false
1445
+ expect(run_script_test(script_sig, script_pk)).to be true
1446
+ end
1447
+
1448
+ # Example 1: S1' p1 CHECKSIG (fails w/ verify_dersig, passes w/o)
1449
+ it 'example 1' do
1450
+ script_sig =
1451
+ '30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21dd' \
1452
+ 'd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f' \
1453
+ '94d1a201'
1454
+ script_pk = "#{p1} OP_CHECKSIG"
1455
+ expect(run_script_test(script_sig, script_pk)).to be true
1456
+ expect(
1457
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1458
+ ).to be false
1459
+ end
1460
+
1461
+ # Example 2: S1' P1 CHECKSIG NOT (fails with either)
1462
+ it 'example 2' do
1463
+ script_sig =
1464
+ '304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f282246' \
1465
+ '2d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace042' \
1466
+ '4fc0be01'
1467
+ script_pk = "#{p1} OP_CHECKSIG OP_NOT"
1468
+ expect(run_script_test(script_sig, script_pk)).to be false
1469
+ expect(
1470
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1471
+ ).to be false
1472
+ end
1473
+
1474
+ # Example 3: F P1 CHECKSIG fails (fails with either)
1475
+ it 'example 3' do
1476
+ script_sig = '0'
1477
+ script_pk = "#{p1} OP_CHECKSIG"
1478
+ expect(run_script_test(script_sig, script_pk)).to be false
1479
+ expect(
1480
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1481
+ ).to be false
1482
+ end
1483
+
1484
+ # Example 4: F P1 CHECKSIG NOT (passes with either)
1485
+ it 'example 4' do
1486
+ script_sig = '0'
1487
+ script_pk = "#{p1} OP_CHECKSIG OP_NOT"
1488
+ expect(run_script_test(script_sig, script_pk)).to be true
1489
+ expect(
1490
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1491
+ ).to be true
1492
+ end
1493
+
1494
+ # Example 5: F' P1 CHECKSIG (fails with either)
1495
+ it 'example 5' do
1496
+ script_sig = '1'
1497
+ script_pk = "#{p1} OP_CHECKSIG"
1498
+ expect(run_script_test(script_sig, script_pk)).to be false
1499
+ expect(
1500
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1501
+ ).to be false
1502
+ end
1503
+
1504
+ # Example 6: F' P1 CHECKSIG NOT (fails w/verify_dersig, passes w/o)
1505
+ it 'example 6' do
1506
+ script_sig = '1'
1507
+ script_pk = "#{p1} OP_CHECKSIG OP_NOT"
1508
+ expect(run_script_test(script_sig, script_pk)).to be true
1509
+ expect(
1510
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1511
+ ).to be false
1512
+ end
1513
+
1514
+ # Example 7: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG (fails w/verify_dersig, passes w/o)
1515
+ it 'example 7' do
1516
+ s1 =
1517
+ '30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db' \
1518
+ '810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea' \
1519
+ '39d501'
1520
+ s2 =
1521
+ '304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68' \
1522
+ 'c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e' \
1523
+ '274c01'
1524
+ script_sig = "0 #{s1} #{s2}"
1525
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG"
1526
+ expect(run_script_test(script_sig, script_pk)).to be true
1527
+ expect(
1528
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1529
+ ).to be false
1530
+ end
1531
+
1532
+ # Example 8: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG NOT (fails for either)
1533
+ it 'example 8' do
1534
+ s1 =
1535
+ '30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46' \
1536
+ '991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737d' \
1537
+ 'b22601'
1538
+ s2 =
1539
+ '3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec3' \
1540
+ '39a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d6' \
1541
+ '3c4801'
1542
+ script_sig = "0 #{s1} #{s2}"
1543
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG OP_NOT"
1544
+ expect(run_script_test(script_sig, script_pk)).to be false
1545
+ expect(
1546
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1547
+ ).to be false
1548
+ end
1549
+
1550
+ # Example 9: 0 F S2' 2 P1 P2 2 CHECKMULTISIG fails (fails for either)
1551
+ it 'example 9' do
1552
+ s1 = '0'
1553
+ s2 =
1554
+ '3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd8' \
1555
+ '83490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b67' \
1556
+ '6b2e01'
1557
+ script_sig = "0 #{s1} #{s2}"
1558
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG"
1559
+ expect(run_script_test(script_sig, script_pk)).to be false
1560
+ expect(
1561
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1562
+ ).to be false
1563
+ end
1564
+
1565
+ # Example 10: 0 F S2' 2 P1 P2 2 CHECKMULTISIG NOT (fails w/verify_dersig, passes w/o)
1566
+ it 'example 10' do
1567
+ s1 = '0'
1568
+ s2 =
1569
+ '30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c' \
1570
+ '05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c378' \
1571
+ '3bf501'
1572
+ script_sig = "0 #{s1} #{s2}"
1573
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG OP_NOT"
1574
+ expect(run_script_test(script_sig, script_pk)).to be true
1575
+ expect(
1576
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1577
+ ).to be false
1578
+ end
1579
+
1580
+ # Example 11: 0 S1' F 2 P1 P2 2 CHECKMULTISIG (fails for either)
1581
+ it 'example 11' do
1582
+ s1 =
1583
+ '30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db' \
1584
+ '810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea' \
1585
+ '39d501'
1586
+ s2 = '0'
1587
+ script_sig = "0 #{s1} #{s2}"
1588
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG"
1589
+ expect(run_script_test(script_sig, script_pk)).to be false
1590
+ expect(
1591
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1592
+ ).to be false
1593
+ end
1594
+
1595
+ # Example 12: 0 S1' F 2 P1 P2 2 CHECKMULTISIG NOT (passes for either)
1596
+ it 'example 12' do
1597
+ s1 =
1598
+ '30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46' \
1599
+ '991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737d' \
1600
+ 'b22601'
1601
+ s2 = '0'
1602
+ script_sig = "0 #{s1} #{s2}"
1603
+ script_pk = "2 #{p1} #{p2} 2 OP_CHECKMULTISIG OP_NOT"
1604
+ expect(run_script_test(script_sig, script_pk)).to be true
1605
+ expect(
1606
+ run_script_test(script_sig, script_pk, verify_dersig: true)
1607
+ ).to be true
1608
+ end
1609
+ end
1610
+ end