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