monacoin-ruby 0.1.2

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 (195) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +5 -0
  4. data/COPYING +18 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +33 -0
  7. data/README.rdoc +210 -0
  8. data/Rakefile +112 -0
  9. data/bin/monacoin_shell +12 -0
  10. data/bitcoin-ruby.gemspec +23 -0
  11. data/examples/bbe_verify_tx.rb +60 -0
  12. data/examples/concept-blockchain-pow.rb +151 -0
  13. data/examples/connect.rb +36 -0
  14. data/examples/generate_tx.rb +34 -0
  15. data/examples/simple_network_monitor_and_util.rb +195 -0
  16. data/spec/bitcoin/bitcoin_spec.rb +598 -0
  17. data/spec/bitcoin/bloom_filter_spec.rb +23 -0
  18. data/spec/bitcoin/builder_spec.rb +342 -0
  19. data/spec/bitcoin/contracthash_spec.rb +45 -0
  20. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  21. data/spec/bitcoin/ext_key_spec.rb +180 -0
  22. data/spec/bitcoin/ffi_openssl.rb +45 -0
  23. data/spec/bitcoin/fixtures/000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json +3697 -0
  24. data/spec/bitcoin/fixtures/03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99.json +23 -0
  25. data/spec/bitcoin/fixtures/0961c660358478829505e16a1f028757e54b5bbf9758341a7546573738f31429.json +24 -0
  26. data/spec/bitcoin/fixtures/0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae.json +37 -0
  27. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  28. data/spec/bitcoin/fixtures/23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63.json +23 -0
  29. data/spec/bitcoin/fixtures/315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json +31 -0
  30. data/spec/bitcoin/fixtures/35e2001b428891fefa0bfb73167c7360669d3cbd7b3aa78e7cad125ddfc51131.json +27 -0
  31. data/spec/bitcoin/fixtures/3a17dace09ffb919ed627a93f1873220f4c975c1248558b18d16bce25d38c4b7.json +72 -0
  32. data/spec/bitcoin/fixtures/3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json +27 -0
  33. data/spec/bitcoin/fixtures/514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58.json +24 -0
  34. data/spec/bitcoin/fixtures/51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e.json +30 -0
  35. data/spec/bitcoin/fixtures/60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1.json +45 -0
  36. data/spec/bitcoin/fixtures/69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json +28 -0
  37. data/spec/bitcoin/fixtures/7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json +27 -0
  38. data/spec/bitcoin/fixtures/761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6.json +27 -0
  39. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  40. data/spec/bitcoin/fixtures/aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4.json +27 -0
  41. data/spec/bitcoin/fixtures/bc179baab547b7d7c1d5d8d6f8b0cc6318eaa4b0dd0a093ad6ac7f5a1cb6b3ba.json +34 -0
  42. data/spec/bitcoin/fixtures/bd1715f1abfdc62bea3f605bdb461b3ba1f2cca6ec0d73a18a548b7717ca8531.json +34 -0
  43. data/spec/bitcoin/fixtures/block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin +0 -0
  44. data/spec/bitcoin/fixtures/cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2.json +24 -0
  45. data/spec/bitcoin/fixtures/ce5fad9b4ef094d8f4937b0707edaf0a6e6ceeaf67d5edbfd51f660eac8f398b.json +41 -0
  46. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  47. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  48. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  49. data/spec/bitcoin/fixtures/f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b.json +23 -0
  50. data/spec/bitcoin/fixtures/filteredblock-0.bin +0 -0
  51. data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.bin +0 -0
  52. data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.json +39 -0
  53. data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.bin +0 -0
  54. data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.json +39 -0
  55. data/spec/bitcoin/fixtures/litecoin-tx-f5aa30f574e3b6f1a3d99c07a6356ba812aabb9661e1d5f71edff828cbd5c996.json +259 -0
  56. data/spec/bitcoin/fixtures/rawblock-0.bin +0 -0
  57. data/spec/bitcoin/fixtures/rawblock-0.json +39 -0
  58. data/spec/bitcoin/fixtures/rawblock-1.bin +0 -0
  59. data/spec/bitcoin/fixtures/rawblock-1.json +39 -0
  60. data/spec/bitcoin/fixtures/rawblock-131025.bin +0 -0
  61. data/spec/bitcoin/fixtures/rawblock-131025.json +5063 -0
  62. data/spec/bitcoin/fixtures/rawblock-170.bin +0 -0
  63. data/spec/bitcoin/fixtures/rawblock-170.json +68 -0
  64. data/spec/bitcoin/fixtures/rawblock-9.bin +0 -0
  65. data/spec/bitcoin/fixtures/rawblock-9.json +39 -0
  66. data/spec/bitcoin/fixtures/rawblock-auxpow.bin +0 -0
  67. data/spec/bitcoin/fixtures/rawblock-testnet-1151351.bin +0 -0
  68. data/spec/bitcoin/fixtures/rawblock-testnet-26478.bin +0 -0
  69. data/spec/bitcoin/fixtures/rawblock-testnet-26478.json +64 -0
  70. data/spec/bitcoin/fixtures/rawblock-testnet-265322.bin +0 -0
  71. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  72. data/spec/bitcoin/fixtures/rawtx-01.bin +0 -0
  73. data/spec/bitcoin/fixtures/rawtx-01.json +27 -0
  74. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  75. data/spec/bitcoin/fixtures/rawtx-02.bin +0 -0
  76. data/spec/bitcoin/fixtures/rawtx-02.json +27 -0
  77. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  78. data/spec/bitcoin/fixtures/rawtx-03.bin +0 -0
  79. data/spec/bitcoin/fixtures/rawtx-03.json +48 -0
  80. data/spec/bitcoin/fixtures/rawtx-04.json +27 -0
  81. data/spec/bitcoin/fixtures/rawtx-0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9.bin +0 -0
  82. data/spec/bitcoin/fixtures/rawtx-05.json +23 -0
  83. data/spec/bitcoin/fixtures/rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin +0 -0
  84. data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin +0 -0
  85. data/spec/bitcoin/fixtures/rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.json +27 -0
  86. data/spec/bitcoin/fixtures/rawtx-406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602.json +23 -0
  87. data/spec/bitcoin/fixtures/rawtx-52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2.bin +0 -0
  88. data/spec/bitcoin/fixtures/rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin +0 -0
  89. data/spec/bitcoin/fixtures/rawtx-ba1ff5cd66713133c062a871a8adab92416f1e38d17786b2bf56ac5f6ffdfdf5.json +37 -0
  90. data/spec/bitcoin/fixtures/rawtx-c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73.json +24 -0
  91. data/spec/bitcoin/fixtures/rawtx-de35d060663750b3975b7997bde7fb76307cec5b270d12fcd9c4ad98b279c28c.json +23 -0
  92. data/spec/bitcoin/fixtures/rawtx-f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.bin +0 -0
  93. data/spec/bitcoin/fixtures/rawtx-p2wpkh.bin +0 -0
  94. data/spec/bitcoin/fixtures/rawtx-p2wpkh.json +67 -0
  95. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  96. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  97. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  98. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  99. data/spec/bitcoin/fixtures/rawtx-testnet-a220adf1902c46a39db25a24bc4178b6a88440f977a7e2cabfdd8b5c1dd35cfb.json +27 -0
  100. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  101. data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.bin +0 -0
  102. data/spec/bitcoin/fixtures/rawtx-testnet-e232e0055dbdca88bbaa79458683195a0b7c17c5b6c524a8d146721d4d4d652f.json +41 -0
  103. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  104. data/spec/bitcoin/fixtures/reorg/blk_0_to_4.dat +0 -0
  105. data/spec/bitcoin/fixtures/reorg/blk_3A.dat +0 -0
  106. data/spec/bitcoin/fixtures/reorg/blk_4A.dat +0 -0
  107. data/spec/bitcoin/fixtures/reorg/blk_5A.dat +0 -0
  108. data/spec/bitcoin/fixtures/script_tests.json +1947 -0
  109. data/spec/bitcoin/fixtures/sighash.json +1004 -0
  110. data/spec/bitcoin/fixtures/testnet/block_0.bin +0 -0
  111. data/spec/bitcoin/fixtures/testnet/block_1.bin +0 -0
  112. data/spec/bitcoin/fixtures/testnet/block_2.bin +0 -0
  113. data/spec/bitcoin/fixtures/testnet/block_3.bin +0 -0
  114. data/spec/bitcoin/fixtures/testnet/block_4.bin +0 -0
  115. data/spec/bitcoin/fixtures/testnet/block_5.bin +0 -0
  116. data/spec/bitcoin/fixtures/tx-0295028ef826b2a188409cb905b631faebb9bb3cdf14510571c5f4bd8591338f.json +64 -0
  117. data/spec/bitcoin/fixtures/tx-03339a725007a279484fb6f5361f522dd1cf4d0923d30e6b973290dba4275f92.json +64 -0
  118. data/spec/bitcoin/fixtures/tx-0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3.json +139 -0
  119. data/spec/bitcoin/fixtures/tx-0ce7e5238fbdb6c086cf1b384b21b827e91cc23f360417265874a5a0d86ce367.json +64 -0
  120. data/spec/bitcoin/fixtures/tx-0ef34c49f630aea17df0080728b0fc67bf5f87fbda936934a4b11b4a69d7821e.json +64 -0
  121. data/spec/bitcoin/fixtures/tx-1129d2a8bd5bb3a81e54dc96a90f1f6b2544575748caa17243470935c5dd91b7.json +28 -0
  122. data/spec/bitcoin/fixtures/tx-19aa42fee0fa57c45d3b16488198b27caaacc4ff5794510d0c17f173f05587ff.json +23 -0
  123. data/spec/bitcoin/fixtures/tx-1a4f3b9dc4494aeedeb39f30dd37e60541b2abe3ed4977992017cc0ad4f44956.json +64 -0
  124. data/spec/bitcoin/fixtures/tx-1f9191dcf2b1844ca28c6ef4b969e1d5fab70a5e3c56b7007949e55851cb0c4f.json +64 -0
  125. data/spec/bitcoin/fixtures/tx-22cd5fef23684d7b304e119bedffde6f54538d3d54a5bfa237e20dc2d9b4b5ad.json +64 -0
  126. data/spec/bitcoin/fixtures/tx-28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f.json +34 -0
  127. data/spec/bitcoin/fixtures/tx-2958fb00b4fd6fe0353503b886eb9a193d502f4fd5fc042d5e03216ba918bbd6.json +64 -0
  128. data/spec/bitcoin/fixtures/tx-29f277145749ad6efbed3ae6ce301f8d33c585ec26b7c044ad93c2f866e9e942.json +64 -0
  129. data/spec/bitcoin/fixtures/tx-2c5e5376c20e9cc78d0fb771730e5d840cc2096eff0ef045b599fe92475ace1c.json +28 -0
  130. data/spec/bitcoin/fixtures/tx-2c63aa814701cef5dbd4bbaddab3fea9117028f2434dddcdab8339141e9b14d1.json +30 -0
  131. data/spec/bitcoin/fixtures/tx-313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0.json +30 -0
  132. data/spec/bitcoin/fixtures/tx-326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e.json +23 -0
  133. data/spec/bitcoin/fixtures/tx-345bed8785c3282a264ffb0dbee61cde54854f10e16f1b3e75b7f2d9f62946f2.json +64 -0
  134. data/spec/bitcoin/fixtures/tx-39ba7440b7103557560cc8ce258009936796485aaf8b478e66ab4cb97c66e31b.json +32 -0
  135. data/spec/bitcoin/fixtures/tx-3a04d57a833367f1655cc5ec3beb587888ef4977a86caa8c8ad4ba7cc717eae7.json +64 -0
  136. data/spec/bitcoin/fixtures/tx-3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae.json +23 -0
  137. data/spec/bitcoin/fixtures/tx-4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9.json +38 -0
  138. data/spec/bitcoin/fixtures/tx-44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a.json +30 -0
  139. data/spec/bitcoin/fixtures/tx-46224764c7870f95b58f155bce1e38d4da8e99d42dbb632d0dd7c07e092ee5aa.json +23 -0
  140. data/spec/bitcoin/fixtures/tx-5df1375ffe61ac35ca178ebb0cab9ea26dedbd0e96005dfcee7e379fa513232f.json +30 -0
  141. data/spec/bitcoin/fixtures/tx-62d9a565bd7b5344c5352e3e9e5f40fa4bbd467fa19c87357216ec8777ba1cce.json +64 -0
  142. data/spec/bitcoin/fixtures/tx-6327783a064d4e350c454ad5cd90201aedf65b1fc524e73709c52f0163739190.json +23 -0
  143. data/spec/bitcoin/fixtures/tx-6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba.json +27 -0
  144. data/spec/bitcoin/fixtures/tx-6aaf18b9f1283b939d8e5d40ff5f8a435229f4178372659cc3a0bce4e262bf78.json +28 -0
  145. data/spec/bitcoin/fixtures/tx-6b48bba6f6d2286d7ec0883c0fc3085955090813a4c94980466611c798b868cc.json +64 -0
  146. data/spec/bitcoin/fixtures/tx-70cfbc6690f9ab46712db44e3079ac227962b2771a9341d4233d898b521619ef.json +40 -0
  147. data/spec/bitcoin/fixtures/tx-7a1a9db42f065f75110fcdb1bc415549c8ef7670417ba1d35a67f1b8adc562c1.json +64 -0
  148. data/spec/bitcoin/fixtures/tx-9a768fc7d0c4bdc86e25154357ef7c0063ca21310e5740a2f12f90b7455184a7.json +64 -0
  149. data/spec/bitcoin/fixtures/tx-9cad8d523a0694f2509d092c39cebc8046adae62b4e4297102d568191d9478d8.json +64 -0
  150. data/spec/bitcoin/fixtures/tx-9e052eb694bd7e15906433f064dff0161a12fd325c1124537766377004023c6f.json +64 -0
  151. data/spec/bitcoin/fixtures/tx-9fb65b7304aaa77ac9580823c2c06b259cc42591e5cce66d76a81b6f51cc5c28.json +23 -0
  152. data/spec/bitcoin/fixtures/tx-a6ce7081addade7676cd2af75c4129eba6bf5e179a19c40c7d4cf6a5fe595954.json +30 -0
  153. data/spec/bitcoin/fixtures/tx-a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944.json +23 -0
  154. data/spec/bitcoin/fixtures/tx-aab7ef280abbb9cc6fbaf524d2645c3daf4fcca2b3f53370e618d9cedf65f1f8.json +23 -0
  155. data/spec/bitcoin/fixtures/tx-ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742.json +27 -0
  156. data/spec/bitcoin/fixtures/tx-ad4bcf3241e5d2ad140564e20db3567d41594cf4c2012433fe46a2b70e0d87b8.json +64 -0
  157. data/spec/bitcoin/fixtures/tx-b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9.json +27 -0
  158. data/spec/bitcoin/fixtures/tx-b8fd633e7713a43d5ac87266adc78444669b987a56b3a65fb92d58c2c4b0e84d.json +28 -0
  159. data/spec/bitcoin/fixtures/tx-bbca0628c42cb8bf7c3f4b2ad688fa56da5308dd2a10255da89fb1f46e6e413d.json +36 -0
  160. data/spec/bitcoin/fixtures/tx-bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224.json +23 -0
  161. data/spec/bitcoin/fixtures/tx-c192b74844e4837a34c4a5a97b438f1c111405b01b99e2d12b7c96d07fc74c04.json +28 -0
  162. data/spec/bitcoin/fixtures/tx-d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830.json +28 -0
  163. data/spec/bitcoin/fixtures/tx-e335562f7e297aadeed88e5954bc4eeb8dc00b31d829eedb232e39d672b0c009.json +406 -0
  164. data/spec/bitcoin/fixtures/tx-eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb.json +35 -0
  165. data/spec/bitcoin/fixtures/tx-fee1b9b85531c8fb6cd7831f83490c7f2aa768b6eefe29854ef5e89ce7b9ecb1.json +64 -0
  166. data/spec/bitcoin/fixtures/txdp-1.txt +32 -0
  167. data/spec/bitcoin/fixtures/txdp-2-signed.txt +19 -0
  168. data/spec/bitcoin/fixtures/txdp-2-unsigned.txt +14 -0
  169. data/spec/bitcoin/fixtures/txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin +1 -0
  170. data/spec/bitcoin/helpers/fake_blockchain.rb +183 -0
  171. data/spec/bitcoin/key_spec.rb +326 -0
  172. data/spec/bitcoin/network_spec.rb +50 -0
  173. data/spec/bitcoin/performance/storage_spec.rb +41 -0
  174. data/spec/bitcoin/protocol/addr_spec.rb +82 -0
  175. data/spec/bitcoin/protocol/alert_spec.rb +22 -0
  176. data/spec/bitcoin/protocol/aux_pow_spec.rb +45 -0
  177. data/spec/bitcoin/protocol/bip143_spec.rb +116 -0
  178. data/spec/bitcoin/protocol/block_spec.rb +208 -0
  179. data/spec/bitcoin/protocol/getblocks_spec.rb +32 -0
  180. data/spec/bitcoin/protocol/inv_spec.rb +134 -0
  181. data/spec/bitcoin/protocol/notfound_spec.rb +31 -0
  182. data/spec/bitcoin/protocol/parser_spec.rb +50 -0
  183. data/spec/bitcoin/protocol/partial_merkle_tree_spec.rb +38 -0
  184. data/spec/bitcoin/protocol/ping_spec.rb +51 -0
  185. data/spec/bitcoin/protocol/reject.rb +17 -0
  186. data/spec/bitcoin/protocol/tx_spec.rb +894 -0
  187. data/spec/bitcoin/protocol/txin_spec.rb +45 -0
  188. data/spec/bitcoin/protocol/txout_spec.rb +27 -0
  189. data/spec/bitcoin/protocol/version_spec.rb +110 -0
  190. data/spec/bitcoin/script/opcodes_spec.rb +773 -0
  191. data/spec/bitcoin/script/script_spec.rb +971 -0
  192. data/spec/bitcoin/secp256k1_spec.rb +78 -0
  193. data/spec/bitcoin/spec_helper.rb +108 -0
  194. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  195. metadata +237 -0
@@ -0,0 +1,971 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative '../spec_helper.rb'
4
+ require 'bitcoin/script'
5
+
6
+ include Bitcoin
7
+
8
+ describe 'Bitcoin::Script' do
9
+ SCRIPT = [
10
+ "410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac",
11
+ "47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901",
12
+ "76a91417977bca1b6287a5e6559c57ef4b6525e9d7ded688ac",
13
+ "524104573b6e9f3a714440048a7b87d606bcbf9e45b8586e70a67a3665ea720c095658471a523e5d923f3f3e015626e7c900bd08560ddffeb17d33c5b52c96edb875954104039c2f4e413a26901e67ad4adbb6a4759af87bc16c7120459ecc9482fed3dd4a4502947f7b4c7782dcadc2bed513ed14d5e770452b97ae246ac2030f13b80a5141048b0f9d04e495c3c754f8c3c109196d713d0778882ef098f785570ee6043f8c192d8f84df43ebafbcc168f5d95a074dc4010b62c003e560abc163c312966b74b653ae", # multisig 2 of 3
14
+ "5141040ee607b584b36e995f2e96dec35457dbb40845d0ce0782c84002134e816a6b8cbc65e9eed047ae05e10760e4113f690fd49ad73b86b04a1d7813d843f8690ace4104220a78f5f6741bb0739675c2cc200643516b02cfdfda5cba21edeaa62c0f954936b30dfd956e3e99af0a8e7665cff6ac5b429c54c418184c81fbcd4bde4088f552ae", # multisig 1 of 2
15
+ "a9149471864495192e39f5f74574b6c8c513588a820487", # p2sh
16
+ "6a04deadbeef", # OP_RETURN deadbeef
17
+ "00141e205151c90c16475363d11b7b8c235cf6c7d695", # p2wpkh
18
+ "00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0" # p2wsh
19
+ ].map{|s|[s].pack("H*")}
20
+ PUBKEYS = [
21
+ "04fb0123fe2c399981bc77d522e2ae3268d2ab15e9a84ae49338a4b1db3886a1ea04cdab955d81e9fa1fcb0c062cb9a5af1ad5dd5064f4afcca322402b07030ec2",
22
+ "0423b8161514560bc8638054b6637ab78f400b24e5694ec8061db635d1f28a17902b14dbf4f80780da659ab24f11ded3095c780452a4004c30ab58dffac33d839a",
23
+ "04f43e76afac66bf3927638b6c4f7e324513ce56d2d658ac9d24c420d09993a4464eea6141a68a4748c092ad0e8f4ac29c4a2f661ef4d22b21f20110f42fcd6f6d",
24
+ ]
25
+
26
+ describe "serialization" do
27
+ it '#to_string' do
28
+ Script.new(SCRIPT[0]).to_string.should ==
29
+ "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 OP_CHECKSIG"
30
+
31
+ Script.new(SCRIPT[1]).to_string.should ==
32
+ "304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901"
33
+
34
+ #Script.new([123].pack("C")).to_string.should == "(opcode 123)"
35
+ Script.new([176].pack("C")).to_string.should == "OP_NOP1"
36
+ Script.from_string("1 OP_DROP 2").to_string.should == "1 OP_DROP 2"
37
+
38
+ Script.from_string("4b").to_string.should == "4b"
39
+ Script.from_string("4b").to_payload.should == "\x01\x4b"
40
+ Script.from_string("ff").to_string.should == "ff"
41
+ Script.from_string("ff").to_payload.should == "\x01\xff"
42
+ Script.from_string("ffff").to_string.should == "ffff"
43
+
44
+ Script.from_string( "ff"*(Script::OP_PUSHDATA1-1) ).to_payload[0] .should == [Script::OP_PUSHDATA1-1].pack("C*")
45
+ Script.from_string( "ff"*Script::OP_PUSHDATA1 ).to_payload[0..1].should == [Script::OP_PUSHDATA1, Script::OP_PUSHDATA1].pack("C*")
46
+ Script.from_string( "ff"*(Script::OP_PUSHDATA1+1) ).to_payload[0..1].should == [Script::OP_PUSHDATA1, Script::OP_PUSHDATA1+1].pack("C*")
47
+ Script.from_string( "ff"*0xff ).to_payload[0..1].should == [Script::OP_PUSHDATA1, 0xff].pack("C*")
48
+ Script.from_string( "ff"*(0xff+1) ).to_payload[0..2].should == [Script::OP_PUSHDATA2, 0x00, 0x01].pack("C*")
49
+ Script.from_string( "ff"*0xffff ).to_payload[0..2].should == [Script::OP_PUSHDATA2, 0xff, 0xff].pack("C*")
50
+ Script.from_string( "ff"*(0xffff+1) ).to_payload[0..4].should == [Script::OP_PUSHDATA4, 0x00, 0x00, 0x01, 0x00].pack("C*")
51
+
52
+ Script.from_string("16").to_string.should == "16"
53
+ Script::OP_2_16.include?(Script.from_string("16").chunks.first).should == true
54
+ Script.from_string("16").to_payload.should == "\x60"
55
+ Script.new("\x60").to_string.should == "16"
56
+
57
+ Script.from_string("0:1:16").to_string.should == "0:1:16"
58
+ Script::OP_2_16.include?(Script.from_string("0:1:16").chunks.first).should == false
59
+ Script.from_string("0:1:16").to_payload.should == "\x01\x16"
60
+ Script.new("\x01\x16").to_string.should == "0:1:16"
61
+
62
+ Script.new("\x4d\x01\x00\x02").to_string.should == "77:1:02"
63
+ Script.from_string("77:1:02").to_payload.should == "\x4d\x01\x00\x02"
64
+ Script.from_string("77:1:01").to_string.should == "77:1:01"
65
+ Script.from_string("77:2:0101").to_string.should == "77:2:0101"
66
+ Script.from_string("78:1:01").to_string.should == "78:1:01"
67
+ Script.from_string("78:2:0101").to_string.should == "78:2:0101"
68
+ Script.new("\x4e\x01\x00\x00\x00\x02").to_string.should == "78:1:02"
69
+ Script.from_string("78:1:02").to_payload.should == "\x4e\x01\x00\x00\x00\x02"
70
+
71
+ Script.new("\x4d\x01\x00").to_string.should == "77:1:"
72
+ Script.from_string("77:1:").to_payload.should == "\x4d\x01\x00"
73
+
74
+ [ # mainnet tx: ebc9fa1196a59e192352d76c0f6e73167046b9d37b8302b6bb6968dfd279b767 outputs
75
+ ["\x01", "238:1:01", true],
76
+ ["\x02\x01", "238:2:0201", true],
77
+ ["L", "238:1:4c", true],
78
+ ["L\x02\x01", "76:2:01", nil],
79
+ ["M", "238:1:4d", true],
80
+ ["M\xff\xff\x01", "238:4:4dffff01", true],
81
+ ["N", "238:1:4e", true],
82
+ ["N\xff\xff\xff\xff\x01", "238:6:4effffffff01", true],
83
+ ].each{|payload,string,parse_invalid|
84
+ Script.new(payload).to_string.should == string
85
+ Script.new(payload).instance_eval{ @parse_invalid }.should == parse_invalid
86
+ Script.from_string(string).to_payload == payload
87
+ }
88
+
89
+ Bitcoin::Script.from_string("(opcode-230) 4 1 2").to_string.should == "(opcode-230) 4 1 2"
90
+ Bitcoin::Script.from_string("(opcode 230) 4 1 2").to_string.should == "(opcode-230) 4 1 2"
91
+ Bitcoin::Script.from_string("(opcode-65449) 4 1 2").to_string.should == "OP_INVALIDOPCODE OP_HASH160 4 1 2"
92
+
93
+ # found in testnet3 block 0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab transactions
94
+ Script.new("\xff\xff\xff\xff").to_string.should == "OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE"
95
+ Script.from_string(Script.new("\xff\xff\xff\xff").to_string).raw.should == "\xFF\xFF\xFF\xFF"
96
+ Script.new("\xff\xff\xff").to_string.should == "OP_INVALIDOPCODE OP_INVALIDOPCODE OP_INVALIDOPCODE"
97
+ Script.from_string(Script.new("\xff\xff\xff").to_string).raw.should == "\xFF\xFF\xFF"
98
+ end
99
+
100
+ it 'Script#binary_from_string' do
101
+ str = Script.new(SCRIPT[0]).to_string
102
+ Script.binary_from_string(str).unpack("H*")[0].should == SCRIPT[0].unpack("H*")[0]
103
+ Script.new(Script.binary_from_string(str)).to_string.should == str
104
+
105
+ str = Script.new(SCRIPT[1]).to_string
106
+ Script.binary_from_string(str).unpack("H*")[0].should == SCRIPT[1].unpack("H*")[0]
107
+ Script.new(Script.binary_from_string(str)).to_string.should == str
108
+ # TODO make tests for OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4 cases
109
+
110
+ string = "2 OP_TOALTSTACK 0 OP_TOALTSTACK OP_TUCK OP_CHECKSIG OP_SWAP OP_HASH160 3cd1def404e12a85ead2b4d3f5f9f817fb0d46ef OP_EQUAL OP_BOOLAND OP_FROMALTSTACK OP_ADD"
111
+ Script.from_string(string).to_string.should == string
112
+
113
+ Script.from_string("0 OP_DROP 2 3 4").to_string.should == "0 OP_DROP 2 3 4"
114
+
115
+ Script.from_string("OP_EVAL").to_string.should == "OP_NOP1"
116
+ Script.from_string("OP_NOP1").to_string.should == "OP_NOP1" # test opcodes_alias table
117
+ Script.from_string("OP_NOP").to_string.should == "OP_NOP"
118
+ Script.from_string("1").to_string.should == "1"
119
+
120
+ Script.from_string("0 ffff OP_CODESEPARATOR 1 ffff 1 OP_CHECKMULTISIG").to_string.should == "0 ffff OP_CODESEPARATOR 1 ffff 1 OP_CHECKMULTISIG"
121
+
122
+ [1,2,4].all?{|n| script = "OP_PUSHDATA#{n} 01 ff"
123
+ Bitcoin::Script.binary_from_string(script) == Bitcoin::Script.binary_from_string( Bitcoin::Script.from_string(script).to_string )
124
+ }.should == true
125
+
126
+ #Script.from_string("-100").to_string.should == "OP_NOP"
127
+ #Script.from_string("100").to_string.should == "100"
128
+
129
+ proc{ Script.from_string("OP_NOP OP_UNKOWN") }.should.raise(Script::ScriptOpcodeError).message.should == "OP_UNKOWN not defined!"
130
+ end
131
+ end
132
+
133
+ describe "get keys/addresses" do
134
+ it '#get_pubkey' do
135
+ Script.new(SCRIPT[0]).get_pubkey.should ==
136
+ "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"
137
+ end
138
+
139
+ it '#get_pubkey_address' do
140
+ Script.new(SCRIPT[0]).get_pubkey_address.should ==
141
+ "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S"
142
+ end
143
+
144
+ it "#get_hash160" do
145
+ Script.new(SCRIPT[2]).get_hash160.should ==
146
+ "17977bca1b6287a5e6559c57ef4b6525e9d7ded6"
147
+ Script.from_string("OP_DUP OP_HASH160 0 OP_EQUALVERIFY OP_CHECKSIG")
148
+ .get_hash160.should == nil
149
+ Script.new(SCRIPT[7]).get_hash160.should == "1e205151c90c16475363d11b7b8c235cf6c7d695"
150
+ end
151
+
152
+ it "#get_hash160_address" do
153
+ Script.new(SCRIPT[2]).get_hash160_address.should ==
154
+ "139k1g5rtTsL4aGZbcASH3Fv3fUh9yBEdW"
155
+ end
156
+
157
+ it "#get_multisig_pubkeys" do
158
+ Script.new(SCRIPT[3]).get_multisig_pubkeys.should == [
159
+ "04573b6e9f3a714440048a7b87d606bcbf9e45b8586e70a67a3665ea720c095658471a523e5d923f3f3e015626e7c900bd08560ddffeb17d33c5b52c96edb87595",
160
+ "04039c2f4e413a26901e67ad4adbb6a4759af87bc16c7120459ecc9482fed3dd4a4502947f7b4c7782dcadc2bed513ed14d5e770452b97ae246ac2030f13b80a51",
161
+ "048b0f9d04e495c3c754f8c3c109196d713d0778882ef098f785570ee6043f8c192d8f84df43ebafbcc168f5d95a074dc4010b62c003e560abc163c312966b74b6"].map{|pk| [pk].pack("H*")}
162
+ Script.from_string("3 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG")
163
+ .get_multisig_pubkeys.should == [
164
+ "04fb0123fe2c399981bc77d522e2ae3268d2ab15e9a84ae49338a4b1db3886a1ea04cdab955d81e9fa1fcb0c062cb9a5af1ad5dd5064f4afcca322402b07030ec2",
165
+ "0423b8161514560bc8638054b6637ab78f400b24e5694ec8061db635d1f28a17902b14dbf4f80780da659ab24f11ded3095c780452a4004c30ab58dffac33d839a",
166
+ "04f43e76afac66bf3927638b6c4f7e324513ce56d2d658ac9d24c420d09993a4464eea6141a68a4748c092ad0e8f4ac29c4a2f661ef4d22b21f20110f42fcd6f6d"].map{|k|[k].pack("H*")}
167
+ end
168
+
169
+ it "#get_multisig_addresses" do
170
+ Script.new(SCRIPT[3]).get_multisig_addresses.should == [
171
+ "1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj", "19Fm2gY7qDTXriNTEhFY2wjxbHna3Gvenk",
172
+ "1B6k6g1d2L975i7beAbiBRxfBWhxomPxvy"]
173
+ Script.new(SCRIPT[4]).get_multisig_addresses.should == [
174
+ "1F2Nnyn7niMcheiYhkHrkc18aDxEkFowy5", "1EE7JGimkV7QqyHwXDJvk3b1yEN4ZUWeqx"]
175
+
176
+ # from tx 274f8be3b7b9b1a220285f5f71f61e2691dd04df9d69bb02a8b3b85f91fb1857, second pubkey has invalid encoding.
177
+ output = "1 0351efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da78 00f2b7816db49d55d24df7bdffdbc1e203b424e8cd39f5651ab938e5e4a193569e 2 OP_CHECKMULTISIG"
178
+ Bitcoin::Script.from_string(output).get_multisig_addresses.should == ["1NdB761LmTmrJixxp93nz7pEiCx5cKPW44", nil]
179
+ end
180
+
181
+ it "#get_p2sh_address" do
182
+ Script.new(SCRIPT[5]).get_p2sh_address.should ==
183
+ "3FDuvkgzsW7LpzL9RBjtjvL7bFXCEeZ7xi"
184
+ end
185
+
186
+ it "#get_address" do
187
+ Script.new(SCRIPT[0]).get_address.should ==
188
+ "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S"
189
+ Script.new(SCRIPT[1]).get_address.should == nil
190
+ Script.new(SCRIPT[2]).get_address.should ==
191
+ "139k1g5rtTsL4aGZbcASH3Fv3fUh9yBEdW"
192
+ Script.new(SCRIPT[3]).get_address.should ==
193
+ "1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj"
194
+ Script.new(SCRIPT[4]).get_address.should ==
195
+ "1F2Nnyn7niMcheiYhkHrkc18aDxEkFowy5"
196
+ Script.new(SCRIPT[5]).get_address.should ==
197
+ "3FDuvkgzsW7LpzL9RBjtjvL7bFXCEeZ7xi"
198
+ end
199
+
200
+ it "#get_addresses" do
201
+ Script.new(SCRIPT[0]).get_addresses.
202
+ should == ["12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S"]
203
+ Script.new(SCRIPT[3]).get_addresses
204
+ .should == ["1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj",
205
+ "19Fm2gY7qDTXriNTEhFY2wjxbHna3Gvenk", "1B6k6g1d2L975i7beAbiBRxfBWhxomPxvy"]
206
+ end
207
+
208
+ it "should get op_return data" do
209
+ Script.new(SCRIPT[6]).get_op_return_data.should == "deadbeef"
210
+ Script.new(SCRIPT[1]).get_op_return_data.should == nil
211
+ Script.from_string("OP_RETURN").get_op_return_data.should == nil
212
+ Script.from_string("OP_RETURN dead beef").get_op_return_data.should == nil
213
+ Script.from_string("OP_RETURN deadbeef").get_op_return_data.should == "deadbeef"
214
+ Script.from_string("OP_RETURN OP_CHECKSIG").get_op_return_data.should == "ac00"
215
+ end
216
+ end
217
+
218
+ describe "determine type" do
219
+
220
+ it '#is_standard?' do
221
+ Script.new(SCRIPT[0]).is_standard?.should == true
222
+ Script.new(SCRIPT[1]).is_standard?.should == false
223
+ Script.new(SCRIPT[2]).is_standard?.should == true
224
+ Script.new(SCRIPT[3]).is_standard?.should == true
225
+ Script.new(SCRIPT[4]).is_standard?.should == true
226
+ Script.new(SCRIPT[5]).is_standard?.should == true
227
+ Script.new(SCRIPT[6]).is_standard?.should == true
228
+ Script.new(SCRIPT[7]).is_standard?.should == true
229
+ Script.new(SCRIPT[8]).is_standard?.should == true
230
+ end
231
+
232
+ it '#is_pubkey?' do
233
+ Script.new(SCRIPT[0]).is_pubkey?.should == true
234
+ Script.new(SCRIPT[1]).is_pubkey?.should == false
235
+ Script.new(SCRIPT[2]).is_pubkey?.should == false
236
+ Script.new(SCRIPT[3]).is_pubkey?.should == false
237
+ Script.new(SCRIPT[4]).is_send_to_ip?.should == false
238
+ Script.new(SCRIPT[5]).is_pubkey?.should == false
239
+ Script.new(SCRIPT[6]).is_pubkey?.should == false
240
+ Script.new(SCRIPT[7]).is_pubkey?.should == false
241
+ Script.new(SCRIPT[8]).is_pubkey?.should == false
242
+ Script.from_string("0 OP_CHECKSIG").is_pubkey?.should == false # testnet aba0441c4c9933dcd7db789c39053739ec435ab742ed2c23c05f22f1488c0bfd
243
+ end
244
+
245
+ it "#is_hash160?" do
246
+ Script.new(SCRIPT[0]).is_hash160?.should == false
247
+ Script.new(SCRIPT[1]).is_pubkey?.should == false
248
+ Script.new(SCRIPT[2]).is_hash160?.should == true
249
+ Script.from_string("OP_DUP OP_HASH160 0 OP_EQUALVERIFY OP_CHECKSIG")
250
+ .is_hash160?.should == false
251
+ Script.new(SCRIPT[5]).is_hash160?.should == false
252
+ Script.new(SCRIPT[6]).is_hash160?.should == false
253
+ Script.new(SCRIPT[7]).is_hash160?.should == false
254
+ Script.new(SCRIPT[8]).is_hash160?.should == false
255
+ end
256
+
257
+ it "#is_multisig?" do
258
+ Script.new(SCRIPT[3]).is_multisig?.should == true
259
+ Script.new(SCRIPT[4]).is_multisig?.should == true
260
+ Script.new(SCRIPT[0]).is_multisig?.should == false
261
+ Script.new(SCRIPT[6]).is_multisig?.should == false
262
+ Script.new(SCRIPT[7]).is_multisig?.should == false
263
+ Script.new(SCRIPT[8]).is_multisig?.should == false
264
+ Script.new("OP_DUP OP_DROP 2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG")
265
+ .is_multisig?.should == false
266
+ Script.new("OP_DROP OP_CHECKMULTISIG").is_multisig?.should == false
267
+ Script.from_string("d366fb5cbf048801b1bf0742bb0d873f65afb406f41756bd4a31865870f6a928 OP_DROP 2 02aae4b5cd593da83679a9c5cadad4c180c008a40dd3ed240cceb2933b9912da36 03a5aebd8b1b6eec06abc55fb13c72a9ed2143f9eed7d665970e38853d564bf1ab OP_CHECKMULTISIG").is_multisig?.should == false
268
+ end
269
+
270
+ it '#is_p2sh?' do
271
+ Script.new(SCRIPT[0]).is_p2sh?.should == false
272
+ Script.new(SCRIPT[1]).is_p2sh?.should == false
273
+ Script.new(SCRIPT[2]).is_p2sh?.should == false
274
+ Script.new(SCRIPT[3]).is_p2sh?.should == false
275
+ Script.new(SCRIPT[4]).is_p2sh?.should == false
276
+ Script.new(SCRIPT[5]).is_p2sh?.should == true
277
+ Script.new(SCRIPT[6]).is_p2sh?.should == false
278
+ Script.new(SCRIPT[7]).is_p2sh?.should == false
279
+ Script.new(SCRIPT[8]).is_p2sh?.should == false
280
+ Script.from_string("OP_DUP OP_HASH160 b689ebc262f50297139e7d16c4f8909e14ed4322 OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_HASH160 1b6246121883816fc0637e4aa280aca1df219b1a OP_EQUAL")
281
+ .is_p2sh?.should == false
282
+ end
283
+
284
+ it '#is_op_return?' do
285
+ Script.new(SCRIPT[0]).is_op_return?.should == false
286
+ Script.new(SCRIPT[1]).is_op_return?.should == false
287
+ Script.new(SCRIPT[2]).is_op_return?.should == false
288
+ Script.new(SCRIPT[3]).is_op_return?.should == false
289
+ Script.new(SCRIPT[4]).is_op_return?.should == false
290
+ Script.new(SCRIPT[5]).is_op_return?.should == false
291
+ Script.new(SCRIPT[6]).is_op_return?.should == true
292
+ Script.new(SCRIPT[7]).is_op_return?.should == false
293
+ Script.new(SCRIPT[8]).is_op_return?.should == false
294
+ Script.from_string("OP_RETURN dead beef").is_op_return?.should == false
295
+ Script.from_string("OP_RETURN deadbeef").is_op_return?.should == true
296
+ Script.from_string("OP_RETURN OP_CHECKSIG").is_op_return?.should == true
297
+ end
298
+
299
+ it '#is_witness_v0_keyhash?' do
300
+ Script.new(SCRIPT[0]).is_witness_v0_keyhash?.should == false
301
+ Script.new(SCRIPT[1]).is_witness_v0_keyhash?.should == false
302
+ Script.new(SCRIPT[2]).is_witness_v0_keyhash?.should == false
303
+ Script.new(SCRIPT[3]).is_witness_v0_keyhash?.should == false
304
+ Script.new(SCRIPT[4]).is_witness_v0_keyhash?.should == false
305
+ Script.new(SCRIPT[5]).is_witness_v0_keyhash?.should == false
306
+ Script.new(SCRIPT[6]).is_witness_v0_keyhash?.should == false
307
+ Script.new(SCRIPT[7]).is_witness_v0_keyhash?.should == true
308
+ Script.new(SCRIPT[8]).is_witness_v0_keyhash?.should == false
309
+ end
310
+
311
+ it '#is_witness_v0_scripthash?' do
312
+ Script.new(SCRIPT[0]).is_witness_v0_scripthash?.should == false
313
+ Script.new(SCRIPT[1]).is_witness_v0_scripthash?.should == false
314
+ Script.new(SCRIPT[2]).is_witness_v0_scripthash?.should == false
315
+ Script.new(SCRIPT[3]).is_witness_v0_scripthash?.should == false
316
+ Script.new(SCRIPT[4]).is_witness_v0_scripthash?.should == false
317
+ Script.new(SCRIPT[5]).is_witness_v0_scripthash?.should == false
318
+ Script.new(SCRIPT[6]).is_witness_v0_scripthash?.should == false
319
+ Script.new(SCRIPT[7]).is_witness_v0_scripthash?.should == false
320
+ Script.new(SCRIPT[8]).is_witness_v0_scripthash?.should == true
321
+ end
322
+
323
+ it "#type" do
324
+ Script.new(SCRIPT[0]).type.should == :pubkey
325
+ Script.new(SCRIPT[1]).type.should == :unknown
326
+ Script.new(SCRIPT[2]).type.should == :hash160
327
+ Script.new(SCRIPT[3]).type.should == :multisig
328
+ Script.new(SCRIPT[4]).type.should == :multisig
329
+ Script.new(SCRIPT[5]).type.should == :p2sh
330
+ Script.new(SCRIPT[6]).type.should == :op_return
331
+ Script.new(SCRIPT[7]).type.should == :witness_v0_keyhash
332
+ Script.new(SCRIPT[8]).type.should == :witness_v0_scripthash
333
+ Script.from_string("OP_RETURN OP_CHECKSIG").type.should == :op_return
334
+ Script.from_string("OP_RETURN dead beef").type.should == :unknown
335
+ end
336
+
337
+ end
338
+
339
+ describe "generate scripts" do
340
+
341
+ it "should generate pubkey script" do
342
+ Script.to_pubkey_script(PUBKEYS[0]).should ==
343
+ Script.from_string("#{PUBKEYS[0]} OP_CHECKSIG").raw
344
+ Script.to_pubkey_script(PUBKEYS[1]).should ==
345
+ Script.from_string("#{PUBKEYS[1]} OP_CHECKSIG").raw
346
+ end
347
+
348
+ it "should generate hash160 script" do
349
+ Script.to_address_script('16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9')
350
+ .should == ["76a9143be0c2daaabbf3d53e47352c19d1e8f047e2f94188ac"].pack("H*")
351
+ hash160 = Bitcoin.hash160_from_address('16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9')
352
+ Script.to_hash160_script(hash160)
353
+ .should == Script.from_string("OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG").raw
354
+ Script.to_address_script('mr1jU3Adw2pkvxTLvQA4MKpXB9Dynj9cXF')
355
+ .should == nil
356
+ end
357
+
358
+ it "should generate multisig script" do
359
+ Script.to_multisig_script(2, *PUBKEYS[0..2]).should ==
360
+ Script.from_string("2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG").raw
361
+ Script.to_multisig_script(1, *PUBKEYS[0..1]).should ==
362
+ Script.from_string("1 #{PUBKEYS[0..1].join(' ')} 2 OP_CHECKMULTISIG").raw
363
+
364
+ m=n=16; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
365
+ .should == "16 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 16 OP_CHECKMULTISIG"
366
+ m=n=17; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
367
+ .should == "0:1:11 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 0:1:11 OP_CHECKMULTISIG"
368
+ m=n=20; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
369
+ .should == "0:1:14 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 0:1:14 OP_CHECKMULTISIG"
370
+ end
371
+
372
+ it "should generate p2sh script" do
373
+ address = "3CkxTG25waxsmd13FFgRChPuGYba3ar36B"
374
+ hash160 = Bitcoin.hash160_from_address address
375
+ Script.to_p2sh_script(hash160).should ==
376
+ Script.from_string("OP_HASH160 #{hash160} OP_EQUAL").raw
377
+ end
378
+
379
+ it "to_witness_hash160_script" do
380
+ hash160 = Bitcoin.hash160('025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357')
381
+ Script.to_witness_hash160_script(hash160).should == Script.new("00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1".htb).raw
382
+ end
383
+
384
+ it "should generate p2wsh script" do
385
+ witness_script = '21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac'
386
+ sha256 = Bitcoin.sha256(witness_script)
387
+ Script.to_witness_p2sh_script(sha256).should == Script.new("00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0".htb).raw
388
+ end
389
+
390
+ it "should generate op_return script" do
391
+ Script.to_op_return_script("deadbeef").should == SCRIPT[6]
392
+ Script.to_op_return_script.should == Script.from_string("OP_RETURN").raw
393
+ end
394
+
395
+ it "should determine type for address script" do
396
+ address = '16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9'
397
+ hash160 = Bitcoin.hash160_from_address address
398
+ Script.to_address_script(address).should ==
399
+ Script.from_string("OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG").raw
400
+
401
+ address = "3CkxTG25waxsmd13FFgRChPuGYba3ar36B"
402
+ hash160 = Bitcoin.hash160_from_address address
403
+ Script.to_p2sh_script(hash160).should ==
404
+ Script.from_string("OP_HASH160 #{hash160} OP_EQUAL").raw
405
+ end
406
+
407
+ end
408
+
409
+ describe "generate script sigs" do
410
+ before do
411
+ @sig = '3045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec'.htb
412
+ end
413
+
414
+ it "should generate pubkey script sig" do
415
+ pub = '04bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
416
+ expected_script = '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec014104bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
417
+
418
+ Script.to_pubkey_script_sig(@sig, pub).should == expected_script
419
+ end
420
+
421
+ it "should accept a compressed public key as input" do
422
+ pub = '02bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'.htb
423
+ expected_script = '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec012102bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'.htb
424
+
425
+ Script.to_pubkey_script_sig(@sig, pub).should == expected_script
426
+ end
427
+
428
+ it "should reject an improperly encoding public key" do
429
+ # Not binary encoded, like it's supposed to be.
430
+ pub = '02bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'
431
+
432
+ lambda {
433
+ Script.to_pubkey_script_sig(@sig, pub)
434
+ }.should.raise
435
+ end
436
+
437
+ it "should support different hash types" do
438
+ hash_type = Script::SIGHASH_TYPE[:single]
439
+ pub = '04bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
440
+ expected_script = '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec034104bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
441
+
442
+ Script.to_pubkey_script_sig(@sig, pub, hash_type).should == expected_script
443
+ end
444
+
445
+ it "should generate multisig script sig" do
446
+ hash_type = Script::SIGHASH_TYPE[:none]
447
+ expected_script = '00483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec02483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec02'.htb
448
+
449
+ Script.to_multisig_script_sig(@sig, @sig, hash_type).should == expected_script
450
+ end
451
+ end
452
+
453
+
454
+ describe "signatures_count" do
455
+
456
+ it "should be zero in data-only scripts" do
457
+ [false, true].each do |accurate|
458
+ Script.from_string("").sigops_count_accurate(accurate).should == 0
459
+ Script.from_string("DEADBEEF").sigops_count_accurate(accurate).should == 0
460
+ Script.from_string("DEAD BEEF").sigops_count_accurate(accurate).should == 0
461
+ Script.from_string("DE AD BE EF").sigops_count_accurate(accurate).should == 0
462
+ Script.from_string("OP_NOP").sigops_count_accurate(accurate).should == 0
463
+ Script.from_string("0").sigops_count_accurate(accurate).should == 0
464
+ Script.from_string("0 1").sigops_count_accurate(accurate).should == 0
465
+ Script.from_string("0 1 2 3").sigops_count_accurate(accurate).should == 0
466
+ end
467
+ end
468
+
469
+ it "should count sigops" do
470
+ [false, true].each do |accurate|
471
+ Script.from_string("OP_CHECKSIG").sigops_count_accurate(accurate).should == 1
472
+ Script.from_string("OP_CHECKSIGVERIFY").sigops_count_accurate(accurate).should == 1
473
+ Script.from_string("OP_CHECKSIG OP_CHECKSIGVERIFY").sigops_count_accurate(accurate).should == 2
474
+ Script.from_string("OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG").sigops_count_accurate(accurate).should == 4
475
+ Script.from_string("1 OP_CHECKSIG 2 OP_CHECKSIG DEADBEEF OP_CHECKSIG 3 OP_CHECKSIG 4").sigops_count_accurate(accurate).should == 4
476
+ end
477
+ end
478
+
479
+ it "should count multisig as 20 sigops in legact inaccurate mode" do
480
+ Script.from_string("OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
481
+ Script.from_string("OP_CHECKMULTISIGVERIFY").sigops_count_accurate(false).should == 20
482
+ Script.from_string("OP_CHECKMULTISIG OP_CHECKMULTISIGVERIFY").sigops_count_accurate(false).should == 40
483
+ Script.from_string("1 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
484
+ Script.from_string("5 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
485
+ Script.from_string("40 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
486
+ end
487
+
488
+ it "should count multisig accurately using number of pubkeys" do
489
+ Script.from_string("1 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 1
490
+ Script.from_string("1 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 1
491
+ Script.from_string("2 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 2
492
+ Script.from_string("2 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 2
493
+ Script.from_string("15 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 15
494
+ Script.from_string("15 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 15
495
+ Script.from_string("16 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 16
496
+ Script.from_string("16 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 16
497
+ Script.from_string("4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 11
498
+ end
499
+
500
+ it "should count multisig as 20 sigops in accurate mode when the pubkey count is missing" do
501
+ Script.from_string("OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
502
+ Script.from_string("OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
503
+ end
504
+
505
+ it "should count multisig as 20 sigops when pubkey count is not OP_{1,...,16}, but bignum as pushdata" do
506
+ Script.from_string("#{Script::OP_PUSHDATA1}:1:01 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
507
+ Script.from_string("#{Script::OP_PUSHDATA1}:1:02 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
508
+ end
509
+
510
+ it "should count multisig as 20 sigops in accurate mode when the pubkey count is out of bounds" do
511
+ Script.from_string("0 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
512
+ Script.from_string("0 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
513
+ Script.from_string("0 OP_CHECKMULTISIG 0 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 40
514
+ Script.from_string("DEADBEEF OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
515
+ Script.from_string("#{Script::OP_PUSHDATA1}:1:11 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
516
+ end
517
+
518
+ it "should extract signature count from P2SH scriptSig" do
519
+
520
+ # Given a P2SH input script (the one with the signatures and a serialized script inside)
521
+ # This should count as 12 sigops (1 + 4 + 7)
522
+ script = Script.from_string("OP_CHECKSIG 4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY")
523
+
524
+ # Serialize the script to be used as a plain pushdata (which will be decoded as a script).
525
+ serialized_script = Script.new("").append_pushdata(script.to_binary)
526
+
527
+ # If empty should return 0.
528
+ Script.from_string("").sigops_count_for_p2sh.should == 0
529
+
530
+ # If ends with OP_N
531
+ Script.from_string("0").sigops_count_for_p2sh.should == 0
532
+ Script.from_string("1").sigops_count_for_p2sh.should == 0
533
+ Script.from_string("5").sigops_count_for_p2sh.should == 0
534
+ Script.from_string("16").sigops_count_for_p2sh.should == 0
535
+
536
+ # If ends with opcode
537
+ Script.from_string("OP_NOP").sigops_count_for_p2sh.should == 0
538
+ Script.from_string("OP_HASH160").sigops_count_for_p2sh.should == 0
539
+ Script.from_string("OP_CHECKSIG").sigops_count_for_p2sh.should == 0
540
+ Script.from_string("DEADBEEF OP_NOP").sigops_count_for_p2sh.should == 0
541
+ Script.from_string("DEADBEEF OP_HASH160").sigops_count_for_p2sh.should == 0
542
+ Script.from_string("DEADBEEF OP_CHECKSIG").sigops_count_for_p2sh.should == 0
543
+
544
+ # If only has the script, should parse it well
545
+ serialized_script.sigops_count_for_p2sh.should == 12
546
+
547
+ # If ends with the script, should also parse well.
548
+ Script.new(Script.from_string("DEADBEEF CAFEBABE").to_binary + serialized_script.to_binary).sigops_count_for_p2sh.should == 12
549
+ Script.new(Script.from_string("DEADBEEF 1").to_binary + serialized_script.to_binary).sigops_count_for_p2sh.should == 12
550
+
551
+ # If has the script, but ends with non-script, should return 0
552
+ # DEADBEEF is a script with OP_CHECKSIGVERIFY in it, so we wrap it in a serialized script with plain pushdata to have 0 count.
553
+ Script.new(serialized_script.to_binary + Script.new("").append_pushdata(Script.from_string("DEADBEEF").to_binary).to_binary).sigops_count_for_p2sh.should == 0
554
+ Script.new(serialized_script.to_binary + Script.from_string("1").to_binary).sigops_count_for_p2sh.should == 0
555
+ end
556
+
557
+ it "should count sigops up until an invalid OP_PUSHDATA" do
558
+ script_binary = Bitcoin::Protocol.read_binary_file(fixtures_path("txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin"))
559
+ Script.new(script_binary).sigops_count_accurate(false).should == 39998
560
+ end
561
+
562
+ end
563
+
564
+ it '#run' do
565
+ script = SCRIPT[1] + SCRIPT[0]
566
+ Script.new(script).run.should == true
567
+
568
+ Script.from_string("1 OP_DUP OP_DROP 1 OP_EQUAL")
569
+ .run.should == true
570
+ Script.from_string("1 OP_DUP OP_DROP 1 OP_EQUAL")
571
+ .run.should == true
572
+ Script.from_string("foo OP_DUP OP_DROP foo OP_EQUAL")
573
+ .run.should == true
574
+ Script.from_string("bar foo OP_DUP OP_DROP bar OP_EQUAL")
575
+ .run.should == false
576
+
577
+ Script.from_string("1 OP_DROP 2").run.should == true
578
+
579
+ # testnet3 tx: 5dea81f9d9d2ea6d06ce23ff225d1e240392519017643f75c96fa2e4316d948a
580
+ script = Script.new( ["0063bac0d0e0f0f1f2f3f3f4ff675168"].pack("H*") )
581
+ script.to_string.should == "0 OP_IF (opcode-186) (opcode-192) (opcode-208) (opcode-224) (opcode-240) (opcode-241) (opcode-242) (opcode-243) (opcode-243) (opcode-244) OP_INVALIDOPCODE OP_ELSE 1 OP_ENDIF"
582
+ script.run.should == true
583
+
584
+ # mainnet tx: 61a078472543e9de9247446076320499c108b52307d8d0fafbe53b5c4e32acc4 redeeming output from 5342c96b946ea2c5e497de5dbf7762021f94aba2c8222c17ed28492fdbb4a6d9
585
+ script = Bitcoin::Script.from_string("16cfb9bc7654ef1d7723e5c2722fc0c3d505045e OP_SIZE OP_DUP 1 OP_GREATERTHAN OP_VERIFY OP_NEGATE OP_HASH256 OP_HASH160 OP_SHA256 OP_SHA1 OP_RIPEMD160 OP_EQUAL")
586
+ script.run.should == true
587
+
588
+ # mainnet tx: 340aa9f72206d600b7e89c9137e4d2d77a920723f83e34707ff452121fd48492 redeeming output from f2d72a7bf22e29e3f2dc721afbf0a922860f81db9fc7eb397937f9d7e87cc438
589
+ script = Bitcoin::Script.from_string("027ce87f6f41dd4d7d874b40889f7df6b288f77f OP_DEPTH OP_HASH256 OP_HASH160 OP_SHA256 OP_SHA1 OP_RIPEMD160 OP_EQUAL")
590
+ script.run.should == true
591
+ end
592
+
593
+ it "should run op_checkmultisig p2sh script with empty signature" do
594
+ # mainnet tx: b78706427923f73b334fd68040f35900503da33c671723c41ca845f6fba6c29c
595
+ tx1 = Bitcoin::P::Tx.new("01000000023904cd3644c6d440a6d752c95f07737c46f5e70fb6fbb28f00aa17e281868b7b010000006b483045022100ac455750dc430957942e9766f88aecfe6eb17d4244eb2cb50ca4a25336fd4dd702202640cc943f4fe8f2166b03005bed3bd024f4762767322b60bf471ecf8e3f3ede012102348d4cad0084f88c4c02bdc1bf90cc6c0893a0b97af76ef644daf72e6786b4afffffffffb84057ae61ad22ac17c02635ee1b37d170ef785847ec28efe848a5607331568e020000006b483045022100d7fee595d7a1f9969767098f8582e7a563f08437f461f0a25395f35c1833839302205f565ab12d343478471a78669c4c3476714032f7758a781d7deab19f160784e0012102ea69c47753d8e0228c0c426294a6b4dc926aebbeb8561248d40be37d257d94e0ffffffff01a08601000000000017a91438430c4d1c214bf11d2c0c3dea8e5e9a5d11aab08700000000".htb)
596
+ # mainnet tx: 136becd0892fa38c5aca8104db8b90b3a0e6b40912b7d1462aed583c067054cd
597
+ tx2 = Bitcoin::P::Tx.new("01000000019cc2a6fbf645a81cc42317673ca33d500059f34080d64f333bf72379420687b70000000008000051005102ae91ffffffff0150c300000000000002ae9100000000".htb)
598
+ tx2.verify_input_signature(0, tx1).should == true
599
+ end
600
+
601
+ it "should debug script branches (OP_IF/NOTIF/ELSE/ENDIF) correctly" do
602
+
603
+ script = Bitcoin::Script.from_string("1 OP_NOTIF OP_RETURN OP_ENDIF")
604
+ script.run {}
605
+ script.debug.should == [
606
+ [], "OP_1",
607
+ [1], "OP_NOTIF",
608
+ [], "OP_ENDIF",
609
+ [], "RESULT"
610
+ ]
611
+
612
+ script = Bitcoin::Script.from_string("1 OP_IF OP_RETURN OP_ENDIF")
613
+ script.run {}
614
+ script.debug.should == [
615
+ [], "OP_1",
616
+ [1], "OP_IF",
617
+ [], "OP_RETURN",
618
+ [], "INVALID TRANSACTION", "RESULT"
619
+ ]
620
+
621
+ script = Bitcoin::Script.from_string("1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
622
+ script.run {}
623
+ script.debug.should == [
624
+ [], "OP_1",
625
+ [1], "OP_IF",
626
+ [], "OP_2",
627
+ [2], "OP_ELSE",
628
+ [2], "OP_ENDIF",
629
+ [2], "OP_2",
630
+ [2, 2], "OP_EQUAL",
631
+ [1], "RESULT"]
632
+
633
+ script = Bitcoin::Script.from_string("0 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
634
+ script.run {}
635
+ script.debug.should == [
636
+ [], "OP_0",
637
+ [[""]], "OP_IF",
638
+ [], "OP_ELSE",
639
+ [], "OP_3",
640
+ [3], "OP_ENDIF",
641
+ [3], "OP_2",
642
+ [3, 2], "OP_EQUAL",
643
+ [0], "RESULT"]
644
+
645
+ script = Bitcoin::Script.from_string("0 OP_IF deadbeef OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
646
+ script.run {}
647
+ script.debug.should == [
648
+ [], "OP_0",
649
+ [[""]], "OP_IF",
650
+ [], "OP_ELSE",
651
+ [], "OP_3",
652
+ [3], "OP_ENDIF",
653
+ [3], "OP_2",
654
+ [3, 2], "OP_EQUAL",
655
+ [0], "RESULT"]
656
+
657
+ script = Bitcoin::Script.from_string("1 OP_IF 2 OP_ELSE 3 OP_ENDIF 2 OP_EQUAL")
658
+ script.run {}
659
+ script.debug.should == [[], "OP_1", [1], "OP_IF", [], "OP_2", [2], "OP_ELSE", [2], "OP_ENDIF", [2], "OP_2", [2, 2], "OP_EQUAL", [1], "RESULT"]
660
+
661
+ script = Bitcoin::Script.from_string("
662
+ 0
663
+ 3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501
664
+ 304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301
665
+ 1
666
+ 635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853
667
+ OP_IF
668
+ 2
669
+ 022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc
670
+ 02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd
671
+ 2
672
+ OP_CHECKMULTISIG
673
+ OP_ELSE
674
+ 2
675
+ 025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d57885348
676
+ 02b18808b3e6857e396167890a52f898cbd5215354f027b89fed895058e49a158b
677
+ 2
678
+ OP_CHECKMULTISIG
679
+ OP_ENDIF")
680
+ script.run {}
681
+ script.debug.should == [
682
+ [], "OP_0",
683
+ [[""]], "PUSH DATA 3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501",
684
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"]], "PUSH DATA 304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301",
685
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"]], "OP_1",
686
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1], "PUSH DATA 635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853",
687
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, ["635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853"]], "OP_IF",
688
+
689
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1], "OP_2",
690
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2], "PUSH DATA 022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc",
691
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"]], "PUSH DATA 02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd",
692
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"], ["02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd"]], "OP_2",
693
+ [[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"], ["02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd"], 2], "OP_CHECKMULTISIG",
694
+ [[""], 0], "OP_ELSE",
695
+ [[""], 0], "OP_ENDIF",
696
+ [[""], 0], "RESULT"]
697
+ end
698
+
699
+ it "should not execute p2sh recursively" do
700
+ # this script_sig includes a pattern that matches the p2sh template
701
+ script_sig = "0 a914b472a266d0bd89c13706a4132ccfb16f7c3b9fcb87"
702
+ pk_script = "OP_HASH160 92a04bc86e23f169691bd6926d11853cc61e1852 OP_EQUAL"
703
+ script = Bitcoin::Script.from_string(script_sig + " " + pk_script)
704
+ script.run.should == true
705
+ end
706
+
707
+ def build_p2sh_multisig_tx(m, *keys)
708
+ redeem_script = Bitcoin::Script.to_multisig_script(m, *keys.map(&:pub))
709
+ p2sh_address = Bitcoin.hash160_to_p2sh_address(Bitcoin.hash160(redeem_script.hth))
710
+
711
+ prev_tx = build_tx {|t| t.input {|i| i.coinbase}
712
+ t.output {|o| o.to p2sh_address; o.value 50e8 } }
713
+ tx = build_tx {|t| t.input {|i| i.prev_out prev_tx, 0 }
714
+ t.output {|o| o.to Bitcoin::Key.generate.addr; o.value 50e8 } }
715
+
716
+ sig_hash = tx.signature_hash_for_input(0, redeem_script)
717
+ return prev_tx, tx, redeem_script, sig_hash
718
+ end
719
+
720
+ it "#sort_p2sh_multisig_signatures 3-of-3" do
721
+ keys = 3.times.map { Bitcoin::Key.generate }
722
+
723
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(3, *keys)
724
+ sigs = keys.map {|k| k.sign(sig_hash) }
725
+
726
+ # add sigs in all possible orders, sort them, and see if they are valid
727
+ [0, 1, 2].permutation do |order|
728
+ script_sig = Script.to_p2sh_multisig_script_sig(redeem_script)
729
+ order.each{|i| script_sig = Script.add_sig_to_multisig_script_sig(sigs[i], script_sig)}
730
+ script_sig = Script.sort_p2sh_multisig_signatures(script_sig, sig_hash)
731
+ tx.in[0].script_sig = script_sig
732
+ tx.verify_input_signature(0, prev_tx).should == true
733
+ end
734
+ end
735
+
736
+ it "#sort_p2sh_multisig_signatures 2-of-3" do
737
+ keys = 3.times.map { Bitcoin::Key.generate }
738
+
739
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(2, *keys)
740
+ sigs = keys.map {|k| k.sign(sig_hash) }
741
+
742
+ # add sigs in all possible orders, sort them, and see if they are valid
743
+ [0, 1, 2].permutation(2) do |order|
744
+ script_sig = Script.to_p2sh_multisig_script_sig(redeem_script)
745
+ order.each{|i| script_sig = Script.add_sig_to_multisig_script_sig(sigs[i], script_sig)}
746
+ script_sig = Script.sort_p2sh_multisig_signatures(script_sig, sig_hash)
747
+ tx.in[0].script_sig = script_sig
748
+ tx.verify_input_signature(0, prev_tx).should == true
749
+ end
750
+ end
751
+
752
+ end
753
+
754
+ describe "Implements BIP62" do
755
+ it 'tests for incorrectly encoded S-values in signatures' do
756
+ # TX 3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae
757
+ sig_orig = ["304502210088984573e3e4f33db7df6aea313f1ce67a3ef3532ea89991494c7f018258371802206ceefc9291450dbd40d834f249658e0f64662d52a41cf14e20c9781144f2fe0701"].pack("H*")
758
+ Bitcoin::Script::is_low_der_signature?(sig_orig).should == true
759
+
760
+ # Set the start of the S-value to 0xff so it's well above the order of the curve divided by two
761
+ sig = sig_orig.unpack("C*")
762
+ length_r = sig[3]
763
+ sig[6 + length_r] = 0xff
764
+
765
+ Bitcoin::Script::is_low_der_signature?(sig.pack("C*")).should == false
766
+ end
767
+ it 'enforces rules 3 and 4' do
768
+ Script.new([75].pack("C") + 'A' * 75).pushes_are_canonical?.should == true
769
+ Script.new([Bitcoin::Script::OP_PUSHDATA1, 75].pack("CC") + 'A' * 75).pushes_are_canonical?.should == false
770
+ Script.new([Bitcoin::Script::OP_PUSHDATA2, 255].pack("Cv") + 'A' * 255).pushes_are_canonical?.should == false
771
+ Script.new([Bitcoin::Script::OP_PUSHDATA4, 1645].pack("CV") + 'A' * 1645).pushes_are_canonical?.should == false
772
+ end
773
+ end
774
+
775
+ describe "Implements BIP66" do
776
+ def build_crediting_tx(script_pk)
777
+ tx = Bitcoin::P::Tx.new
778
+ input = Bitcoin::P::TxIn.new(nil, 0xffffffff, 2, "\x00\x00")
779
+ output = Bitcoin::P::TxOut.new(0, script_pk)
780
+ tx.add_in(input)
781
+ tx.add_out(output)
782
+ Bitcoin::P::Tx.new(tx.to_payload)
783
+ end
784
+
785
+ def build_spending_tx(script_sig, tx_credit)
786
+ tx = Bitcoin::P::Tx.new
787
+ input = Bitcoin::P::TxIn.new(tx_credit.binary_hash, 0, 2, script_sig)
788
+ output = Bitcoin::P::TxOut.new(0, '')
789
+ tx.add_in(input)
790
+ tx.add_out(output)
791
+ Bitcoin::P::Tx.new(tx.to_payload)
792
+ end
793
+
794
+ # essentially DoTest() from script_tests.cpp
795
+ def run_script_test(script_sig_str, script_pk_str, opts={})
796
+ script_sig = Bitcoin::Script.from_string(script_sig_str)
797
+ script_pk = Bitcoin::Script.from_string(script_pk_str)
798
+ tx_credit = build_crediting_tx(script_pk.raw)
799
+ tx = build_spending_tx(script_sig.raw, tx_credit)
800
+ tx.verify_input_signature(0, tx_credit, Time.now.to_i, opts)
801
+ end
802
+
803
+ it 'overly long signature fails with DERSIG passes without' do
804
+ script_sig = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
805
+ script_pk = "0 OP_CHECKSIG OP_NOT"
806
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
807
+ run_script_test(script_sig, script_pk).should == true
808
+ end
809
+
810
+ it 'missing S fails with DERSIG passes without' do
811
+ script_sig = "3022022000000000000000000000000000000000000000000000000000000000000000000"
812
+ script_pk = "0 OP_CHECKSIG OP_NOT"
813
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
814
+ run_script_test(script_sig, script_pk).should == true
815
+ end
816
+
817
+ it 'S with invalid fails with DERSIG passes without' do
818
+ script_sig = "3024021077777777777777777777777777777777020a7777777777777777777777777777777701"
819
+ script_pk = "0 OP_CHECKSIG OP_NOT"
820
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
821
+ run_script_test(script_sig, script_pk).should == true
822
+ end
823
+
824
+ it 'non-integer R fails with DERSIG passes without' do
825
+ script_sig = "302403107777777777777777777777777777777702107777777777777777777777777777777701"
826
+ script_pk = "0 OP_CHECKSIG OP_NOT"
827
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
828
+ run_script_test(script_sig, script_pk).should == true
829
+ end
830
+
831
+ it 'non-integer S fails with DERSIG passes without' do
832
+ script_sig = "302402107777777777777777777777777777777703107777777777777777777777777777777701"
833
+ script_pk = "0 OP_CHECKSIG OP_NOT"
834
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
835
+ run_script_test(script_sig, script_pk).should == true
836
+ end
837
+
838
+ it 'zero length R fails with DERSIG passes without' do
839
+ script_sig = "3014020002107777777777777777777777777777777701"
840
+ script_pk = "0 OP_CHECKSIG OP_NOT"
841
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
842
+ run_script_test(script_sig, script_pk).should == true
843
+ end
844
+
845
+ it 'zero length S fails with DERSIG passes without' do
846
+ script_sig = "3014021077777777777777777777777777777777020001"
847
+ script_pk = "0 OP_CHECKSIG OP_NOT"
848
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
849
+ run_script_test(script_sig, script_pk).should == true
850
+ end
851
+
852
+ it 'negative S fails with DERSIG passes without' do
853
+ script_sig = "302402107777777777777777777777777777777702108777777777777777777777777777777701"
854
+ script_pk = "0 OP_CHECKSIG OP_NOT"
855
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
856
+ run_script_test(script_sig, script_pk).should == true
857
+ end
858
+
859
+ # see: https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki#examples
860
+ # see also: https://github.com/bitcoin/bitcoin/pull/5713/files
861
+ P1 = "038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508"
862
+ P2 = "03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640"
863
+
864
+ # Example 1: S1' P1 CHECKSIG (fails w/ verify_dersig, passes w/o)
865
+ it 'example 1' do
866
+ script_sig = "30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201"
867
+ script_pk = "#{P1} OP_CHECKSIG"
868
+ run_script_test(script_sig, script_pk).should == true
869
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
870
+ end
871
+
872
+ # Example 2: S1' P1 CHECKSIG NOT (fails with either)
873
+ it 'example 2' do
874
+ script_sig = "304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01"
875
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
876
+ run_script_test(script_sig, script_pk).should == false
877
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
878
+ end
879
+
880
+ # Example 3: F P1 CHECKSIG fails (fails with either)
881
+ it 'example 3' do
882
+ script_sig = "0"
883
+ script_pk = "#{P1} OP_CHECKSIG"
884
+ run_script_test(script_sig, script_pk).should == false
885
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
886
+ end
887
+
888
+ # Example 4: F P1 CHECKSIG NOT (passes with either)
889
+ it 'example 4' do
890
+ script_sig = "0"
891
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
892
+ run_script_test(script_sig, script_pk).should == true
893
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == true
894
+ end
895
+
896
+ # Example 5: F' P1 CHECKSIG (fails with either)
897
+ it 'example 5' do
898
+ script_sig = "1"
899
+ script_pk = "#{P1} OP_CHECKSIG"
900
+ run_script_test(script_sig, script_pk).should == false
901
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
902
+ end
903
+
904
+ # Example 6: F' P1 CHECKSIG NOT (fails w/verify_dersig, passes w/o)
905
+ it 'example 6' do
906
+ script_sig = "1"
907
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
908
+ run_script_test(script_sig, script_pk).should == true
909
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
910
+ end
911
+
912
+ # Example 7: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG (fails w/verify_dersig, passes w/o)
913
+ it 'example 7' do
914
+ s1 = "30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501"
915
+ s2 = "304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01"
916
+ script_sig = "0 #{s1} #{s2}"
917
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
918
+ run_script_test(script_sig, script_pk).should == true
919
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
920
+ end
921
+
922
+ # Example 8: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG NOT (fails for either)
923
+ it 'example 8' do
924
+ s1 = "30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601"
925
+ s2 = "3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801"
926
+ script_sig = "0 #{s1} #{s2}"
927
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
928
+ run_script_test(script_sig, script_pk).should == false
929
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
930
+ end
931
+
932
+ # Example 9: 0 F S2' 2 P1 P2 2 CHECKMULTISIG fails (fails for either)
933
+ it 'example 9' do
934
+ s1 = "0"
935
+ s2 = "3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01"
936
+ script_sig = "0 #{s1} #{s2}"
937
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
938
+ run_script_test(script_sig, script_pk).should == false
939
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
940
+ end
941
+
942
+ # Example 10: 0 F S2' 2 P1 P2 2 CHECKMULTISIG NOT (fails w/verify_dersig, passes w/o)
943
+ it 'example 10' do
944
+ s1 = "0"
945
+ s2 = "30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501"
946
+ script_sig = "0 #{s1} #{s2}"
947
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
948
+ run_script_test(script_sig, script_pk).should == true
949
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
950
+ end
951
+
952
+ # Example 11: 0 S1' F 2 P1 P2 2 CHECKMULTISIG (fails for either)
953
+ it 'example 11' do
954
+ s1 = "30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501"
955
+ s2 = "0"
956
+ script_sig = "0 #{s1} #{s2}"
957
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
958
+ run_script_test(script_sig, script_pk).should == false
959
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
960
+ end
961
+
962
+ # Example 12: 0 S1' F 2 P1 P2 2 CHECKMULTISIG NOT (passes for either)
963
+ it 'example 12' do
964
+ s1 = "30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601"
965
+ s2 = "0"
966
+ script_sig = "0 #{s1} #{s2}"
967
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
968
+ run_script_test(script_sig, script_pk).should == true
969
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == true
970
+ end
971
+ end