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
@@ -2,9 +2,8 @@
2
2
 
3
3
  module Bitcoin
4
4
  module Protocol
5
-
5
+ # https://en.bitcoin.it/wiki/Protocol_documentation#block
6
6
  class Block
7
-
8
7
  BLOCK_VERSION_DEFAULT = (1 << 0)
9
8
  BLOCK_VERSION_AUXPOW = (1 << 8)
10
9
  BLOCK_VERSION_CHAIN_START = (1 << 16)
@@ -15,8 +14,10 @@ module Bitcoin
15
14
 
16
15
  # previous block hash
17
16
  attr_accessor :prev_block_hash
18
- alias :prev_block :prev_block_hash
19
- def prev_block=(hash); @prev_block_hash = hash; end
17
+ alias prev_block prev_block_hash
18
+ def prev_block=(hash)
19
+ @prev_block_hash = hash
20
+ end
20
21
 
21
22
  # transactions (Array of Tx)
22
23
  attr_accessor :tx
@@ -44,7 +45,7 @@ module Bitcoin
44
45
 
45
46
  attr_reader :partial_merkle_tree
46
47
 
47
- alias :transactions :tx
48
+ alias transactions tx
48
49
 
49
50
  # compare to another block
50
51
  def ==(other)
@@ -52,16 +53,17 @@ module Bitcoin
52
53
  end
53
54
 
54
55
  def binary_hash
55
- [@hash].pack("H*")
56
+ [@hash].pack('H*')
56
57
  end
57
58
 
58
59
  def prev_block_hex
59
- @prev_block_hex ||= @prev_block_hash.reverse.unpack("H*")[0]
60
+ @prev_block_hex ||= @prev_block_hash.reverse.unpack('H*')[0]
60
61
  end
61
62
 
62
63
  # create block from raw binary +data+
63
- def initialize(data=nil)
64
+ def initialize(data = nil)
64
65
  @tx = []
66
+ @payload = nil
65
67
  parse_data_from_io(data) if data
66
68
  end
67
69
 
@@ -72,68 +74,74 @@ module Bitcoin
72
74
  end
73
75
 
74
76
  # parse raw binary data
75
- def parse_data_from_io(buf, header_only=false)
77
+ def parse_data_from_io(buf, header_only = false)
76
78
  buf = buf.is_a?(String) ? StringIO.new(buf) : buf
77
- @ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce = buf.read(80).unpack("Va32a32VVV")
79
+ @ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce = buf.read(80).unpack('Va32a32VVV')
78
80
  recalc_block_hash
79
81
 
80
- if Bitcoin.network[:auxpow_chain_id] != nil && (@ver & BLOCK_VERSION_AUXPOW) > 0
82
+ if !Bitcoin.network[:auxpow_chain_id].nil? && (@ver & BLOCK_VERSION_AUXPOW) > 0
81
83
  @aux_pow = AuxPow.new(nil)
82
84
  @aux_pow.parse_data_from_io(buf)
83
85
  end
84
86
 
85
87
  return buf if buf.eof?
86
88
 
87
- if header_only == :filtered
88
- @tx_count = buf.read(4).unpack("V")[0]
89
-
90
- nhashes = Protocol.unpack_var_int_from_io(buf)
91
- hashes = []
92
- nhashes.times do
93
- hashes << buf.read(256 / 8)
94
- end
95
-
96
- nflags = Protocol.unpack_var_int_from_io(buf)
97
- flags = buf.read(nflags)
98
-
99
- @partial_merkle_tree = PartialMerkleTree.new(@tx_count, hashes, flags)
100
- @partial_merkle_tree.set_value
101
-
102
- return buf
103
- end
89
+ return parse_filtered_header(buf) if header_only == :filtered
104
90
 
105
91
  tx_size = Protocol.unpack_var_int_from_io(buf)
106
92
  @tx_count = tx_size
107
93
  return buf if header_only
108
94
 
109
- tx_size.times{
95
+ tx_size.times do
110
96
  break if payload == true
111
97
  return buf if buf.eof?
112
98
 
113
99
  t = Tx.new(nil)
114
- payload = t.parse_data_from_io(buf)
100
+ t.parse_data_from_io(buf)
115
101
  @tx << t
116
- }
102
+ end
117
103
 
118
104
  @payload = to_payload
119
105
  buf
120
106
  end
121
107
 
108
+ def parse_filtered_header(buf)
109
+ @tx_count = buf.read(4).unpack('V')[0]
110
+
111
+ nhashes = Protocol.unpack_var_int_from_io(buf)
112
+ hashes = []
113
+ nhashes.times do
114
+ hashes << buf.read(256 / 8)
115
+ end
116
+
117
+ nflags = Protocol.unpack_var_int_from_io(buf)
118
+ flags = buf.read(nflags)
119
+
120
+ @partial_merkle_tree = PartialMerkleTree.new(@tx_count, hashes, flags)
121
+ @partial_merkle_tree.assign_value
122
+
123
+ buf
124
+ end
125
+
122
126
  # recalculate the block hash
123
127
  def recalc_block_hash
124
- @hash = Bitcoin.block_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver)
128
+ @hash = Bitcoin.block_hash(
129
+ @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver
130
+ )
125
131
  end
126
132
 
127
133
  def recalc_block_scrypt_hash
128
- @scrypt_hash = Bitcoin.block_scrypt_hash(@prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver)
134
+ @scrypt_hash = Bitcoin.block_scrypt_hash(
135
+ @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, @time, @bits, @nonce, @ver
136
+ )
129
137
  end
130
138
 
131
139
  def recalc_mrkl_root
132
140
  @mrkl_root = if partial_merkle_tree
133
- partial_merkle_tree.root.value.htb_reverse
134
- else
135
- Bitcoin.hash_mrkl_tree( @tx.map(&:hash) ).last.htb_reverse
136
- end
141
+ partial_merkle_tree.root.value.htb_reverse
142
+ else
143
+ Bitcoin.hash_mrkl_tree(@tx.map(&:hash)).last.htb_reverse
144
+ end
137
145
  end
138
146
 
139
147
  # verify mrkl tree
@@ -141,7 +149,7 @@ module Bitcoin
141
149
  if partial_merkle_tree
142
150
  partial_merkle_tree.valid_tree?(@mrkl_root.reverse_hth)
143
151
  else
144
- @mrkl_root.reverse_hth == Bitcoin.hash_mrkl_tree( @tx.map(&:hash) ).last
152
+ @mrkl_root.reverse_hth == Bitcoin.hash_mrkl_tree(@tx.map(&:hash)).last
145
153
  end
146
154
  end
147
155
 
@@ -156,16 +164,21 @@ module Bitcoin
156
164
  # get the block header info
157
165
  # [<version>, <prev_block>, <merkle_root>, <time>, <bits>, <nonce>, <txcount>, <size>]
158
166
  def header_info
159
- [@ver, @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth, Time.at(@time), @bits, @nonce, @tx.size, @payload.size]
167
+ [
168
+ @ver, @prev_block_hash.reverse_hth, @mrkl_root.reverse_hth,
169
+ Time.at(@time), @bits, @nonce, @tx.size, @payload.size
170
+ ]
160
171
  end
161
172
 
162
173
  # convert to raw binary format
163
174
  def to_payload
164
- head = [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce].pack("Va32a32VVV")
165
- head << @aux_pow.to_payload if @aux_pow
166
- return head if @tx.size == 0
175
+ @aux_pow ||= nil
176
+ head = [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce].pack('Va32a32VVV')
177
+ head << @aux_pow.to_payload if @aux_pow
178
+ return head if @tx.empty?
179
+
167
180
  head << Protocol.pack_var_int(@tx.size)
168
- @tx.each{|tx| head << tx.to_payload }
181
+ @tx.each { |tx| head << tx.to_payload }
169
182
  head
170
183
  end
171
184
 
@@ -175,11 +188,11 @@ module Bitcoin
175
188
  'hash' => @hash, 'ver' => @ver,
176
189
  'prev_block' => @prev_block_hash.reverse_hth, 'mrkl_root' => @mrkl_root.reverse_hth,
177
190
  'time' => @time, 'bits' => @bits, 'nonce' => @nonce,
178
- 'n_tx' => @tx.size, 'size' => (@payload||to_payload).bytesize,
179
- 'tx' => @tx.map{|i| i.to_hash(options) },
180
- 'mrkl_tree' => Bitcoin.hash_mrkl_tree( @tx.map{|i| i.hash } )
191
+ 'n_tx' => @tx.size, 'size' => (@payload || to_payload).bytesize,
192
+ 'tx' => @tx.map { |i| i.to_hash(options) },
193
+ 'mrkl_tree' => Bitcoin.hash_mrkl_tree(@tx.map(&:hash))
181
194
  }
182
- h['aux_pow'] = @aux_pow.to_hash if @aux_pow
195
+ h['aux_pow'] = @aux_pow.to_hash if @aux_pow
183
196
  h
184
197
  end
185
198
 
@@ -202,75 +215,90 @@ module Bitcoin
202
215
  # introduced in block version 2 by BIP_0034
203
216
  # blockchain height as seen by the block itself.
204
217
  # do not trust this value, instead verify with chain storage.
205
- def bip34_block_height(height=nil)
218
+ def bip34_block_height(height = nil)
206
219
  return nil unless @ver >= 2
207
220
  if height # generate height binary
208
- buf = [height].pack("V").gsub(/\x00+$/,"")
209
- [buf.bytesize, buf].pack("Ca*")
221
+ buf = [height].pack('V').gsub(/\x00+$/, '')
222
+ [buf.bytesize, buf].pack('Ca*')
210
223
  else
211
224
  coinbase = @tx.first.inputs.first.script_sig
212
- coinbase[1..coinbase[0].ord].ljust(4, "\x00").unpack("V").first
225
+ coinbase[1..coinbase[0].ord].ljust(4, "\x00").unpack('V').first
213
226
  end
214
- rescue
227
+ rescue StandardError
215
228
  nil
216
229
  end
217
230
 
218
231
  # convert to json representation as seen in the block explorer.
219
232
  # (see also #from_json)
220
- def to_json(options = {:space => ''}, *a)
221
- JSON.pretty_generate( to_hash(options), options )
233
+ def to_json(options = { space: '' }, *_)
234
+ JSON.pretty_generate(to_hash(options), options)
222
235
  end
223
236
 
224
237
  # write json representation to a file
225
238
  # (see also #to_json)
226
239
  def to_json_file(path)
227
- File.open(path, 'wb'){|f| f.print to_json; }
240
+ File.open(path, 'wb') { |f| f.print to_json; }
228
241
  end
229
242
 
230
243
  # parse ruby hash (see also #to_hash)
231
- def self.from_hash(h, do_raise=true)
244
+ def self.from_hash(h, do_raise = true)
232
245
  blk = new(nil)
233
- blk.instance_eval{
246
+ blk.instance_eval do
234
247
  @ver, @time, @bits, @nonce = h.values_at('ver', 'time', 'bits', 'nonce')
235
- @prev_block_hash, @mrkl_root = h.values_at('prev_block', 'mrkl_root').map{|i| i.htb_reverse }
236
- unless h['hash'] == recalc_block_hash
237
- raise "Block hash mismatch! Claimed: #{h['hash']}, Actual: #{@hash}" if do_raise
248
+ @prev_block_hash, @mrkl_root = h.values_at('prev_block', 'mrkl_root').map(&:htb_reverse)
249
+
250
+ if do_raise && h['hash'] != recalc_block_hash
251
+ raise "Block hash mismatch! Claimed: #{h['hash']}, Actual: #{@hash}"
238
252
  end
239
- @aux_pow = AuxPow.from_hash(h['aux_pow']) if h['aux_pow']
240
- h['tx'].each{|tx| @tx << Tx.from_hash(tx, do_raise) }
241
- if h['tx'].any?
242
- (raise "Block merkle root mismatch! Block: #{h['hash']}" unless verify_mrkl_root) if do_raise
253
+
254
+ @aux_pow = AuxPow.from_hash(h['aux_pow']) if h['aux_pow']
255
+
256
+ h['tx'].each { |tx| @tx << Tx.from_hash(tx, do_raise) }
257
+ if h['tx'].any? && do_raise && !verify_mrkl_root
258
+ raise "Block merkle root mismatch! Block: #{h['hash']}"
243
259
  end
244
- }
260
+ end
245
261
  blk
246
262
  end
247
263
 
248
264
  # convert ruby hash to raw binary
249
- def self.binary_from_hash(h); from_hash(h).to_payload; end
265
+ def self.binary_from_hash(h)
266
+ from_hash(h).to_payload
267
+ end
250
268
 
251
269
  # parse json representation (see also #to_json)
252
- def self.from_json(json_string); from_hash( JSON.load(json_string) ); end
270
+ def self.from_json(json_string)
271
+ from_hash(JSON.parse(json_string))
272
+ end
253
273
 
254
274
  # convert json representation to raw binary
255
- def self.binary_from_json(json_string); from_json(json_string).to_payload; end
275
+ def self.binary_from_json(json_string)
276
+ from_json(json_string).to_payload
277
+ end
256
278
 
257
279
  # convert header to json representation.
258
- def header_to_json(options = {:space => ''})
280
+ def header_to_json(options = { space: '' })
259
281
  h = to_hash
260
- %w[tx mrkl_tree].each{|k| h.delete(k) }
261
- JSON.pretty_generate( h, options )
282
+ %w[tx mrkl_tree].each { |k| h.delete(k) }
283
+ JSON.pretty_generate(h, options)
262
284
  end
263
285
 
264
286
  # block header binary output
265
287
  def block_header
266
- [@ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce, Protocol.pack_var_int(0)].pack("Va32a32VVVa*")
288
+ [
289
+ @ver, @prev_block_hash, @mrkl_root, @time, @bits, @nonce, Protocol.pack_var_int(0)
290
+ ].pack('Va32a32VVVa*')
267
291
  end
268
292
 
269
293
  # read binary block from a file
270
- def self.from_file(path); new( Bitcoin::Protocol.read_binary_file(path) ); end
294
+ def self.from_file(path)
295
+ new(Bitcoin::Protocol.read_binary_file(path))
296
+ end
271
297
 
272
298
  # read json block from a file
273
- def self.from_json_file(path); from_json( Bitcoin::Protocol.read_binary_file(path) ); end
299
+ def self.from_json_file(path)
300
+ from_json(Bitcoin::Protocol.read_binary_file(path))
301
+ end
274
302
 
275
303
  # get the (statistical) amount of work that was needed to generate this block.
276
304
  def block_work
@@ -278,8 +306,6 @@ module Bitcoin
278
306
  return 0 if target <= 0
279
307
  (2**256) / (target + 1)
280
308
  end
281
-
282
309
  end
283
-
284
310
  end
285
311
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Bitcoin
4
4
  module Protocol
5
-
5
+ # https://en.bitcoin.it/wiki/Protocol_documentation#Message_types
6
6
  class Handler
7
7
  def on_inv_transaction(hash)
8
8
  p ['inv transaction', hash.hth]
@@ -29,15 +29,13 @@ module Bitcoin
29
29
  end
30
30
 
31
31
  def on_block(block)
32
- #p ['block', block]
32
+ # p ['block', block]
33
33
  puts block.to_json
34
34
  end
35
35
 
36
36
  def on_error(message, payload)
37
37
  p ['error', message, payload]
38
38
  end
39
-
40
39
  end
41
-
42
40
  end
43
41
  end
@@ -2,23 +2,66 @@
2
2
 
3
3
  module Bitcoin
4
4
  module Protocol
5
-
5
+ # https://en.bitcoin.it/wiki/Protocol_documentation#Message_types
6
6
  class Parser
7
7
  attr_reader :stats
8
8
 
9
- def initialize(handler=nil)
9
+ def initialize(handler = nil)
10
10
  @h = handler || Handler.new
11
- @buf = ""
11
+ @buf = ''
12
12
  @stats = { 'total_packets' => 0, 'total_bytes' => 0, 'total_errors' => 0 }
13
13
  end
14
14
 
15
- def log; @log ||= Bitcoin::Logger.create("parser"); end
15
+ # rubocop:disable CyclomaticComplexity
16
+ def process_pkt(command, payload)
17
+ @stats['total_packets'] += 1
18
+ @stats['total_bytes'] += payload.bytesize
19
+ @stats[command] ? (@stats[command] += 1) : @stats[command] = 1
20
+ case command
21
+ when 'tx' then @h.on_tx(Tx.new(payload))
22
+ when 'block' then @h.on_block(Block.new(payload))
23
+ when 'headers' then parse_headers(payload)
24
+ when 'inv' then parse_inv(payload, :put)
25
+ when 'getdata' then parse_inv(payload, :get)
26
+ when 'addr' then parse_addr(payload)
27
+ when 'getaddr' then @h.on_getaddr if @h.respond_to?(:on_getaddr)
28
+ when 'verack' then parse_verack
29
+ when 'version' then parse_version(payload)
30
+ when 'alert' then parse_alert(payload)
31
+ when 'ping' then @h.on_ping(payload.unpack('Q')[0])
32
+ when 'pong' then @h.on_pong(payload.unpack('Q')[0])
33
+ when 'getblocks' then @h.on_getblocks(*parse_getblocks(payload)) \
34
+ if @h.respond_to?(:on_getblocks)
35
+ when 'getheaders' then @h.on_getheaders(*parse_getblocks(payload)) \
36
+ if @h.respond_to?(:on_getheaders)
37
+ when 'mempool' then handle_mempool_request(payload)
38
+ when 'notfound' then handle_notfound_reply(payload)
39
+ when 'merkleblock' then parse_mrkle_block(payload)
40
+ when 'reject' then handle_reject(payload)
41
+ else
42
+ parse_error :unknown_packet, [command, payload.hth]
43
+ end
44
+ end
45
+ # rubocop:enable CyclomaticComplexity
46
+
47
+ def parse_headers(payload)
48
+ return unless @h.respond_to?(:on_headers)
49
+ buf = StringIO.new(payload)
50
+ count = Protocol.unpack_var_int_from_io(buf)
51
+ headers = Array.new(count) do
52
+ break if buf.eof?
53
+ b = Block.new
54
+ b.parse_data_from_io(buf, true)
55
+ b
56
+ end
57
+ @h.on_headers(headers)
58
+ end
16
59
 
17
60
  # handles inv/getdata packets
18
- def parse_inv(payload, type=:put)
61
+ def parse_inv(payload, type = :put)
19
62
  count, payload = Protocol.unpack_var_int(payload)
20
63
  payload.each_byte.each_slice(36).with_index do |i, idx|
21
- hash = i[4..-1].reverse.pack("C32")
64
+ hash = i[4..-1].reverse.pack('C32')
22
65
  case i[0]
23
66
  when 1
24
67
  type == :put ? @h.on_inv_transaction(hash) : @h.on_get_transaction(hash)
@@ -33,70 +76,27 @@ module Bitcoin
33
76
  @h.on_get_block(hash)
34
77
  end
35
78
  else
36
- parse_error :parse_inv, i.pack("C*")
79
+ parse_error :parse_inv, i.pack('C*')
37
80
  end
38
81
  end
39
82
  end
40
83
 
41
84
  def parse_addr(payload)
42
- count, payload = Protocol.unpack_var_int(payload)
85
+ _, payload = Protocol.unpack_var_int(payload)
43
86
  payload.each_byte.each_slice(30) do |i|
44
- @h.on_addr(Addr.new(i.pack("C*"))) rescue parse_error(:addr, i.pack("C*"))
87
+ begin
88
+ @h.on_addr(Addr.new(i.pack('C*')))
89
+ rescue StandardError
90
+ parse_error(:addr, i.pack('C*'))
91
+ end
45
92
  end
46
93
  end
47
94
 
48
- def parse_headers(payload)
49
- return unless @h.respond_to?(:on_headers)
50
- buf = StringIO.new(payload)
51
- count = Protocol.unpack_var_int_from_io(buf)
52
- headers = count.times.map{
53
- break if buf.eof?
54
- b = Block.new; b.parse_data_from_io(buf, header_only=true); b
55
- }
56
- @h.on_headers(headers)
57
- end
58
-
59
- def parse_mrkle_block(payload)
60
- return unless @h.respond_to?(:on_mrkle_block)
61
- b = Block.new
62
- b.parse_data_from_io(payload, header_only= :filtered)
63
- @h.on_mrkle_block(b)
64
- end
65
-
66
- def parse_getblocks(payload)
67
- version, payload = payload.unpack('Va*')
68
- count, payload = Protocol.unpack_var_int(payload)
69
- buf, payload = payload.unpack("a#{count*32}a*")
70
- hashes = buf.each_byte.each_slice(32).map{|i| hash = i.reverse.pack("C32").hth }
71
- stop_hash = payload[0..32].reverse_hth
72
- [version, hashes, stop_hash]
73
- end
74
-
75
- def process_pkt(command, payload)
76
- @stats['total_packets'] += 1
77
- @stats['total_bytes'] += payload.bytesize
78
- @stats[command] ? (@stats[command] += 1) : @stats[command] = 1
79
- case command
80
- when 'tx'; @h.on_tx( Tx.new(payload) )
81
- when 'block'; @h.on_block( Block.new(payload) )
82
- when 'headers'; parse_headers(payload)
83
- when 'inv'; parse_inv(payload, :put)
84
- when 'getdata'; parse_inv(payload, :get)
85
- when 'addr'; parse_addr(payload)
86
- when 'getaddr'; @h.on_getaddr if @h.respond_to?(:on_getaddr)
87
- when 'verack'; @h.respond_to?(:on_verack) ? @h.on_verack : (@h.respond_to?(:on_handshake_complete) ? @h.on_handshake_complete : nil)
88
- when 'version'; parse_version(payload)
89
- when 'alert'; parse_alert(payload)
90
- when 'ping'; @h.on_ping(payload.unpack("Q")[0])
91
- when 'pong'; @h.on_pong(payload.unpack("Q")[0])
92
- when 'getblocks'; @h.on_getblocks(*parse_getblocks(payload)) if @h.respond_to?(:on_getblocks)
93
- when 'getheaders'; @h.on_getheaders(*parse_getblocks(payload)) if @h.respond_to?(:on_getheaders)
94
- when 'mempool'; handle_mempool_request(payload)
95
- when 'notfound'; handle_notfound_reply(payload)
96
- when 'merkleblock'; parse_mrkle_block(payload)
97
- when 'reject'; handle_reject(payload)
95
+ def parse_verack
96
+ if @h.respond_to?(:on_verack)
97
+ @h.on_verack
98
98
  else
99
- parse_error :unknown_packet, [command, payload.hth]
99
+ @h.respond_to?(:on_handshake_complete) ? @h.on_handshake_complete : nil
100
100
  end
101
101
  end
102
102
 
@@ -106,36 +106,53 @@ module Bitcoin
106
106
  end
107
107
 
108
108
  def parse_alert(payload)
109
- return unless @h.respond_to?(:on_alert)
110
- @h.on_alert Bitcoin::Protocol::Alert.parse(payload)
109
+ # nop (https://github.com/lian/bitcoin-ruby/issues/268)
111
110
  end
112
111
 
113
- def handle_reject(payload)
114
- return unless @h.respond_to?(:on_reject)
115
- @h.on_reject Bitcoin::Protocol::Reject.parse(payload)
112
+ def parse_getblocks(payload)
113
+ version, payload = payload.unpack('Va*')
114
+ count, payload = Protocol.unpack_var_int(payload)
115
+ buf, payload = payload.unpack("a#{count * 32}a*")
116
+ hashes = buf.each_byte.each_slice(32).map { |i| i.reverse.pack('C32').hth }
117
+ stop_hash = payload[0..32].reverse_hth
118
+ [version, hashes, stop_hash]
116
119
  end
117
120
 
118
121
  # https://en.bitcoin.it/wiki/BIP_0035
119
- def handle_mempool_request(payload)
120
- return unless @version.fields[:version] >= 60002 # Protocol version >= 60002
121
- return unless (@version.fields[:services] & Bitcoin::Protocol::Version::NODE_NETWORK) == 1 # NODE_NETWORK bit set in Services
122
+ def handle_mempool_request(*_)
123
+ return unless @version.fields[:version] >= 60_002 # Protocol version >= 60002
124
+ return unless (
125
+ @version.fields[:services] & Bitcoin::Protocol::Version::NODE_NETWORK
126
+ ) == 1 # NODE_NETWORK bit set in Services
122
127
  @h.on_mempool if @h.respond_to?(:on_mempool)
123
128
  end
124
129
 
125
130
  def handle_notfound_reply(payload)
126
131
  return unless @h.respond_to?(:on_notfound)
127
- count, payload = Protocol.unpack_var_int(payload)
132
+ _, payload = Protocol.unpack_var_int(payload)
128
133
  payload.each_byte.each_slice(36) do |i|
129
- hash = i[4..-1].reverse.pack("C32")
134
+ hash = i[4..-1].reverse.pack('C32')
130
135
  case i[0]
131
- when 1; @h.on_notfound(:tx, hash)
132
- when 2; @h.on_notfound(:block, hash)
136
+ when 1 then @h.on_notfound(:tx, hash)
137
+ when 2 then @h.on_notfound(:block, hash)
133
138
  else
134
- parse_error(:notfound, [i.pack("C*"), hash])
139
+ parse_error(:notfound, [i.pack('C*'), hash])
135
140
  end
136
141
  end
137
142
  end
138
143
 
144
+ def parse_mrkle_block(payload)
145
+ return unless @h.respond_to?(:on_mrkle_block)
146
+ b = Block.new
147
+ b.parse_data_from_io(payload, :filtered)
148
+ @h.on_mrkle_block(b)
149
+ end
150
+
151
+ def handle_reject(payload)
152
+ return unless @h.respond_to?(:on_reject)
153
+ @h.on_reject Bitcoin::Protocol::Reject.parse(payload)
154
+ end
155
+
139
156
  def parse(buf)
140
157
  @buf += buf
141
158
  while parse_buffer; end
@@ -143,52 +160,51 @@ module Bitcoin
143
160
  end
144
161
 
145
162
  def parse_buffer
146
- head_magic = Bitcoin::network[:magic_head]
163
+ head_magic = Bitcoin.network[:magic_head]
147
164
  head_size = 24
148
165
  return false if @buf.size < head_size
149
166
 
150
- magic, cmd, length, checksum = @buf.unpack("a4A12Va4")
151
- payload = @buf[head_size...head_size+length]
167
+ magic, cmd, length, checksum = @buf.unpack('a4A12Va4')
168
+ payload = @buf[head_size...head_size + length]
152
169
 
153
- unless magic == head_magic
154
- handle_stream_error(:close, "head_magic not found")
155
- @buf = ''
156
- else
170
+ if magic == head_magic
157
171
 
158
- if Digest::SHA256.digest(Digest::SHA256.digest( payload ))[0...4] != checksum
159
- if (length < 50000) && (payload.size < length)
172
+ if Digest::SHA256.digest(Digest::SHA256.digest(payload))[0...4] != checksum
173
+ if (length < 50_000) && (payload.size < length)
160
174
  size_info = [payload.size, length].join('/')
161
175
  handle_stream_error(:debug, "chunked packet stream (#{size_info})")
162
176
  else
163
- handle_stream_error(:close, "checksum mismatch")
177
+ handle_stream_error(:close, 'checksum mismatch')
164
178
  end
165
179
  return
166
180
  end
167
- @buf = @buf[head_size+length..-1] || ""
181
+ @buf = @buf[head_size + length..-1] || ''
168
182
 
169
183
  process_pkt(cmd, payload)
184
+ else
185
+ handle_stream_error(:close, 'head_magic not found')
186
+ @buf = ''
170
187
  end
171
188
 
172
189
  # not empty yet? parse more.
173
- @buf[0] != nil
190
+ !@buf[0].nil?
174
191
  end
175
192
 
176
193
  def handle_stream_error(type, msg)
194
+ # TODO: replace by writing a real logger/exception handler
177
195
  case type
178
196
  when :close
179
- log.debug {"closing packet stream (#{msg})"}
197
+ puts "closing packet stream (#{msg})"
180
198
  else
181
- log.debug { [type, msg] }
199
+ puts [type, msg].inspect
182
200
  end
183
201
  end
184
202
 
185
- def parse_error *err
203
+ def parse_error(*err)
186
204
  @stats['total_errors'] += 1
187
205
  return unless @h.respond_to?(:on_error)
188
- @h.on_error *err
206
+ @h.on_error(*err)
189
207
  end
190
-
191
- end # Parser
192
-
208
+ end
193
209
  end
194
210
  end