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,47 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+
6
+ describe 'Bitcoin::Protocol::TxIn' do
7
+ describe '#initialize without specifying script_sig_length and script_sig' do
8
+ it 'still creates a serializable TxIn' do
9
+ prev_tx = Bitcoin::Protocol::Tx.new(
10
+ fixtures_file('rawtx-01.bin')
11
+ )
12
+ tx_in = Bitcoin::Protocol::TxIn.new(prev_tx.binary_hash, 0)
13
+ tx_in.to_payload
14
+ end
15
+ end
16
+
17
+ it 'should compare txins' do
18
+ i1 = Bitcoin::Protocol::Tx.new(
19
+ fixtures_file('rawtx-01.bin')
20
+ ).in[0]
21
+ i11 = Bitcoin::Protocol::TxIn.new(
22
+ i1.prev_out, i1.prev_out_index, i1.script_sig_length, i1.script_sig
23
+ )
24
+ i2 = Bitcoin::Protocol::Tx.new(fixtures_file('rawtx-02.bin')).in[0]
25
+
26
+ expect(i1).to eq(i1)
27
+ expect(i1).to eq(i11)
28
+ expect(i1).not_to be_nil
29
+ expect(i1).not_to eq(i2)
30
+ end
31
+
32
+ it 'should be final only when sequence == 0xffffffff' do
33
+ txin = Bitcoin::Protocol::TxIn.new
34
+ expect(txin.final?).to be true
35
+ expect(txin.sequence)
36
+ .to eq(Bitcoin::Protocol::TxIn::DEFAULT_SEQUENCE)
37
+
38
+ txin.sequence = "\x01\x00\x00\x00"
39
+ expect(txin.final?).to be false
40
+
41
+ txin.sequence = "\x00\x00\x00\x00"
42
+ expect(txin.final?).to be false
43
+
44
+ txin.sequence = "\xff\xff\xff\xff"
45
+ expect(txin.final?).to be true
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+
6
+ describe Bitcoin::Protocol::TxOut do
7
+ it '#initialize without specifying script_sig_length' do
8
+ key = Bitcoin::Key.generate
9
+ tx_out = Bitcoin::Protocol::TxOut.new(
10
+ 12_345,
11
+ Bitcoin::Script.from_string(
12
+ "OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG"
13
+ ).to_payload
14
+ )
15
+
16
+ tx_out.to_payload
17
+ end
18
+
19
+ it 'should compare txouts' do
20
+ o1 = Bitcoin::Protocol::Tx.new(fixtures_file('rawtx-01.bin')).out[0]
21
+ o11 = Bitcoin::Protocol::TxOut.new(o1.value, o1.pk_script)
22
+ o2 = Bitcoin::Protocol::Tx.new(fixtures_file('rawtx-02.bin')).out[0]
23
+
24
+ expect(o1).to eq(o1)
25
+ expect(o1).to eq(o11)
26
+ expect(o1).not_to eq(o2)
27
+ expect(o1).not_to be_nil
28
+ end
29
+
30
+ it 'should update parsed script cache on script change' do
31
+ out = Bitcoin::Protocol::TxOut.new(123, 'abc')
32
+ parsed = out.parsed_script
33
+ out.pk_script = 'def'
34
+ expect(out.parsed_script).not_to eq(parsed)
35
+ end
36
+ end
@@ -0,0 +1,121 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require 'spec_helper'
5
+
6
+ describe 'Bitcoin::Protocol::Parser (version)' do
7
+ # Mock interface
8
+ class VersionHandler < Bitcoin::Protocol::Handler
9
+ attr_reader :pkt
10
+
11
+ def on_version(pkt)
12
+ @pkt = pkt
13
+ end
14
+ end
15
+
16
+ let(:handler) { VersionHandler.new }
17
+
18
+ it 'parses version packets' do
19
+ pkt = Bitcoin::Protocol.pkt(
20
+ 'version',
21
+ [
22
+ '60ea00000100000000000000b3c1424f00000000010000000000000000000000000' \
23
+ '000000000ffff7f000001e1ca010000000000000000000000000000000000ffff7f' \
24
+ '000001479d9525d0c7b30688ae122f626974636f696e2d71743a302e362e302f82b' \
25
+ '60000'
26
+ ].pack('H*')
27
+ )
28
+
29
+ parser = Bitcoin::Protocol::Parser.new(handler)
30
+ expect(parser.parse(pkt + 'AAAA')).to eq('AAAA')
31
+
32
+ pkt = handler.pkt
33
+ expect(pkt.fields)
34
+ .to eq(version: 60_000,
35
+ services: Bitcoin::Protocol::Version::NODE_NETWORK,
36
+ time: 1_329_775_027,
37
+ from: '127.0.0.1:18333',
38
+ to: '127.0.0.1:57802',
39
+ nonce: 12_576_309_328_653_329_813,
40
+ user_agent: '/bitcoin-qt:0.6.0/',
41
+ last_block: 46_722,
42
+ relay: true)
43
+
44
+ pkt = [
45
+ 'f9 be b4 d9 76 65 72 73 69 6f 6e 00 00 00 00 00 55 00 00 00 a4 c2 08 ' \
46
+ 'cb 40 9c 00 00 01 00 00 00 00 00 00 00 10 42 c9 4e 00 00 00 00 01 00 ' \
47
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff 7f 00 00 01 04 ' \
48
+ 'd2 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff 7f 00 ' \
49
+ '00 01 47 9d 4b b8 bb 21 ae d7 f0 71 00 fa 00 00 00'.split(' ').join
50
+ ].pack('H*')
51
+
52
+ handler = VersionHandler.new
53
+ parser = Bitcoin::Protocol::Parser.new(handler)
54
+ expect(parser.parse(pkt + 'AAAA')).to eq('AAAA')
55
+
56
+ pkt = handler.pkt
57
+ expect(pkt.fields)
58
+ .to eq(version: 40_000,
59
+ services: Bitcoin::Protocol::Version::NODE_NETWORK,
60
+ time: 1_321_812_496,
61
+ from: '127.0.0.1:18333',
62
+ to: '127.0.0.1:1234',
63
+ nonce: 8_210_299_263_586_646_091,
64
+ user_agent: '',
65
+ last_block: 250,
66
+ relay: true)
67
+ end
68
+
69
+ it 'creates version packets' do
70
+ version = Bitcoin::Protocol::Version.new(
71
+ time: 1_337,
72
+ from: '127.0.0.1:8333',
73
+ to: '127.0.0.1:1234',
74
+ nonce: 123,
75
+ last_block: 188_617
76
+ )
77
+
78
+ handler = VersionHandler.new
79
+ parser = Bitcoin::Protocol::Parser.new(handler)
80
+ parser.parse(version.to_pkt)
81
+
82
+ pkt = handler.pkt
83
+ expect(pkt.fields)
84
+ .to eq(version: Bitcoin.network[:protocol_version],
85
+ services: Bitcoin::Protocol::Version::NODE_NETWORK,
86
+ time: 1_337,
87
+ to: '127.0.0.1:8333',
88
+ from: '127.0.0.1:1234',
89
+ nonce: 123,
90
+ user_agent: "/bitcoin-ruby:#{Bitcoin::VERSION}/",
91
+ last_block: 188_617,
92
+ relay: true)
93
+ end
94
+
95
+ # check that we support sending and receiving of the BIP0037 fRelay flag
96
+ it 'creates spv enabled version packets' do
97
+ version = Bitcoin::Protocol::Version.new(
98
+ time: 1_337,
99
+ from: '127.0.0.1:8333',
100
+ to: '127.0.0.1:1234',
101
+ nonce: 123,
102
+ last_block: 188_617,
103
+ relay: false
104
+ )
105
+
106
+ parser = Bitcoin::Protocol::Parser.new(handler)
107
+ parser.parse(version.to_pkt)
108
+
109
+ pkt = handler.pkt
110
+ expect(pkt.fields)
111
+ .to eq(version: Bitcoin.network[:protocol_version],
112
+ services: Bitcoin::Protocol::Version::NODE_NETWORK,
113
+ time: 1_337,
114
+ to: '127.0.0.1:8333',
115
+ from: '127.0.0.1:1234',
116
+ nonce: 123,
117
+ user_agent: "/bitcoin-ruby:#{Bitcoin::VERSION}/",
118
+ last_block: 188_617,
119
+ relay: false)
120
+ end
121
+ end
@@ -0,0 +1,864 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Bitcoin::Script do
6
+ # Re-open script class
7
+ module Bitcoin
8
+ # Add accessors for private member variables.
9
+ class Script
10
+ attr_writer :stack
11
+ attr_accessor :stack_alt
12
+ end
13
+ end
14
+
15
+ let(:script) { Bitcoin::Script.new('') }
16
+
17
+ # Invoke the given operation on the initial stack provided.
18
+ #
19
+ # @param operation [String,Symbol] name of the operation to be performed.
20
+ # @param stack [Array<String>] stack state prior to operation.
21
+ # @return [Array<String>] stack state after the operation.
22
+ def op(operation, stack)
23
+ script.stack = stack
24
+ script.send("op_#{operation}")
25
+ script.stack
26
+ end
27
+
28
+ # Run a script and check if result matches the hash provided.
29
+ #
30
+ # @param string [String] text script to be run.
31
+ # @param hash [String] data expected to have been signed by key.
32
+ # @return [Boolean] true if script ran and verified successfully, false
33
+ # otherwise.
34
+ def run_script(string, hash)
35
+ script = Bitcoin::Script.from_string(string)
36
+ script.run do |pk, sig, _|
37
+ begin
38
+ k = Bitcoin::Key.new(nil, pk.unpack('H*')[0])
39
+ k && k.verify(hash, sig)
40
+ rescue StandardError
41
+ false
42
+ end
43
+ end == true
44
+ end
45
+
46
+ it 'should do OP_NOP' do
47
+ expect(op(:nop, ['foobar'])).to eq(['foobar'])
48
+ end
49
+
50
+ it 'should do OP_DUP' do
51
+ expect(op(:dup, ['foobar'])).to eq(%w[foobar foobar])
52
+ end
53
+
54
+ it 'should do OP_SHA256' do
55
+ expect(op(:sha256, ['foobar']))
56
+ .to eq(
57
+ [['c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2'].pack('H*')]
58
+ )
59
+ end
60
+
61
+ it 'should do OP_SHA1' do
62
+ expect(op(:sha1, ['foobar']))
63
+ .to eq([['8843d7f92416211de9ebb963ff4ce28125932878'].pack('H*')])
64
+ end
65
+
66
+ it 'should do OP_HASH160' do
67
+ expect(op(:hash160, ['foobar']))
68
+ .to eq([['f6c97547d73156abb300ae059905c4acaadd09dd'].pack('H*')])
69
+ end
70
+
71
+ it 'should do OP_RIPEMD160' do
72
+ expect(op(:ripemd160, ['foobar']))
73
+ .to eq([['a06e327ea7388c18e4740e350ed4e60f2e04fc41'].pack('H*')])
74
+ end
75
+
76
+ it 'should do OP_HASH256' do
77
+ expect(op(:hash256, ['foobar']))
78
+ .to eq(
79
+ [['3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda1'].pack('H*')]
80
+ )
81
+ end
82
+
83
+ it 'should do OP_TOALTSTACK' do
84
+ expect(op(:toaltstack, ['foobar'])).to be_empty
85
+ expect(script.stack_alt).to eq(['foobar'])
86
+ end
87
+
88
+ it 'should do OP_FROMALTSTACK' do
89
+ script.instance_eval { @stack = [] }
90
+ script.instance_eval { @stack_alt = ['foo'] }
91
+ script.op_fromaltstack
92
+ expect(script.stack).to eq(['foo'])
93
+ expect(script.stack_alt).to be_empty
94
+ end
95
+
96
+ it 'should do OP_TUCK' do
97
+ expect(op(:tuck, %w[foobar foo bar])).to eq(%w[foobar bar foo bar])
98
+ end
99
+
100
+ it 'should do OP_SWAP' do
101
+ expect(op(:swap, %w[foo bar])).to eq(%w[bar foo])
102
+ end
103
+
104
+ it 'should do OP_BOOLAND' do
105
+ expect(op(:booland, [0, 0])).to eq([0])
106
+ expect(op(:booland, [0, 1])).to eq([0])
107
+ expect(op(:booland, [1, 0])).to eq([0])
108
+ expect(op(:booland, [1, 1])).to eq([1])
109
+ end
110
+
111
+ it 'should do OP_ADD' do
112
+ expect(op(:add, [0, 1])).to eq([1])
113
+ expect(op(:add, [3, 4])).to eq([7])
114
+ expect(op(:add, [5, -4])).to eq([1])
115
+ end
116
+
117
+ it 'should do OP_SUB' do
118
+ expect(op(:sub, [3, 2])).to eq([1])
119
+ expect(op(:sub, [9, 1])).to eq([8])
120
+ expect(op(:sub, [1, 3])).to eq([-2])
121
+ end
122
+
123
+ it 'should do OP_GREATERTHANOREQUAL' do
124
+ expect(op(:greaterthanorequal, [2, 1])).to eq([1])
125
+ expect(op(:greaterthanorequal, [2, 2])).to eq([1])
126
+ expect(op(:greaterthanorequal, [1, 2])).to eq([0])
127
+ end
128
+
129
+ it 'should do OP_DROP' do
130
+ expect(op(:drop, ['foo'])).to be_empty
131
+ end
132
+
133
+ it 'should do OP_EQUAL' do
134
+ expect(op(:equal, [1, 2])).to eq([0])
135
+ expect(op(:equal, [1, 1])).to eq([1])
136
+ end
137
+
138
+ it 'should do OP_VERIFY' do
139
+ expect(op(:verify, [1])).to be_empty
140
+ expect(op(:verify, [0])).to eq([0])
141
+ end
142
+
143
+ it 'should do OP_EQUALVERIFY' do
144
+ expect(op(:equalverify, [1, 2])).to eq([0])
145
+ expect(script).to be_invalid
146
+ expect(op(:equalverify, [1, 1])).to be_empty
147
+ expect(script).not_to be_invalid
148
+ end
149
+
150
+ it 'should do OP_0' do
151
+ expect(op('0', ['foo'])).to eq(['foo', ''])
152
+ end
153
+
154
+ it 'should do OP_1' do
155
+ expect(op('1', ['foo'])).to eq(['foo', 1])
156
+ end
157
+
158
+ it 'should do OP_MIN' do
159
+ [
160
+ [[4, 5], 4],
161
+ [[5, 4], 4],
162
+ [[4, 4], 4],
163
+ [["\x04", "\x05"], 4],
164
+ [[1, 0], 0],
165
+ [[0, 1], 0],
166
+ [[-1, 0], -1],
167
+ [[0, -2_147_483_647], -2_147_483_647]
168
+ ].each do |stack, expected|
169
+ expect(op(:min, stack)).to eq([expected])
170
+ end
171
+ end
172
+
173
+ it 'should do OP_MAX' do
174
+ [
175
+ [[4, 5], 5],
176
+ [[5, 4], 5],
177
+ [[4, 4], 4],
178
+ [["\x04", "\x05"], 5],
179
+ [[2_147_483_647, 0], 2_147_483_647],
180
+ [[0, 100], 100],
181
+ [[-100, 0], 0],
182
+ [[0, -2_147_483_647], 0]
183
+ ].each do |stack, expected|
184
+ expect(op(:max, stack)).to eq([expected])
185
+ end
186
+ end
187
+
188
+ it 'should do op_2over' do
189
+ expect(op('2over', [1, 2, 3, 4])).to eq([1, 2, 3, 4, 1, 2])
190
+ end
191
+
192
+ it 'should do op_2swap' do
193
+ expect(op('2swap', [1, 2, 3, 4])).to eq([3, 4, 1, 2])
194
+ end
195
+
196
+ it 'should do op_ifdup' do
197
+ expect(op(:ifdup, [1])).to eq([1, 1])
198
+ expect(op(:ifdup, ['a'])).to eq(%w[a a])
199
+ expect(op(:ifdup, [0])).to eq([0])
200
+ end
201
+
202
+ it 'should do op_1negate' do
203
+ expect(op('1negate', [])).to eq([-1])
204
+ end
205
+
206
+ it 'should do op_depth' do
207
+ expect(op(:depth, [])).to eq([0])
208
+ expect(op(:depth, [1, 2, 3])).to eq([1, 2, 3, 3])
209
+ end
210
+
211
+ it 'should do op_boolor' do
212
+ [
213
+ [[1, 1], 1],
214
+ [[1, 0], 1],
215
+ [[0, 1], 1],
216
+ [[0, 0], 0],
217
+ [[16, 17], 1],
218
+ [[-1, 0], 1]
219
+ # [[1 ], :invalid],
220
+ ].each do |stack, expected|
221
+ expect(op(:boolor, stack)).to eq([expected])
222
+ end
223
+ end
224
+
225
+ it 'should do op_lessthan' do
226
+ [
227
+ [[11, 10], 0],
228
+ [[4, 4], 0],
229
+ [[10, 11], 1],
230
+ [[-11, 11], 1],
231
+ [[-11, -10], 1],
232
+ [[-1, 0], 1]
233
+ ].each do |stack, expected|
234
+ expect(op(:lessthan, stack)).to eq([expected])
235
+ end
236
+ end
237
+
238
+ it 'should do op_lessthanorequal' do
239
+ [
240
+ [[11, 10], 0],
241
+ [[4, 4], 1],
242
+ [[10, 11], 1],
243
+ [[-11, 11], 1],
244
+ [[-11, -10], 1],
245
+ [[-1, 0], 1]
246
+ ].each do |stack, expected|
247
+ expect(op(:lessthanorequal, stack)).to eq([expected])
248
+ end
249
+ end
250
+
251
+ it 'should do op_greaterthan' do
252
+ [
253
+ [[11, 10], 1],
254
+ [[4, 4], 0],
255
+ [[10, 11], 0],
256
+ [[-11, 11], 0],
257
+ [[-11, -10], 0],
258
+ [[-1, 0], 0],
259
+ [[1, 0], 1]
260
+ ].each do |stack, expected|
261
+ expect(op(:greaterthan, stack)).to eq([expected])
262
+ end
263
+ end
264
+
265
+ it 'should do op_greaterthanorequal' do
266
+ [
267
+ [[11, 10], 1],
268
+ [[4, 4], 1],
269
+ [[10, 11], 0],
270
+ [[-11, 11], 0],
271
+ [[-11, -10], 0],
272
+ [[-1, 0], 0],
273
+ [[1, 0], 1],
274
+ [[0, 0], 1]
275
+ ].each do |stack, expected|
276
+ expect(op(:greaterthanorequal, stack)).to eq([expected])
277
+ end
278
+ end
279
+
280
+ it 'should do op_not' do
281
+ expect(op(:not, [0])).to eq([1])
282
+ expect(op(:not, [1])).to eq([0])
283
+ end
284
+
285
+ it 'should do op_0notequal' do
286
+ [
287
+ [[0], 0],
288
+ [[1], 1],
289
+ [[111], 1],
290
+ [[-111], 1]
291
+ ].each do |stack, expected|
292
+ expect(op('0notequal', stack)).to eq([expected])
293
+ end
294
+ end
295
+
296
+ it 'should do op_abs' do
297
+ [
298
+ [[0], 0],
299
+ [[16], 16],
300
+ [[-16], 16],
301
+ [[-1], 1]
302
+ ].each do |stack, expected|
303
+ expect(op(:abs, stack)).to eq([expected])
304
+ end
305
+ end
306
+
307
+ it 'should do op_2div' do
308
+ expect(op('2div', [2])).to eq([1])
309
+ expect(op('2div', [10])).to eq([5])
310
+ expect(op('2div', [-10])).to eq([-5])
311
+ end
312
+
313
+ it 'should do op_2mul' do
314
+ expect(op('2mul', [2])).to eq([4])
315
+ expect(op('2mul', [10])).to eq([20])
316
+ expect(op('2mul', [-10])).to eq([-20])
317
+ end
318
+
319
+ it 'should do op_1add' do
320
+ expect(op('1add', [2])).to eq([3])
321
+ expect(op('1add', [10])).to eq([11])
322
+ expect(op('1add', [-10])).to eq([-9])
323
+ end
324
+
325
+ it 'should do op_1sub' do
326
+ expect(op('1sub', [2])).to eq([1])
327
+ expect(op('1sub', [10])).to eq([9])
328
+ expect(op('1sub', [-10])).to eq([-11])
329
+ end
330
+
331
+ it 'should do op_negate' do
332
+ expect(op('negate', [-2])).to eq([2])
333
+ expect(op('negate', [2])).to eq([-2])
334
+ expect(op('negate', [0])).to eq([0])
335
+ end
336
+
337
+ it 'should do op_within' do
338
+ [
339
+ [[0, 0, 1], 1],
340
+ [[1, 0, 1], 0],
341
+ [[0, -2_147_483_647, 2_147_483_647], 1],
342
+ [[-1, -100, 100], 1],
343
+ [[11, -100, 100], 1],
344
+ [[-2_147_483_647, -100, 100], 0],
345
+ [[2_147_483_647, -100, 100], 0],
346
+ [[-1, -1, 0], 1]
347
+ ].each do |stack, expected|
348
+ expect(op(:within, stack)).to eq([expected])
349
+ end
350
+ end
351
+
352
+ it 'should do op_numequal' do
353
+ [
354
+ [[0, 0], 1],
355
+ [[0, 1], 0]
356
+ ].each do |stack, expected|
357
+ expect(op(:numequal, stack)).to eq([expected])
358
+ end
359
+ end
360
+
361
+ it 'should do op_numequalverify' do
362
+ [
363
+ [[0, 0], []],
364
+ [[0, 1], [0]]
365
+ ].each do |stack, expected|
366
+ expect(op(:numequalverify, stack)).to eq(expected)
367
+ end
368
+ end
369
+
370
+ it 'should do op_numnotequal' do
371
+ [
372
+ [[0, 0], 0],
373
+ [[0, 1], 1]
374
+ ].each do |stack, expected|
375
+ expect(op(:numnotequal, stack)).to eq([expected])
376
+ end
377
+ end
378
+
379
+ it 'should do op_over' do
380
+ [
381
+ [[1, 0], [1, 0, 1]],
382
+ [[-1, 1], [-1, 1, -1]],
383
+ [[1], [1]]
384
+ ].each do |stack, expected|
385
+ expect(op(:over, stack)).to eq(expected)
386
+ end
387
+ end
388
+
389
+ it 'should do op_pick' do
390
+ [
391
+ [[1, 0, 0, 0, 3], [1, 0, 0, 0, 1]],
392
+ [[1, 0], [1, 1]]
393
+ ].each do |stack, expected|
394
+ expect(op(:pick, stack)).to eq(expected)
395
+ expect(script).not_to be_invalid
396
+ end
397
+
398
+ [
399
+ [[0], [0]],
400
+ [[-1], [-1]]
401
+ ].each do |stack, expected|
402
+ expect(op(:pick, stack)).to eq(expected)
403
+ expect(script).to be_invalid
404
+ end
405
+ end
406
+
407
+ it 'should do op_roll' do
408
+ [
409
+ [[1, 0, 0, 0, 3], [0, 0, 0, 1]],
410
+ [[1, 0], [1]]
411
+ ].each do |stack, expected|
412
+ expect(op(:roll, stack)).to eq(expected)
413
+ expect(script).not_to be_invalid
414
+ end
415
+
416
+ [
417
+ [[0], [0]],
418
+ [[-1], [-1]]
419
+ ].each do |stack, expected|
420
+ expect(op(:roll, stack)).to eq(expected)
421
+ expect(script).to be_invalid
422
+ end
423
+ end
424
+
425
+ it 'should do op_2rot' do
426
+ expect(op('2rot', [-1, 0, 1, 2, 3, 4, 5, 6]))
427
+ .to eq([-1, 0, 3, 4, 5, 6, 1, 2])
428
+ expect(script).not_to be_invalid
429
+
430
+ expect(op('2rot', [2, 3, 4, 5, 6])).to eq([2, 3, 4, 5, 6])
431
+ expect(script).to be_invalid
432
+ end
433
+
434
+ it 'should do op_rot' do
435
+ expect(op(:rot, [22, 21, 20])).to eq([21, 20, 22])
436
+ expect(op(:rot, [21, 20])).to eq([21, 20])
437
+ end
438
+
439
+ it 'should do op_2drop' do
440
+ expect(op('2drop', [1, 2, 3])).to eq([1])
441
+ expect(op('2drop', [2, 3])).to be_empty
442
+ end
443
+
444
+ it 'should do op_2dup' do
445
+ expect(op('2dup', [2, 3])).to eq([2, 3, 2, 3])
446
+ expect(op('2dup', [3])).to eq([3])
447
+ end
448
+
449
+ it 'should do op_3dup' do
450
+ expect(op('3dup', [1, 2, 3])).to eq([1, 2, 3, 1, 2, 3])
451
+ expect(op('3dup', [2, 3])).to eq([2, 3])
452
+ expect(op('3dup', [3])).to eq([3])
453
+ end
454
+
455
+ it 'should do op_nip' do
456
+ expect(op(:nip, [1, 2])).to eq([2])
457
+ expect(op(:nip, [1, 2, 3])).to eq([1, 3])
458
+ end
459
+
460
+ it 'should do op_size' do
461
+ [
462
+ [[0], [0, 0]],
463
+ [[1], [1, 1]],
464
+ [[127], [127, 1]],
465
+ [[128], [128, 2]],
466
+ [[32_767], [32_767, 2]],
467
+ [[32_768], [32_768, 3]],
468
+ [[8_388_607], [8_388_607, 3]],
469
+ [[8_388_608], [8_388_608, 4]],
470
+ [[2_147_483_647], [2_147_483_647, 4]],
471
+ [[2_147_483_648], [2_147_483_648, 5]],
472
+ [[-1], [-1, 1]],
473
+ [[-127], [-127, 1]],
474
+ [[-128], [-128, 2]],
475
+ [[-32_767], [-32_767, 2]],
476
+ [[-32_768], [-32_768, 3]],
477
+ [[-8_388_607], [-8_388_607, 3]],
478
+ [[-8_388_608], [-8_388_608, 4]],
479
+ [[-2_147_483_647], [-2_147_483_647, 4]],
480
+ [[-2_147_483_648], [-2_147_483_648, 5]],
481
+ [['abcdefghijklmnopqrstuvwxyz'], ['abcdefghijklmnopqrstuvwxyz', 26]]
482
+ ].each do |stack, expected|
483
+ expect(op(:size, stack)).to eq(expected)
484
+ end
485
+ end
486
+
487
+ it 'should do if/notif/else/end' do
488
+ [
489
+ '1 1 OP_IF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ENDIF',
490
+ '1 0 OP_IF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ENDIF',
491
+ '1 1 OP_IF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ELSE OP_IF 0 OP_ELSE 1 OP_ENDIF OP_ENDIF',
492
+ '0 0 OP_IF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ELSE OP_IF 0 OP_ELSE 1 OP_ENDIF OP_ENDIF',
493
+ '1 1 OP_NOTIF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ENDIF',
494
+ '1 0 OP_NOTIF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ENDIF',
495
+ '1 0 OP_NOTIF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ELSE OP_IF 0 OP_ELSE 1 OP_ENDIF OP_ENDIF',
496
+ '0 1 OP_NOTIF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ELSE OP_IF 0 OP_ELSE 1 OP_ENDIF OP_ENDIF',
497
+ '0 OP_IF OP_RETURN OP_ENDIF 1',
498
+ '1 OP_IF 1 OP_ENDIF',
499
+ '0 OP_IF 50 OP_ENDIF 1',
500
+ '0 OP_IF OP_VER OP_ELSE 1 OP_ENDIF',
501
+ '0 OP_IF 50 40 OP_ELSE 1 OP_ENDIF',
502
+ '1 OP_DUP OP_IF OP_ENDIF',
503
+ '1 OP_IF 1 OP_ENDIF',
504
+ '1 OP_DUP OP_IF OP_ELSE OP_ENDIF',
505
+ '1 OP_IF 1 OP_ELSE OP_ENDIF',
506
+ '0 OP_IF OP_ELSE 1 OP_ENDIF',
507
+ 'beef OP_IF 1 OP_ELSE 0 OP_ENDIF',
508
+ '0 OP_NOTIF 1 OP_ELSE 0 OP_ENDIF',
509
+ 'beef OP_NOTIF 0 OP_ELSE 1 OP_ENDIF'
510
+ ].each do |script|
511
+ expect(Bitcoin::Script.from_string(script).run).to be true
512
+ end
513
+ end
514
+
515
+ it 'should do OP_CHECKSIG' do
516
+ script.stack = %w[bar foo]
517
+ verify_callback = proc do |pubkey, signature, type|
518
+ expect(pubkey).to eq('foo')
519
+ expect(signature).to eq('ba')
520
+ expect(type).to eq('r'.ord)
521
+ true
522
+ end
523
+ expect(script.op_checksig(verify_callback)).to eq([1])
524
+
525
+ script.stack = %w[bar foo]
526
+ verify_callback = proc { true }
527
+ expect(script.op_checksig(verify_callback)).to eq([1])
528
+
529
+ script.stack = %w[bar foo]
530
+ verify_callback = proc { false }
531
+ expect(script.op_checksig(verify_callback)).to eq([0])
532
+
533
+ script.stack = ['foo']
534
+ verify_callback = proc { false }
535
+ expect(script.op_checksig(verify_callback)).to be_nil
536
+
537
+ pubkey = [
538
+ '04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552' \
539
+ 'e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3'
540
+ ].pack('H*')
541
+ signature = [
542
+ '304402202c2fb840b527326f9bbc7ce68c6c196a368a38864b5a47681352c4b2f416f' \
543
+ '7ed02205c4801cfa8aed205f26c7122ab5a5934fcf7a2f038fd130cdd8bcc56bdde0a00'
544
+ ].pack('H*')
545
+ hash_type = [1].pack('C')
546
+ signature_data = [
547
+ '20245059adb84acaf1aa942b5d8a586da7ba76f17ecb5de4e7543e1ce1b94bc3'
548
+ ].pack('H*')
549
+
550
+ script.stack = [signature + hash_type, pubkey]
551
+ verify_callback = proc do |pub, sig, hash_t|
552
+ expect(pub).to eq(pubkey)
553
+ expect(sig).to eq(signature)
554
+ expect(hash_t).to eq(1)
555
+
556
+ hash = signature_data
557
+ Bitcoin.verify_signature(hash, sig, pub.unpack('H*')[0])
558
+ end
559
+ expect(script.op_checksig(verify_callback)).to eq([1])
560
+
561
+ script.stack = [signature + hash_type, 1]
562
+ verify_callback = proc do |pub, _, _|
563
+ pub.is_a?(String)
564
+ end
565
+ expect(script.op_checksig(verify_callback)).to eq([1])
566
+
567
+ script.stack = [signature + hash_type, pubkey]
568
+ verify_callback = proc do |pub, sig, _|
569
+ hash = 'foo' + signature_data
570
+ Bitcoin.verify_signature(hash, sig, pub.unpack('H*')[0])
571
+ end
572
+ expect(script.op_checksig(verify_callback)).to eq([0])
573
+
574
+ script.stack = [signature + hash_type, pubkey]
575
+ verify_callback = proc do |pub, _, _|
576
+ hash = signature_data
577
+ Bitcoin.verify_signature(hash, 'foo', pub.unpack('H*')[0])
578
+ end
579
+ expect(script.op_checksig(verify_callback)).to eq([0])
580
+
581
+ script.stack = [signature + hash_type, pubkey]
582
+ verify_callback = proc do |_, sig, _|
583
+ hash = signature_data
584
+ Bitcoin.verify_signature(hash, sig, 'foo')
585
+ end
586
+ expect(script.op_checksig(verify_callback)).to eq([0])
587
+
588
+ # Bitcoin::Key API
589
+ key = Bitcoin::Key.new
590
+ key.generate
591
+ signature = (key.sign('foobar') + "\x01").unpack('H*')[0]
592
+ script = Bitcoin::Script.from_string("#{signature} #{key.pub} OP_CHECKSIG")
593
+ result = script.run do |pk, sig, _|
594
+ k = Bitcoin::Key.new nil, pk.unpack('H*')[0]
595
+ k.verify('foobar', sig)
596
+ end
597
+
598
+ expect(result).to be true
599
+ expect(script.stack).to be_empty
600
+ end
601
+
602
+ it 'should do OP_CHECKMULTISIG' do
603
+ k1 = Bitcoin::Key.new
604
+ k2 = Bitcoin::Key.new
605
+ k3 = Bitcoin::Key.new
606
+ k1.generate
607
+ k2.generate
608
+ k3.generate
609
+ sig1 = (k1.sign('foobar') + "\x01").unpack('H*')[0]
610
+ sig2 = (k2.sign('foobar') + "\x01").unpack('H*')[0]
611
+ sig3 = (k3.sign('foobar') + "\x01").unpack('H*')[0]
612
+
613
+ script = "0 #{sig1} 1 #{k1.pub} 1 OP_CHECKMULTISIG"
614
+ expect(run_script(script, 'foobar')).to be true
615
+
616
+ script = "0 #{sig1} #{sig2} 2 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
617
+ expect(run_script(script, 'foobar')).to be true
618
+
619
+ script = "0 #{sig2} #{sig1} 2 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
620
+ expect(run_script(script, 'foobar')).to be false
621
+
622
+ script = "0 #{sig1} #{sig2} 2 #{k2.pub} #{k1.pub} 2 OP_CHECKMULTISIG"
623
+ expect(run_script(script, 'foobar')).to be false
624
+
625
+ script = "0 #{sig1} #{sig2} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
626
+ expect(run_script(script, 'foobar')).to be true
627
+
628
+ script = "0 #{sig2} #{sig3} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
629
+ expect(run_script(script, 'foobar')).to be true
630
+
631
+ script = "0 #{sig1} #{sig2} #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
632
+ expect(run_script(script, 'foobar')).to be true
633
+
634
+ # without OP_NOP
635
+ script = "#{sig1} #{sig2} #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 " \
636
+ 'OP_CHECKMULTISIG'
637
+ expect(run_script(script, 'foobar')).to be true
638
+
639
+ script = "0 #{sig2} 1 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
640
+ expect(run_script(script, 'foobar')).to be true
641
+
642
+ script = "0 #{sig2} OP_TRUE #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
643
+ expect(run_script(script, 'foobar')).to be true
644
+
645
+ script = "0 #{sig1} #{sig2} #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 2 OP_CHECKMULTISIG"
646
+ expect(run_script(script, 'foobar')).to be false
647
+
648
+ script = "0 #{sig1} #{sig2} #{sig3} 3 #{k2.pub} #{k3.pub} 2 OP_CHECKMULTISIG"
649
+ expect(run_script(script, 'foobar')).to be false
650
+
651
+ script = "0 #{sig1} #{sig2} #{sig3} 3 2 #{k3.pub} 2 OP_CHECKMULTISIG"
652
+ expect(run_script(script, 'foobar')).to be false
653
+
654
+ script = "0 #{sig1} #{sig2} #{sig3} 3 0 #{k3.pub} 2 OP_CHECKMULTISIG"
655
+ expect(run_script(script, 'foobar')).to be false
656
+
657
+ script = "0 #{sig1} #{sig2} 2 3 #{k2.pub} #{k3.pub} 2 OP_CHECKMULTISIG"
658
+ expect(run_script(script, 'foobar')).to be false
659
+
660
+ script = "0 #{sig1} #{sig2} 0 3 #{k2.pub} #{k3.pub} 2 OP_CHECKMULTISIG"
661
+ expect(run_script(script, 'foobar')).to be false
662
+
663
+ script = "0 #{sig2} f0f0f0f0 2 #{k1.pub} #{k2.pub} 2 OP_CHECKMULTISIG"
664
+ expect(run_script(script, 'foobar')).to be false
665
+
666
+ script = "0 afafafaf #{sig2} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
667
+ expect(run_script(script, 'foobar')).to be false
668
+
669
+ script = "0 #{sig1} f0f0f0f0 #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
670
+ expect(run_script(script, 'foobar')).to be false
671
+
672
+ script = "0 #{sig1} f0f0f0f0 #{sig3} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG OP_NOT"
673
+ expect(run_script(script, 'foobar')).to be true
674
+
675
+ script = '1 1 1 1 1 OP_CHECKMULTISIG OP_NOT'
676
+ expect(run_script(script, 'foobar')).to be true
677
+
678
+ # mainnet tx output: 514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58
679
+ script = "0 #{sig1} 1 0 #{k1.pub} OP_SWAP OP_1ADD OP_CHECKMULTISIG"
680
+ expect(run_script(script, 'foobar')).to be true
681
+ expect(Bitcoin::Script.from_string(script).get_addresses).to be_empty
682
+ expect(Bitcoin::Script.from_string(script).is_multisig?).to be false
683
+ script = "#{k1.pub} OP_SWAP OP_1ADD OP_CHECKMULTISIG"
684
+ expect(Bitcoin::Script.from_string(script).get_addresses).to be_empty
685
+ expect(Bitcoin::Script.from_string(script).is_multisig?).to be false
686
+
687
+ script = "0 #{sig2} #{sig1} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
688
+ expect(run_script(script, 'foobar')).to be false
689
+ script = "0 #{sig3} #{sig2} 2 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
690
+ expect(run_script(script, 'foobar')).to be false
691
+ script = "0 #{sig1} #{sig3} #{sig2} 3 #{k1.pub} #{k2.pub} #{k3.pub} 3 OP_CHECKMULTISIG"
692
+ expect(run_script(script, 'foobar')).to be false
693
+ end
694
+
695
+ it 'should do P2SH' do
696
+ k1 = Bitcoin::Key.new
697
+ k1.generate
698
+ sig = (k1.sign('foobar') + "\x01").unpack('H*')[0]
699
+ inner_script = Bitcoin::Script.from_string("#{k1.pub} OP_CHECKSIG").raw.unpack('H*')[0]
700
+ script_hash = Bitcoin.hash160(inner_script)
701
+ script = Bitcoin::Script.from_string(
702
+ "#{sig} #{inner_script} OP_HASH160 #{script_hash} OP_EQUAL"
703
+ )
704
+ expect(script.is_p2sh?).to be true
705
+ expect(run_script(script.to_string, 'foobar')).to be true
706
+ expect(run_script(script.to_string, 'barbaz')).to be false
707
+
708
+ script = Bitcoin::Script.from_string(
709
+ "0 #{sig} #{inner_script} OP_HASH160 #{script_hash} OP_EQUAL"
710
+ )
711
+ expect(script.is_p2sh?).to be true
712
+ expect(run_script(script.to_string, 'foobar')).to be true
713
+
714
+ script = Bitcoin::Script.from_string("OP_HASH160 #{script_hash} OP_EQUAL")
715
+ expect(script.is_p2sh?).to be true
716
+ expect(run_script(script.to_string, 'foobar')).to be false
717
+
718
+ address = '3CkxTG25waxsmd13FFgRChPuGYba3ar36B'
719
+ script = Bitcoin::Script.new(Bitcoin::Script.to_address_script(address))
720
+ expect(script.type).to eq(:p2sh)
721
+
722
+ inner_script = Bitcoin::Script.from_string('0 OP_NOT').raw.unpack('H*')[0]
723
+ script_hash = Bitcoin.hash160(inner_script)
724
+ script = Bitcoin::Script.from_string("#{inner_script} OP_HASH160 #{script_hash} OP_EQUAL")
725
+ expect(script.is_p2sh?).to be true
726
+ expect(run_script(script.to_string, 'foobar')).to be true
727
+ end
728
+
729
+ it 'should skip OP_EVAL' do
730
+ expect(Bitcoin::Script.from_string('1 OP_EVAL').to_string).to eq('1 OP_NOP1')
731
+ expect(Bitcoin::Script.from_string('1 OP_EVAL').run).to be true
732
+ expect(Bitcoin::Script.from_string('0 OP_EVAL').run).to be false
733
+ end
734
+
735
+ it 'should do testnet3 scripts' do
736
+ [
737
+ 'OP_1NEGATE OP_1NEGATE OP_ADD 82 OP_EQUAL',
738
+ '6f 1 OP_ADD 12 OP_SUB 64 OP_EQUAL',
739
+ '76:1:07 7 OP_EQUAL',
740
+ 'OP_1NEGATE e4 64 OP_WITHIN',
741
+ '0 ffffffff ffffff7f OP_WITHIN',
742
+ '6162636465666768696a6b6c6d6e6f707172737475767778797a OP_SIZE 1a OP_EQUAL',
743
+ '0 OP_IFDUP OP_DEPTH 1 OP_EQUALVERIFY 0 OP_EQUAL',
744
+ '1 OP_NOP1 OP_CHECKHASHVERIFY OP_NOP3 OP_NOP4 OP_NOP5 OP_NOP6 OP_NOP7 ' \
745
+ 'OP_NOP8 OP_NOP9 OP_NOP10 1 OP_EQUAL',
746
+ '1 OP_NOP1 OP_NOP2 OP_NOP3 OP_NOP4 OP_NOP5 OP_NOP6 OP_NOP7 OP_NOP8 ' \
747
+ 'OP_NOP9 OP_NOP10 1 OP_EQUAL',
748
+ '0 ffffffff ffffff7f OP_WITHIN',
749
+ '0:1:16 0:1:15 0:1:14 OP_ROT OP_ROT 0:1:15 OP_EQUAL',
750
+ 'ffffff7f OP_NEGATE OP_DUP OP_ADD feffffff80 OP_EQUAL',
751
+ '90 OP_ABS 90 OP_NEGATE OP_EQUAL',
752
+ '0 OP_DROP OP_DEPTH 0 OP_EQUAL',
753
+ '1 0 OP_NOTIF OP_IF 1 OP_ELSE 0 OP_ENDIF OP_ELSE OP_IF 0 OP_ELSE 1 OP_ENDIF OP_ENDIF',
754
+ '6f OP_1SUB 6e OP_EQUAL',
755
+ '13 14 OP_2DUP OP_ROT OP_EQUALVERIFY OP_EQUAL',
756
+ '10 0 11 OP_TOALTSTACK OP_DROP OP_FROMALTSTACK OP_ADD 0:1:15 OP_EQUAL',
757
+ 'ffffff7f OP_DUP OP_ADD feffffff00 OP_EQUAL',
758
+ '77:1:08 8 OP_EQUAL',
759
+ '1 OP_NOT 0 OP_EQUAL',
760
+ '0 OP_DROP OP_DEPTH 0 OP_EQUAL',
761
+ '6f 1 OP_ADD 12 OP_SUB 64 OP_EQUAL',
762
+ '0:1:0b 11 OP_EQUAL',
763
+ '13 14 OP_2DUP OP_ROT OP_EQUALVERIFY OP_EQUAL',
764
+ 'ffffff7f OP_DUP OP_ADD feffffff00 OP_EQUAL',
765
+ '0 OP_DROP OP_DEPTH 0 OP_EQUAL',
766
+ '0 ffffffff OP_MIN ffffffff OP_NUMEQUAL',
767
+ '90 OP_ABS 90 OP_NEGATE OP_EQUAL',
768
+ 'OP_1NEGATE e803 OP_ADD e703 OP_EQUAL',
769
+ '0:1:16 0:1:15 0:1:14 OP_ROT OP_ROT OP_ROT 0:1:14 OP_EQUAL',
770
+ '13 14 OP_2DUP OP_ROT OP_EQUALVERIFY OP_EQUAL',
771
+ '8b 11 OP_LESSTHANOREQUAL',
772
+ 'ffffff7f ffffffff OP_ADD 0 OP_EQUAL',
773
+ 'ffffff7f OP_NEGATE OP_DUP OP_ADD feffffff80 OP_EQUAL',
774
+ '8b 11 OP_GREATERTHANOREQUAL OP_NOT',
775
+ '0 OP_0NOTEQUAL 0 OP_EQUAL',
776
+ '2 82 OP_ADD 0 OP_EQUAL'
777
+ ].each do |script|
778
+ parsed_script = Bitcoin::Script.from_string(script)
779
+ result = parsed_script.run
780
+ expect(result).to be true
781
+ end
782
+
783
+ [
784
+ 'ffffff7f ffffff7f OP_ADD ffffff7f OP_ADD OP_TRUE'
785
+ ].each do |script|
786
+ parsed_script = Bitcoin::Script.from_string(script)
787
+ result = parsed_script.run
788
+ expect(result).to be false
789
+ end
790
+ end
791
+
792
+ it 'should do OP_VER' do
793
+ s = Bitcoin::Script.from_string('OP_VER')
794
+ s.run
795
+ expect(s).to be_invalid
796
+
797
+ s = Bitcoin::Script.from_string('1 OP_IF OP_VER 1 OP_ELSE 0 OP_ENDIF')
798
+ expect(s.run).to be false
799
+ expect(s).to be_invalid
800
+
801
+ s = Bitcoin::Script.from_string('1 OP_IF 1 OP_ELSE OP_VER 0 OP_ENDIF')
802
+ expect(s.run).to be true
803
+ expect(s).not_to be_invalid
804
+ end
805
+
806
+ it 'should not allow DISABLED_OPCODES' do
807
+ Bitcoin::Script::DISABLED_OPCODES.each do |opcode|
808
+ s = Bitcoin::Script.from_string(Bitcoin::Script::OPCODES[opcode] + ' 1')
809
+ expect(s.run).to be false
810
+ expect(s).to be_invalid
811
+
812
+ s = Bitcoin::Script.from_string(
813
+ "1 OP_IF #{Bitcoin::Script::OPCODES[opcode]} 1 OP_ELSE 1 OP_ENDIF"
814
+ )
815
+ expect(s.run).to be false
816
+ expect(s).to be_invalid
817
+
818
+ s = Bitcoin::Script.from_string(
819
+ "1 OP_IF 1 OP_ELSE #{Bitcoin::Script::OPCODES[opcode]} 1 OP_ENDIF"
820
+ )
821
+ expect(s.run).to be false
822
+ expect(s).to be_invalid
823
+ end
824
+ end
825
+
826
+ it 'check before casting and mark bad cases invalid' do
827
+ # tries to pop off an element from the empty stack here.
828
+ s = Bitcoin::Script.from_string('OP_NOT')
829
+ expect(s.run).to be false
830
+ expect(s).to be_invalid
831
+ end
832
+
833
+ it 'should do OP_CHECKSIGVERIFY and OP_CHECKMULTISIGVERIFY' do
834
+ tx1 = Bitcoin::P::Tx.new(
835
+ '0100000001a3fe4396b575690095bfc088d864aa971c99f65e2d893b48e0b26b1b60a2' \
836
+ '8754000000006a47304402201ddfc8e3f825add9f42c0ce76dc5709cf76871e7ee6c97' \
837
+ 'aae11d7db7f829b3f202201c3043515bfcf3d77845c8740ce4ccb4bda3f431da64f259' \
838
+ '6ee0ea2dfb727a5c01210328a5915165382c9b119d10d313c5781d98a7de79225f3c58' \
839
+ 'e7fa115660ba90e0ffffffff0270f305000000000017a914ca164de1946bf0146ed1f3' \
840
+ '2413df0efb0e1c730f87005d8806000000001976a91437c1d63690e00845663f3de661' \
841
+ 'fef981c08e8de588ac00000000'.htb
842
+ )
843
+ tx2 = Bitcoin::P::Tx.new(
844
+ '0100000001a1c5263304aa47f8e4e8a8dbca33e525667f7f0d84390c5a92d49eccbe5b' \
845
+ '970f00000000fde50152483045022100fbc7ccd87ad2384a4d8823d3cf36d839bb6acc' \
846
+ 'a3d80a9ed9c51c784b7bdf1e430220305fcb1660219fcc340935000aa92dd02684b763' \
847
+ '177b8a3c1be094c919af323701473044022008f66d2e31175cdefbd7461afb5f9946e5' \
848
+ 'dcb8173d1a2d3ef837f1c810695d160220250354de77b4a919b87910aa203ecec54bd1' \
849
+ '006d2dad2fcac06a54f39a9d39a101514d4f0176519c6375522103b124c48bbff7ebe1' \
850
+ '6e7bd2b2f2b561aa53791da678a73d2777cc1ca4619ab6f72103ad6bb76e00d124f07a' \
851
+ '22680e39debd4dc4bdb1aa4b893720dd05af3c50560fdd52af67529c63552103b124c4' \
852
+ '8bbff7ebe16e7bd2b2f2b561aa53791da678a73d2777cc1ca4619ab6f721025098a1d5' \
853
+ 'a338592bf1e015468ec5a8fafc1fc9217feb5cb33597f3613a2165e9210360cfabc01d' \
854
+ '52eaaeb3976a5de05ff0cfa76d0af42d3d7e1b4c233ee8a00655ed2103f571540c81fd' \
855
+ '9dbf9622ca00cfe95762143f2eab6b65150365bb34ac533160432102bc2b4be1bca32b' \
856
+ '9d97e2d6fb255504f4bc96e01aaca6e29bfa3f8bea65d8865855af672103ad6bb76e00' \
857
+ 'd124f07a22680e39debd4dc4bdb1aa4b893720dd05af3c50560fddada820a4d9338883' \
858
+ '18a23c28fb5fc67aca8530524e2074b1d185dbf5b4db4ddb0642848868685174519c63' \
859
+ '51670068000000000170f30500000000001976a914bce2fe0e49630a996cb9fe611e6b' \
860
+ '9b7d1e4dc21188acb4ff6153'.htb
861
+ )
862
+ expect(tx2.verify_input_signature(0, tx1)).to be true
863
+ end
864
+ end