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
@@ -1,172 +1,166 @@
1
1
  # encoding: ascii-8bit
2
- # Ruby reference implementation: https://github.com/sipa/bech32/tree/master/ref/c
3
- module Bitcoin; end
4
- module Bitcoin::Bech32
5
-
6
- CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l".unpack("C*")
7
- CHARSET_REV = [
8
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
9
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
11
- 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
12
- -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
13
- 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
14
- -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
15
- 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
16
- ]
17
-
18
- class << self
19
-
20
- def polymod_step(pre)
21
- b = pre >> 25
22
- return ((pre & 0x1FFFFFF) << 5) ^ \
2
+
3
+ module Bitcoin
4
+ # Ruby reference implementation: https://github.com/sipa/bech32/tree/master/ref/c
5
+ module Bech32
6
+ CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'.unpack('C*')
7
+ CHARSET_REV = [
8
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
9
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
11
+ 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
12
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
13
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
14
+ -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
15
+ 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
16
+ ].freeze
17
+
18
+ class << self
19
+ def polymod_step(pre)
20
+ b = pre >> 25
21
+ ((pre & 0x1FFFFFF) << 5) ^ \
23
22
  (-((b >> 0) & 1) & 0x3b6a57b2) ^ \
24
23
  (-((b >> 1) & 1) & 0x26508e6d) ^ \
25
24
  (-((b >> 2) & 1) & 0x1ea119fa) ^ \
26
25
  (-((b >> 3) & 1) & 0x3d4233dd) ^ \
27
26
  (-((b >> 4) & 1) & 0x2a1462b3)
28
- end
29
-
30
- def encode(hrp, data)
31
- buf = []
32
- chk = 1
33
-
34
- hrp.unpack("C*").each do |ch|
35
- return nil if ch < 33 || ch > 126
36
- return nil if ch >= 'A'.ord && ch <= 'Z'.ord
37
- chk = polymod_step(chk) ^ (ch >> 5)
38
27
  end
39
28
 
40
- return nil if (hrp.bytesize + 7 + data.size) > 90
29
+ def encode(hrp, data)
30
+ buf = []
31
+ chk = 1
41
32
 
42
- chk = polymod_step(chk)
43
- hrp.unpack("C*").each do |ch|
44
- chk = polymod_step(chk) ^ (ch & 0x1f)
45
- buf << ch
46
- end
47
-
48
- buf << '1'.ord
33
+ hrp.unpack('C*').each do |ch|
34
+ return nil if ch < 33 || ch > 126
35
+ return nil if ch >= 'A'.ord && ch <= 'Z'.ord
36
+ chk = polymod_step(chk) ^ (ch >> 5)
37
+ end
49
38
 
50
- data.each do |i|
51
- return nil if (i >> 5) != 0
52
- chk = polymod_step(chk) ^ i
53
- buf << CHARSET[i]
54
- end
39
+ return nil if (hrp.bytesize + 7 + data.size) > 90
55
40
 
56
- 6.times do |n|
57
41
  chk = polymod_step(chk)
58
- end
42
+ hrp.unpack('C*').each do |ch|
43
+ chk = polymod_step(chk) ^ (ch & 0x1f)
44
+ buf << ch
45
+ end
59
46
 
60
- chk ^= 1
47
+ buf << '1'.ord
61
48
 
62
- 6.times do |i|
63
- buf << CHARSET[(chk >> ((5 - i) * 5)) & 0x1f]
64
- end
49
+ data.each do |i|
50
+ return nil if (i >> 5) != 0
51
+ chk = polymod_step(chk) ^ i
52
+ buf << CHARSET[i]
53
+ end
65
54
 
66
- return buf.pack("C*")
67
- end
55
+ 6.times do
56
+ chk = polymod_step(chk)
57
+ end
68
58
 
69
- def decode(input)
70
- chk = 1
71
- input_len = input.bytesize
72
- have_lower, have_upper = false, false
59
+ chk ^= 1
73
60
 
74
- return nil if input_len < 8 || input_len > 90
61
+ 6.times do |i|
62
+ buf << CHARSET[(chk >> ((5 - i) * 5)) & 0x1f]
63
+ end
75
64
 
76
- data_len = 0
77
- while data_len < input_len && input[(input_len - 1) - data_len] != '1' do
78
- data_len += 1
65
+ buf.pack('C*')
79
66
  end
80
67
 
81
- hrp_len = input_len - (1 + data_len)
82
- return nil if hrp_len < 1 || data_len < 6
68
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
69
+ def decode(input)
70
+ chk = 1
71
+ input_len = input.bytesize
72
+ have_lower = false
73
+ have_upper = false
83
74
 
84
- data_len -= 6
75
+ return nil if input_len < 8 || input_len > 90
85
76
 
86
- hrp = []
87
- hrp_len.times do |i|
88
- ch = input[i].ord
89
- return nil if ch < 33 || ch > 126
77
+ data_len = 0
78
+ data_len += 1 while data_len < input_len && input[(input_len - 1) - data_len] != '1'
90
79
 
91
- if ch >= 'a'.ord && ch <= 'z'.ord
92
- have_lower = true
93
- elsif ch >= 'A'.ord && ch <= 'Z'.ord
94
- have_upper = true
95
- ch = (ch - 'A'.ord) + 'a'.ord
96
- end
80
+ hrp_len = input_len - (1 + data_len)
81
+ return nil if hrp_len < 1 || data_len < 6
97
82
 
98
- hrp << ch
99
- chk = polymod_step(chk) ^ (ch >> 5)
100
- end
101
-
102
- chk = polymod_step(chk)
83
+ hrp = []
84
+ hrp_len.times do |i|
85
+ ch = input[i].ord
86
+ return nil if ch < 33 || ch > 126
103
87
 
104
- hrp_len.times do |i|
105
- chk = polymod_step(chk) ^ (input[i].ord & 0x1f)
106
- end
88
+ if ch >= 'a'.ord && ch <= 'z'.ord
89
+ have_lower = true
90
+ elsif ch >= 'A'.ord && ch <= 'Z'.ord
91
+ have_upper = true
92
+ ch = (ch - 'A'.ord) + 'a'.ord
93
+ end
107
94
 
108
- data = []
109
- i = hrp_len + 1
110
- while i < input_len do
111
- ch = input[i].ord
112
- v = ((ch & 0x80) != 0) ? -1 : CHARSET_REV[ch]
95
+ hrp << ch
96
+ chk = polymod_step(chk) ^ (ch >> 5)
97
+ end
113
98
 
114
- have_lower = true if ch >= 'a'.ord && ch <= 'z'.ord
115
- have_upper = true if ch >= 'A'.ord && ch <= 'Z'.ord
116
- return nil if v == -1
99
+ chk = polymod_step(chk)
117
100
 
118
- chk = polymod_step(chk) ^ v
119
- if (i + 6) < input_len
120
- data << v
101
+ hrp_len.times do |i|
102
+ chk = polymod_step(chk) ^ (input[i].ord & 0x1f)
121
103
  end
122
- i += 1
123
- end
124
104
 
125
- return nil if have_lower && have_upper
126
- return nil if chk != 1
105
+ data = []
106
+ i = hrp_len + 1
107
+ while i < input_len
108
+ ch = input[i].ord
109
+ v = (ch & 0x80) != 0 ? -1 : CHARSET_REV[ch]
127
110
 
128
- return [hrp.pack("C*"), data]
129
- end
111
+ have_lower = true if ch >= 'a'.ord && ch <= 'z'.ord
112
+ have_upper = true if ch >= 'A'.ord && ch <= 'Z'.ord
113
+ return nil if v == -1
130
114
 
131
- # Utility for converting bytes of data between bases. These is used for
132
- # BIP 173 address encoding/decoding to convert between sequences of bytes
133
- # representing 8-bit values and groups of 5 bits. Conversions may be padded
134
- # with trailing 0 bits to the nearest byte boundary. Returns nil if
135
- # conversion requires padding and pad is false.
136
- #
137
- # For example:
138
- #
139
- # convert_bits("\xFF\xFF", from_bits: 8, to_bits: 5, pad: true)
140
- # => "\x1F\x1F\x1F\10"
141
- #
142
- # See https://github.com/bitcoin/bitcoin/blob/595a7bab23bc21049526229054ea1fff1a29c0bf/src/utilstrencodings.h#L154
143
- def convert_bits(chunks, from_bits:, to_bits:, pad:)
144
- output_mask = (1 << to_bits) - 1
145
- buffer_mask = (1 << (from_bits + to_bits - 1)) - 1
146
-
147
- buffer = 0
148
- bits = 0
149
-
150
- output = []
151
- chunks.each do |chunk|
152
- buffer = ((buffer << from_bits) | chunk) & buffer_mask
153
- bits += from_bits
154
- while bits >= to_bits
155
- bits -= to_bits
156
- output << ((buffer >> bits) & output_mask)
115
+ chk = polymod_step(chk) ^ v
116
+ data << v if (i + 6) < input_len
117
+ i += 1
157
118
  end
158
- end
159
119
 
160
- if pad && bits > 0
161
- output << ((buffer << (to_bits - bits)) & output_mask)
162
- end
120
+ return nil if have_lower && have_upper
121
+ return nil if chk != 1
163
122
 
164
- if !pad && (bits >= from_bits || ((buffer << (to_bits - bits)) & output_mask) != 0)
165
- return nil
123
+ [hrp.pack('C*'), data]
166
124
  end
125
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
126
+
127
+ # Utility for converting bytes of data between bases. These is used for
128
+ # BIP 173 address encoding/decoding to convert between sequences of bytes
129
+ # representing 8-bit values and groups of 5 bits. Conversions may be padded
130
+ # with trailing 0 bits to the nearest byte boundary. Returns nil if
131
+ # conversion requires padding and pad is false.
132
+ #
133
+ # For example:
134
+ #
135
+ # convert_bits("\xFF\xFF", from_bits: 8, to_bits: 5, pad: true)
136
+ # => "\x1F\x1F\x1F\10"
137
+ #
138
+ # See https://github.com/bitcoin/bitcoin/blob/595a7bab23bc21049526229054ea1fff1a29c0bf/src/utilstrencodings.h#L154
139
+ def convert_bits(chunks, from_bits:, to_bits:, pad:)
140
+ output_mask = (1 << to_bits) - 1
141
+ buffer_mask = (1 << (from_bits + to_bits - 1)) - 1
142
+
143
+ buffer = 0
144
+ bits = 0
145
+
146
+ output = []
147
+ chunks.each do |chunk|
148
+ buffer = ((buffer << from_bits) | chunk) & buffer_mask
149
+ bits += from_bits
150
+ while bits >= to_bits
151
+ bits -= to_bits
152
+ output << ((buffer >> bits) & output_mask)
153
+ end
154
+ end
167
155
 
168
- output
169
- end
156
+ output << ((buffer << (to_bits - bits)) & output_mask) if pad && bits > 0
170
157
 
158
+ if !pad && (bits >= from_bits || ((buffer << (to_bits - bits)) & output_mask) != 0)
159
+ return nil
160
+ end
161
+
162
+ output
163
+ end
164
+ end
171
165
  end
172
166
  end
@@ -1,9 +1,10 @@
1
1
  module Bitcoin
2
+ # https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
2
3
  class BloomFilter
3
4
  SEED_SHIFT = 0xfba4c795
4
- BIT_MASK = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]
5
+ BIT_MASK = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80].freeze
5
6
 
6
- MAX_FILTER_SIZE = 36000
7
+ MAX_FILTER_SIZE = 36_000
7
8
  MAX_HASH_FUNCS = 50
8
9
 
9
10
  # flags for filterload message
@@ -53,8 +54,8 @@ module Bitcoin
53
54
 
54
55
  # using #ceil instead of #floor may be better, but it's bitcoinj's way
55
56
 
56
- calc_m = (-Math.log(fp_rate) * elements / ln2 / ln2 / 8).floor;
57
- @filter_size = [1, [calc_m, MAX_FILTER_SIZE].min].max;
57
+ calc_m = (-Math.log(fp_rate) * elements / ln2 / ln2 / 8).floor
58
+ @filter_size = [1, [calc_m, MAX_FILTER_SIZE].min].max
58
59
  @filter = "\x00" * @filter_size
59
60
 
60
61
  calc_k = (@filter_size * 8 * ln2 / elements).floor
@@ -62,7 +63,7 @@ module Bitcoin
62
63
  end
63
64
 
64
65
  def rotate_left32(x, r)
65
- return (x << r) | (x >> (32 - r))
66
+ (x << r) | (x >> (32 - r))
66
67
  end
67
68
 
68
69
  #
@@ -80,13 +81,15 @@ module Bitcoin
80
81
  # body
81
82
  while i < num_blocks
82
83
  k1 = (object[i] & 0xFF) |
83
- ((object[i + 1] & 0xFF) << 8) |
84
- ((object[i + 2] & 0xFF) << 16) |
85
- ((object[i + 3] & 0xFF) << 24)
84
+ ((object[i + 1] & 0xFF) << 8) |
85
+ ((object[i + 2] & 0xFF) << 16) |
86
+ ((object[i + 3] & 0xFF) << 24)
86
87
 
87
- k1 *= c1; k1 &= 0xffffffff
88
+ k1 *= c1
89
+ k1 &= 0xffffffff
88
90
  k1 = rotate_left32(k1, 15)
89
- k1 *= c2; k1 &= 0xffffffff
91
+ k1 *= c2
92
+ k1 &= 0xffffffff
90
93
 
91
94
  h1 ^= k1
92
95
  h1 = rotate_left32(h1, 13)
@@ -97,29 +100,29 @@ module Bitcoin
97
100
 
98
101
  k1 = 0
99
102
  flg = object.length & 3
100
- if flg >= 3
101
- k1 ^= (object[num_blocks + 2] & 0xff) << 16
102
- end
103
- if flg >= 2
104
- k1 ^= (object[num_blocks + 1] & 0xff) << 8
105
- end
103
+ k1 ^= (object[num_blocks + 2] & 0xff) << 16 if flg >= 3
104
+ k1 ^= (object[num_blocks + 1] & 0xff) << 8 if flg >= 2
106
105
  if flg >= 1
107
106
  k1 ^= (object[num_blocks] & 0xff)
108
- k1 *= c1; k1 &= 0xffffffff
107
+ k1 *= c1
108
+ k1 &= 0xffffffff
109
109
  k1 = rotate_left32(k1, 15)
110
- k1 *= c2; k1 &= 0xffffffff
110
+ k1 *= c2
111
+ k1 &= 0xffffffff
111
112
  h1 ^= k1
112
113
  end
113
114
 
114
115
  # finalization
115
116
  h1 ^= object.length
116
117
  h1 ^= h1 >> 16
117
- h1 *= 0x85ebca6b; h1 &= 0xffffffff
118
+ h1 *= 0x85ebca6b
119
+ h1 &= 0xffffffff
118
120
  h1 ^= h1 >> 13
119
- h1 *= 0xc2b2ae35; h1 &= 0xffffffff
121
+ h1 *= 0xc2b2ae35
122
+ h1 &= 0xffffffff
120
123
  h1 ^= h1 >> 16
121
124
 
122
- return (h1 & 0xffffffff) % (@filter_size * 8)
125
+ (h1 & 0xffffffff) % (@filter_size * 8)
123
126
  end
124
127
  end
125
128
  end
@@ -1,15 +1,13 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
3
  module Bitcoin
4
-
5
4
  # Optional DSL to help create blocks and transactions.
6
5
  #
7
6
  # see also BlockBuilder, TxBuilder, TxInBuilder, TxOutBuilder, ScriptBuilder
8
7
  module Builder
9
-
10
8
  # build a Bitcoin::Protocol::Block matching the given +target+.
11
9
  # see BlockBuilder for details.
12
- def build_block(target = "00".ljust(64, 'f'))
10
+ def build_block(target = '00'.ljust(64, 'f'))
13
11
  c = BlockBuilder.new
14
12
  yield c
15
13
  c.block(target)
@@ -17,7 +15,7 @@ module Bitcoin
17
15
 
18
16
  # build a Bitcoin::Protocol::Tx.
19
17
  # see TxBuilder for details.
20
- def build_tx opts = {}
18
+ def build_tx(opts = {})
21
19
  c = TxBuilder.new
22
20
  yield c
23
21
  c.tx opts
@@ -45,35 +43,44 @@ module Bitcoin
45
43
  #
46
44
  # See Bitcoin::Builder::TxBuilder for details on building transactions.
47
45
  class BlockBuilder
46
+ attr_writer :prev_block, :time, :version
48
47
 
49
48
  def initialize
50
49
  @block = P::Block.new(nil)
51
50
  end
52
51
 
53
52
  # specify block version. this is usually not necessary. defaults to 1.
54
- def version v
53
+ def version(v) # rubocop:disable Style/TrivialAccessors
55
54
  @version = v
56
55
  end
57
56
 
58
57
  # set the hash of the previous block.
59
- def prev_block hash
58
+ def prev_block(hash) # rubocop:disable Style/TrivialAccessors
60
59
  @prev_block = hash
61
60
  end
62
61
 
63
62
  # set the block timestamp (defaults to current time).
64
- def time time
63
+ def time(time) # rubocop:disable Style/TrivialAccessors
65
64
  @time = time
66
65
  end
67
66
 
68
67
  # add transactions to the block (see TxBuilder).
69
- def tx tx = nil
70
- tx ||= ( c = TxBuilder.new; yield c; c.tx )
68
+ def tx(tx = nil)
69
+ tx ||= begin
70
+ c = TxBuilder.new
71
+ yield c
72
+ c.tx
73
+ end
71
74
  @block.tx << tx
72
75
  tx
73
76
  end
74
77
 
75
78
  # create the block according to values specified via DSL.
76
- def block target
79
+ def block(target)
80
+ @version ||= nil
81
+ @mrkl_root ||= nil
82
+ @time ||= nil
83
+
77
84
  @block.ver = @version || 1
78
85
  @block.prev_block = @prev_block.htb.reverse
79
86
  @block.mrkl_root = @mrkl_root
@@ -82,33 +89,31 @@ module Bitcoin
82
89
  @block.mrkl_root = Bitcoin.hash_mrkl_tree(@block.tx.map(&:hash)).last.htb.reverse
83
90
  find_hash(target)
84
91
  block = P::Block.new(@block.to_payload)
85
- raise "Payload Error" unless block.to_payload == @block.to_payload
92
+ raise 'Payload Error' unless block.to_payload == @block.to_payload
86
93
  block
87
94
  end
88
95
 
89
96
  private
90
97
 
91
98
  # increment nonce/time to find a block hash matching the +target+.
92
- def find_hash target
99
+ def find_hash(target)
93
100
  @block.bits = Bitcoin.encode_compact_bits(target)
94
101
  t = Time.now
95
102
  @block.recalc_block_hash
96
103
  until @block.hash.to_i(16) < target.to_i(16)
97
104
  @block.nonce += 1
98
105
  @block.recalc_block_hash
99
- if @block.nonce == 100000
100
- if t
101
- tt = 1 / ((Time.now - t) / 100000) / 1000
102
- print "\r%.2f khash/s" % tt
103
- end
104
- t = Time.now
105
- @block.time = Time.now.to_i
106
- @block.nonce = 0
107
- $stdout.flush
106
+ next unless @block.nonce == 100_000
107
+ if t
108
+ tt = 1 / ((Time.now - t) / 100_000) / 1000
109
+ print format("\r%.2f khash/s", tt)
108
110
  end
111
+ t = Time.now
112
+ @block.time = Time.now.to_i
113
+ @block.nonce = 0
114
+ $stdout.flush
109
115
  end
110
116
  end
111
-
112
117
  end
113
118
 
114
119
  # DSL to create Bitcoin::Protocol::Tx used by Builder#build_tx.
@@ -129,20 +134,21 @@ module Bitcoin
129
134
  #
130
135
  # See TxInBuilder and TxOutBuilder for details on how to build in/outputs.
131
136
  class TxBuilder
132
-
133
137
  def initialize
134
138
  @tx = P::Tx.new(nil)
135
- @tx.ver, @tx.lock_time = 1, 0
136
- @ins, @outs = [], []
139
+ @tx.ver = 1
140
+ @tx.lock_time = 0
141
+ @ins = []
142
+ @outs = []
137
143
  end
138
144
 
139
145
  # specify tx version. this is usually not necessary. defaults to 1.
140
- def version n
146
+ def version(n)
141
147
  @tx.ver = n
142
148
  end
143
149
 
144
150
  # specify tx lock_time. this is usually not necessary. defaults to 0.
145
- def lock_time n
151
+ def lock_time(n)
146
152
  @tx.lock_time = n
147
153
  end
148
154
 
@@ -154,10 +160,10 @@ module Bitcoin
154
160
  end
155
161
 
156
162
  # add an output to the transaction (see TxOutBuilder).
157
- def output value = nil, recipient = nil, type = :address
163
+ def output(value = nil, recipient = nil, type = :address)
158
164
  c = TxOutBuilder.new
159
165
  c.value(value) if value
160
- c.to(recipient, type) if recipient
166
+ c.to(recipient, type) if recipient
161
167
  yield c if block_given?
162
168
  @outs << c
163
169
  end
@@ -172,14 +178,15 @@ module Bitcoin
172
178
  # to the given address. The :leave_fee option can be used in this
173
179
  # case to specify a tx fee that should be left unclaimed by the
174
180
  # change output.
175
- def tx opts = {}
181
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
182
+ def tx(opts = {})
176
183
  return @tx if @tx.hash
177
184
 
178
185
  if opts[:change_address] && !opts[:input_value]
179
186
  raise "Must give 'input_value' when auto-generating change output!"
180
187
  end
181
- @ins.each {|i| @tx.add_in(i.txin) }
182
- @outs.each {|o| @tx.add_out(o.txout) }
188
+ @ins.each { |i| @tx.add_in(i.txin) }
189
+ @outs.each { |o| @tx.add_out(o.txout) }
183
190
  if opts[:change_address]
184
191
  output_value = @tx.out.map(&:value).inject(:+) || 0
185
192
  change_value = opts[:input_value] - output_value
@@ -202,7 +209,7 @@ module Bitcoin
202
209
  end
203
210
 
204
211
  # run our tx through an encode/decode cycle to make sure that the binary format is sane
205
- raise "Payload Error" unless P::Tx.new(@tx.to_witness_payload).to_payload == @tx.to_payload
212
+ raise 'Payload Error' unless P::Tx.new(@tx.to_witness_payload).to_payload == @tx.to_payload
206
213
  @tx.instance_eval do
207
214
  @payload = to_payload
208
215
  @hash = hash_from_payload(@payload)
@@ -210,38 +217,44 @@ module Bitcoin
210
217
 
211
218
  @tx
212
219
  end
220
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
213
221
 
214
222
  # coinbase inputs don't need to be signed, they only include the given +coinbase_data+
215
- def include_coinbase_data i, inc
216
- script_sig = [inc.coinbase_data].pack("H*")
223
+ def include_coinbase_data(i, inc)
224
+ script_sig = [inc.coinbase_data].pack('H*')
217
225
  @tx.in[i].script_sig_length = script_sig.bytesize
218
226
  @tx.in[i].script_sig = script_sig
219
227
  end
220
228
 
221
229
  def sig_hash_and_all_keys_exist?(inc, sig_script)
222
- return false unless @sig_hash && inc.has_keys?
230
+ return false unless @sig_hash && inc.keys?
223
231
  script = Bitcoin::Script.new(sig_script)
224
- return true if script.is_hash160? || script.is_pubkey? || script.is_witness_v0_keyhash? || (Bitcoin.namecoin? && script.is_namecoin?)
232
+ return true if script.is_hash160? ||
233
+ script.is_pubkey? ||
234
+ script.is_witness_v0_keyhash? ||
235
+ (Bitcoin.namecoin? && script.is_namecoin?)
225
236
  if script.is_multisig?
226
- return inc.has_multiple_keys? && inc.key.size >= script.get_signatures_required
237
+ return inc.multiple_keys? && inc.key.size >= script.get_signatures_required
227
238
  end
228
- raise "Script type must be hash160, pubkey, p2wpkh or multisig"
239
+ raise 'Script type must be hash160, pubkey, p2wpkh or multisig'
229
240
  end
230
241
 
231
242
  def add_empty_script_sig_to_input(i)
232
243
  @tx.in[i].script_sig_length = 0
233
- @tx.in[i].script_sig = ""
244
+ @tx.in[i].script_sig = ''
234
245
  # add the sig_hash that needs to be signed, so it can be passed on to a signing device
235
246
  @tx.in[i].sig_hash = @sig_hash
236
- # add the address the sig_hash needs to be signed with as a convenience for the signing device
237
- @tx.in[i].sig_address = Script.new(@prev_script).get_address if @prev_script
247
+ # add the address the sig_hash needs to be signed with as a convenience for the
248
+ # signing device
249
+ @tx.in[i].sig_address = Script.new(@prev_script).get_address if @prev_script
238
250
  end
239
251
 
240
252
  def get_script_sig(inc, hash_type)
241
- if inc.has_multiple_keys?
253
+ if inc.multiple_keys?
242
254
  # multiple keys given, generate signature for each one
243
255
  sigs = inc.sign(@sig_hash)
244
- if redeem_script = inc.instance_eval { @redeem_script }
256
+ redeem_script = inc.instance_eval { @redeem_script }
257
+ if redeem_script
245
258
  # when a redeem_script was specified, assume we spend a p2sh multisig script
246
259
  script_sig = Script.to_p2sh_multisig_script_sig(redeem_script, sigs)
247
260
  else
@@ -251,73 +264,80 @@ module Bitcoin
251
264
  else
252
265
  # only one key given, generate signature and script_sig
253
266
  sig = inc.sign(@sig_hash)
254
- script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack("H*"), hash_type)
267
+ script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack('H*'), hash_type)
255
268
  end
256
- return script_sig
269
+ script_sig
257
270
  end
258
271
 
259
272
  # Sign input number +i+ with data from given +inc+ object (a TxInBuilder).
260
- def sign_input i, inc
261
- if @tx.in[i].coinbase?
262
- include_coinbase_data(i, inc)
263
- else
264
- @prev_script = inc.instance_variable_get(:@prev_out_script)
273
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
274
+ def sign_input(i, inc)
275
+ return include_coinbase_data(i, inc) if @tx.in[i].coinbase?
276
+ @prev_script = inc.instance_variable_get(:@prev_out_script)
277
+
278
+ # get the signature script; use +redeem_script+ if given
279
+ # (indicates spending a p2sh output), otherwise use the prev_script
280
+ sig_script = inc.instance_eval { @redeem_script }
281
+ sig_script ||= @prev_script
282
+
283
+ hash_type = if inc.prev_out_forkid
284
+ Script::SIGHASH_TYPE[:all] | Script::SIGHASH_TYPE[:forkid]
285
+ else
286
+ Script::SIGHASH_TYPE[:all]
287
+ end
288
+
289
+ # when a sig_script was found, generate the sig_hash to be signed
290
+ if sig_script
291
+ script = Script.new(sig_script)
292
+ @sig_hash = if script.is_witness_v0_keyhash?
293
+ @tx.signature_hash_for_witness_input(i, sig_script, inc.value)
294
+ elsif inc.prev_out_forkid
295
+ @tx.signature_hash_for_input(
296
+ i,
297
+ sig_script,
298
+ hash_type,
299
+ inc.value,
300
+ inc.prev_out_forkid
301
+ )
302
+ else
303
+ @tx.signature_hash_for_input(i, sig_script)
304
+ end
305
+ end
265
306
 
266
- # get the signature script; use +redeem_script+ if given
267
- # (indicates spending a p2sh output), otherwise use the prev_script
268
- sig_script = inc.instance_eval { @redeem_script }
269
- sig_script ||= @prev_script
307
+ # when there is a sig_hash and one or more signature_keys were specified
308
+ if sig_hash_and_all_keys_exist?(inc, sig_script)
309
+ # add the script_sig to the txin
310
+ if script.is_witness_v0_keyhash? # for p2wpkh
311
+ @tx.in[i].script_witness.stack << inc.sign(@sig_hash) + \
312
+ [Script::SIGHASH_TYPE[:all]].pack('C')
313
+ @tx.in[i].script_witness.stack << inc.key.pub.htb
270
314
 
271
- hash_type = if inc.prev_out_forkid
272
- Script::SIGHASH_TYPE[:all] | Script::SIGHASH_TYPE[:forkid]
315
+ redeem_script = inc.instance_eval { @redeem_script }
316
+ @tx.in[i].script_sig = Bitcoin::Script.pack_pushdata(redeem_script) if redeem_script
273
317
  else
274
- Script::SIGHASH_TYPE[:all]
318
+ @tx.in[i].script_sig = get_script_sig(inc, hash_type)
275
319
  end
276
-
277
- # when a sig_script was found, generate the sig_hash to be signed
278
- if sig_script
279
- script = Script.new(sig_script)
280
- if script.is_witness_v0_keyhash?
281
- @sig_hash = @tx.signature_hash_for_witness_input(i, sig_script, inc.value)
282
- else
283
- @sig_hash = if inc.prev_out_forkid
284
- @tx.signature_hash_for_input(
285
- i,
286
- sig_script,
287
- hash_type,
288
- inc.value,
289
- inc.prev_out_forkid)
290
- else
291
- @tx.signature_hash_for_input(i, sig_script)
292
- end
293
- end
294
- end
295
-
296
- # when there is a sig_hash and one or more signature_keys were specified
297
- if sig_hash_and_all_keys_exist?(inc, sig_script)
298
- # add the script_sig to the txin
299
- if script.is_witness_v0_keyhash? # for p2wpkh
300
- @tx.in[i].script_witness.stack << inc.sign(@sig_hash) + [Script::SIGHASH_TYPE[:all]].pack("C")
301
- @tx.in[i].script_witness.stack << inc.key.pub.htb
302
- else
303
- @tx.in[i].script_sig = get_script_sig(inc, hash_type)
304
- end
305
- # double-check that the script_sig is valid to spend the given prev_script
306
- if @prev_script && !inc.prev_out_forkid && !@tx.verify_input_signature(i, @prev_script)
307
- raise "Signature error"
308
- end
309
- elsif inc.has_multiple_keys?
310
- raise "Keys missing for multisig signing"
311
- else
312
- # no sig_hash, add an empty script_sig.
313
- add_empty_script_sig_to_input(i)
320
+ # double-check that the script_sig is valid to spend the given prev_script
321
+ if @prev_script && !inc.prev_out_forkid
322
+ verified = if script.is_witness_v0_keyhash?
323
+ @tx.verify_witness_input_signature(i, @prev_script, inc.value)
324
+ else
325
+ @tx.verify_input_signature(i, @prev_script)
326
+ end
327
+ raise 'Signature error' unless verified
314
328
  end
329
+ elsif inc.multiple_keys?
330
+ raise 'Keys missing for multisig signing'
331
+ else
332
+ # no sig_hash, add an empty script_sig.
333
+ add_empty_script_sig_to_input(i)
315
334
  end
316
335
  end
336
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
317
337
 
318
338
  # Randomize the outputs using SecureRandom
319
339
  def randomize_outputs
320
- @outs.sort_by!{ SecureRandom.random_bytes(4).unpack("I")[0] }
340
+ @outs.sort_by! { SecureRandom.random_bytes(4).unpack('I')[0] }
321
341
  end
322
342
  end
323
343
 
@@ -346,45 +366,48 @@ module Bitcoin
346
366
  #
347
367
  # If you want to spend a multisig output, just provide an array of keys to #signature_key.
348
368
  class TxInBuilder
349
- attr_reader :prev_tx, :prev_script, :redeem_script, :key, :coinbase_data, :prev_out_value, :prev_out_forkid
369
+ attr_reader :coinbase_data, :key, :prev_out_forkid, :prev_script, :prev_tx
370
+ attr_writer :prev_out_script, :prev_out_value, :redeem_script, :sequence
350
371
 
351
372
  def initialize
352
373
  @txin = P::TxIn.new
353
374
  @prev_out_hash = "\x00" * 32
354
375
  @prev_out_index = 0
376
+ @redeem_script = nil
377
+ @key = nil
355
378
  end
356
379
 
357
380
  # Previous transaction that contains the output we want to use.
358
381
  # You can either pass the transaction, or just the tx hash.
359
382
  # If you pass only the hash, you need to pass the previous outputs
360
383
  # +script+ separately if you want the txin to be signed.
361
- def prev_out tx, idx = nil, script = nil, prev_value = nil, prev_forkid = nil
384
+ def prev_out(tx, idx = nil, script = nil, prev_value = nil, prev_forkid = nil)
362
385
  @prev_out_forkid = prev_forkid
363
386
  if tx.is_a?(Bitcoin::P::Tx)
364
387
  @prev_tx = tx
365
388
  @prev_out_hash = tx.binary_hash
366
- @prev_out_script = tx.out[idx].pk_script if idx
389
+ @prev_out_script = tx.out[idx].pk_script if idx
367
390
  else
368
391
  @prev_out_hash = tx.htb.reverse
369
392
  end
370
- @prev_out_script = script if script
371
- @prev_out_index = idx if idx
393
+ @prev_out_script = script if script
394
+ @prev_out_index = idx if idx
372
395
  @prev_out_value = prev_value if prev_value
373
396
  end
374
397
 
375
398
  # Index of the output in the #prev_out transaction.
376
- def prev_out_index i
399
+ def prev_out_index(i)
377
400
  @prev_out_index = i
378
- @prev_out_script = @prev_tx.out[i].pk_script if @prev_tx
401
+ @prev_out_script = @prev_tx.out[i].pk_script if @prev_tx
379
402
  end
380
403
 
381
404
  # Previous output's +pk_script+. Needed when only the tx hash is specified as #prev_out.
382
- def prev_out_script script
405
+ def prev_out_script(script) # rubocop:disable Style/TrivialAccessors
383
406
  @prev_out_script = script
384
407
  end
385
408
 
386
409
  # Previous output's +value+. Needed when only spend segwit utxo.
387
- def prev_out_value value
410
+ def prev_out_value(value) # rubocop:disable Style/TrivialAccessors
388
411
  @prev_out_value = value
389
412
  end
390
413
 
@@ -394,52 +417,70 @@ module Bitcoin
394
417
 
395
418
  # Redeem script for P2SH output. To spend from a P2SH output, you need to provide
396
419
  # the script with a hash matching the P2SH address.
397
- def redeem_script script
420
+ def redeem_script(script) # rubocop:disable Style/TrivialAccessors
398
421
  @redeem_script = script
399
422
  end
400
423
 
401
424
  # Specify sequence. This is usually not needed.
402
- def sequence s
425
+ def sequence(s) # rubocop:disable Style/TrivialAccessors
403
426
  @sequence = s
404
427
  end
405
428
 
406
429
  # Bitcoin::Key used to sign the signature_hash for the input.
407
430
  # see Bitcoin::Script.signature_hash_for_input and Bitcoin::Key.sign.
408
- def signature_key key
431
+ def signature_key(key)
409
432
  @key = key
410
433
  end
411
434
 
412
435
  # Specify that this is a coinbase input. Optionally set +data+.
413
436
  # If this is set, no other options need to be given.
414
- def coinbase data = nil
437
+ def coinbase(data = nil)
415
438
  @coinbase_data = data || OpenSSL::Random.random_bytes(32)
416
439
  @prev_out_hash = "\x00" * 32
417
- @prev_out_index = 4294967295
440
+ @prev_out_index = 4_294_967_295
418
441
  end
419
442
 
420
443
  # Create the txin according to specified values
421
444
  def txin
445
+ @sequence ||= nil
422
446
  @txin.prev_out = @prev_out_hash
423
447
  @txin.prev_out_index = @prev_out_index
424
448
  @txin.sequence = @sequence || "\xff\xff\xff\xff"
425
449
  @txin
426
450
  end
427
451
 
428
- def has_multiple_keys?
452
+ def multiple_keys?
429
453
  @key.is_a?(Array)
430
454
  end
431
455
 
432
- def has_keys?
433
- @key && (has_multiple_keys? ? @key.all?(&:priv) : @key.priv)
456
+ def has_multiple_keys? # rubocop:disable Naming/PredicateName
457
+ warn '[DEPRECATION] `TxInBuilder.has_multiple_keys?` is deprecated. ' \
458
+ 'Use `multiple_keys?` instaed.'
459
+ multiple_keys?
460
+ end
461
+
462
+ def keys?
463
+ @key && (multiple_keys? ? @key.all?(&:priv) : @key.priv)
434
464
  end
435
465
 
436
- def is_witness_v0_keyhash?
466
+ def has_keys? # rubocop:disable Naming/PredicateName
467
+ warn '[DEPRECATION] `TxInBuilder.has_keys?` is deprecated. Use `keys?` instead.'
468
+ keys?
469
+ end
470
+
471
+ def witness_v0_keyhash?
437
472
  @prev_out_script && Script.new(@prev_out_script).is_witness_v0_keyhash?
438
473
  end
439
474
 
475
+ def is_witness_v0_keyhash? # rubocop:disable Naming/PredicateName
476
+ warn '[DEPRECATION] `TxInBuilder.is_witness_v0_keyhash?` is deprecated. ' \
477
+ 'Use `witness_v0_keyhash?` instead.'
478
+ witness_v0_keyhash?
479
+ end
480
+
440
481
  def sign(sig_hash)
441
- if has_multiple_keys?
442
- @key.map {|k| k.sign(sig_hash) }
482
+ if multiple_keys?
483
+ @key.map { |k| k.sign(sig_hash) }
443
484
  else
444
485
  @key.sign(sig_hash)
445
486
  end
@@ -457,14 +498,14 @@ module Bitcoin
457
498
 
458
499
  # Script type (:pubkey, :address/hash160, :multisig).
459
500
  # Defaults to :address.
460
- def type type
501
+ def type(type)
461
502
  @type = type.to_sym
462
503
  end
463
504
 
464
505
  # Recipient(s) of the script.
465
506
  # Depending on the #type, this should be an address, a hash160 pubkey,
466
507
  # or an array of multisig pubkeys.
467
- def recipient *data
508
+ def recipient(*data)
468
509
  @script, @redeem_script = *Script.send("to_#{@type}_script", *data)
469
510
  end
470
511
  end
@@ -490,23 +531,24 @@ module Bitcoin
490
531
  end
491
532
 
492
533
  # Set output value (in base units / "satoshis")
493
- def value value
534
+ def value(value)
494
535
  @txout.value = value
495
536
  end
496
537
 
497
538
  # Set recipient address and script type (defaults to :address).
498
- def to recipient, type = :address
499
- @txout.pk_script, @txout.redeem_script = *Bitcoin::Script.send("to_#{type}_script", *recipient)
539
+ def to(recipient, type = :address)
540
+ @txout.pk_script, @txout.redeem_script = *Bitcoin::Script.send(
541
+ "to_#{type}_script", *recipient
542
+ )
500
543
  end
501
544
 
502
545
  # Add a script to the output (see ScriptBuilder).
503
- def script &block
546
+ def script
504
547
  c = ScriptBuilder.new
505
548
  yield c
506
- @txout.pk_script, @txout.redeem_script = c.script, c.redeem_script
549
+ @txout.pk_script = c.script
550
+ @txout.redeem_script = c.redeem_script
507
551
  end
508
-
509
552
  end
510
-
511
553
  end
512
554
  end