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,61 +1,73 @@
1
- class Bitcoin::Protocol::PartialMerkleTree
2
- Node = Struct.new(:value, :left, :right, :width_idx)
1
+ module Bitcoin
2
+ module Protocol
3
+ # https://en.bitcoin.it/wiki/Protocol_documentation#Merkle_Trees
4
+ class PartialMerkleTree
5
+ Node = Struct.new(:value, :left, :right, :width_idx)
3
6
 
4
- BIT_MASK = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]
7
+ BIT_MASK = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80].freeze
5
8
 
6
- def initialize(total_txs, hashes, flags)
7
- @total_txs, @flags = total_txs, flags
8
- @hashes = hashes.map{|h| h.reverse_hth }
9
- @visit_idx = 0
10
- end
9
+ def initialize(total_txs, hashes, flags)
10
+ @total_txs = total_txs
11
+ @flags = flags
12
+ @hashes = hashes.map(&:reverse_hth)
13
+ @visit_idx = 0
14
+ end
11
15
 
12
- def tx_hashes
13
- @leaves.reject{|n| n.value.nil? }.map{|n| n.value }
14
- end
16
+ def tx_hashes
17
+ @leaves.reject { |n| n.value.nil? }.map(&:value)
18
+ end
15
19
 
16
- def build_tree
17
- lay = @leaves = @total_txs.times.map{ Node.new(nil, nil, nil) }
18
- while lay.size > 1
19
- lay = lay.each_slice(2).map do |left, right|
20
- Node.new(nil, left, right)
20
+ def build_tree
21
+ lay = @leaves = Array.new(@total_txs) { Node.new(nil, nil, nil) }
22
+ while lay.size > 1
23
+ lay = lay.each_slice(2).map do |left, right|
24
+ Node.new(nil, left, right)
25
+ end
26
+ end
27
+ lay[0]
21
28
  end
22
- end
23
- return lay[0]
24
- end
25
29
 
26
- def current_flag
27
- @flags[@visit_idx / 8].ord & BIT_MASK[@visit_idx % 8] == 0
28
- end
30
+ def current_flag
31
+ (@flags[@visit_idx / 8].ord & BIT_MASK[@visit_idx % 8]).zero?
32
+ end
29
33
 
30
- def root
31
- @root ||= build_tree
32
- end
34
+ def root
35
+ @root ||= build_tree
36
+ end
33
37
 
34
- def set_value(node = root)
35
- if current_flag || (node.left.nil? && node.right.nil?)
36
- node.value = @hashes.shift
37
- return
38
- end
38
+ def set_value(node = root) # rubocop:disable Naming/AccessorMethodName
39
+ warn '[DEPRECATION] `PartialMerkleTree.set_value` is deprecated. ' \
40
+ 'Use `assign_value` instead.'
41
+ assign_value(node)
42
+ end
39
43
 
40
- if node.left
41
- @visit_idx += 1
42
- set_value(node.left)
43
- end
44
- if node.right
45
- @visit_idx += 1
46
- set_value(node.right)
47
- end
44
+ def assign_value(node = root)
45
+ if current_flag || (node.left.nil? && node.right.nil?)
46
+ node.value = @hashes.shift
47
+ return
48
+ end
48
49
 
49
- right = node.right || node.left
50
- node.value = Bitcoin.bitcoin_mrkl(node.left.value, right.value)
50
+ if node.left
51
+ @visit_idx += 1
52
+ assign_value(node.left)
53
+ end
54
+ if node.right
55
+ @visit_idx += 1
56
+ assign_value(node.right)
57
+ end
51
58
 
52
- return
53
- end
59
+ right = node.right || node.left
60
+ node.value = Bitcoin.bitcoin_mrkl(node.left.value, right.value)
54
61
 
55
- def valid_tree?(mrkl_root_hash)
56
- return false unless @hashes.empty?
57
- return false if ((@visit_idx + 1)/8.0).ceil != @flags.length
58
- return false if mrkl_root_hash != root.value
59
- return true
62
+ nil
63
+ end
64
+
65
+ def valid_tree?(mrkl_root_hash)
66
+ return false unless @hashes.empty?
67
+ return false if ((@visit_idx + 1) / 8.0).ceil != @flags.length
68
+ return false if mrkl_root_hash != root.value
69
+ true
70
+ end
71
+ end
60
72
  end
61
73
  end
@@ -1,38 +1,36 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
3
  module Bitcoin
4
- module Protocol
4
+ module Protocol
5
+ Reject = Struct.new(:message, :ccode, :reason, :data) do
6
+ CCODE_TABLE = {
7
+ 0x01 => :malformed,
8
+ 0x10 => :invalid,
9
+ 0x11 => :obsolete,
10
+ 0x12 => :duplicate,
11
+ 0x40 => :nonstandard,
12
+ 0x41 => :dust,
13
+ 0x42 => :insufficientfee,
14
+ 0x43 => :checkpoint
15
+ }.freeze
5
16
 
6
- class Reject < Struct.new(:message, :ccode, :reason, :data)
7
- CCODE_TABLE = {
8
- 0x01 => :malformed,
9
- 0x10 => :invalid,
10
- 0x11 => :obsolete,
11
- 0x12 => :duplicate,
12
- 0x40 => :nonstandard,
13
- 0x41 => :dust,
14
- 0x42 => :insufficientfee,
15
- 0x43 => :checkpoint,
16
- }
17
+ def self.parse(payload)
18
+ message, payload = Bitcoin::Protocol.unpack_var_string(payload)
19
+ ccode, payload = payload.unpack('Ca*')
20
+ reason, payload = Bitcoin::Protocol.unpack_var_string(payload)
21
+ data = payload
17
22
 
18
- def self.parse(payload)
19
- message, payload = Bitcoin::Protocol.unpack_var_string(payload)
20
- ccode, payload = payload.unpack("Ca*")
21
- reason, payload = Bitcoin::Protocol.unpack_var_string(payload)
22
- data = payload
23
+ code = CCODE_TABLE[ccode] || ccode
24
+ new(message, code, reason, data)
25
+ end
23
26
 
24
- code = CCODE_TABLE[ccode] || ccode
25
- new(message, code, reason, data)
26
- end
27
-
28
- def tx_hash
29
- message == "tx" && self[:data].reverse.bth
30
- end
27
+ def tx_hash
28
+ message == 'tx' && self[:data].reverse.bth
29
+ end
31
30
 
32
- def block_hash
33
- message == "block" && self[:data].reverse.bth
31
+ def block_hash
32
+ message == 'block' && self[:data].reverse.bth
33
+ end
34
34
  end
35
35
  end
36
-
37
- end
38
36
  end
@@ -1,11 +1,9 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
3
  module Bitcoin
4
-
5
4
  module Protocol
6
-
5
+ # TxWitness section of https://en.bitcoin.it/wiki/Protocol_documentation#tx
7
6
  class ScriptWitness
8
-
9
7
  # witness stack
10
8
  attr_reader :stack
11
9
 
@@ -21,11 +19,8 @@ module Bitcoin
21
19
  # output script in raw binary format
22
20
  def to_payload
23
21
  payload = Bitcoin::Protocol.pack_var_int(stack.size)
24
- payload << stack.map{|e| Bitcoin::Protocol.pack_var_int(e.bytesize) << e }.join
22
+ payload << stack.map { |e| Bitcoin::Protocol.pack_var_int(e.bytesize) << e }.join
25
23
  end
26
-
27
24
  end
28
-
29
25
  end
30
-
31
- end
26
+ end
@@ -4,9 +4,8 @@ require 'bitcoin/script'
4
4
 
5
5
  module Bitcoin
6
6
  module Protocol
7
-
7
+ # https://en.bitcoin.it/wiki/Protocol_documentation#tx
8
8
  class Tx
9
-
10
9
  MARKER = 0
11
10
  FLAG = 1
12
11
 
@@ -36,8 +35,8 @@ module Bitcoin
36
35
  attr_accessor :marker
37
36
  attr_accessor :flag
38
37
 
39
- alias :inputs :in
40
- alias :outputs :out
38
+ alias inputs in
39
+ alias outputs out
41
40
 
42
41
  # compare to another tx
43
42
  def ==(other)
@@ -46,19 +45,23 @@ module Bitcoin
46
45
 
47
46
  # return the tx hash in binary format
48
47
  def binary_hash
49
- @binary_hash ||= [@hash].pack("H*").reverse
48
+ @binary_hash ||= [@hash].pack('H*').reverse
50
49
  end
51
50
 
52
51
  # create tx from raw binary +data+
53
- def initialize(data=nil)
54
- @ver, @lock_time, @in, @out, @scripts = 1, 0, [], [], []
55
- @enable_bitcoinconsensus = !!ENV['USE_BITCOINCONSENSUS']
52
+ def initialize(data = nil)
53
+ @ver = 1
54
+ @lock_time = 0
55
+ @in = []
56
+ @out = []
57
+ @scripts = []
58
+ @enable_bitcoinconsensus = !ENV['USE_BITCOINCONSENSUS'].nil?
56
59
  parse_data_from_io(data) if data
57
60
  end
58
61
 
59
62
  # generate the tx hash for given +payload+ in hex format
60
63
  def hash_from_payload(payload)
61
- Digest::SHA256.digest(Digest::SHA256.digest( payload )).reverse_hth
64
+ Digest::SHA256.digest(Digest::SHA256.digest(payload)).reverse_hth
62
65
  end
63
66
  alias generate_hash hash_from_payload
64
67
 
@@ -68,26 +71,31 @@ module Bitcoin
68
71
  end
69
72
 
70
73
  # add an input
71
- def add_in(input); (@in ||= []) << input; end
74
+ def add_in(input)
75
+ (@in ||= []) << input
76
+ end
72
77
 
73
78
  # add an output
74
- def add_out(output); (@out ||= []) << output; end
79
+ def add_out(output)
80
+ (@out ||= []) << output
81
+ end
75
82
 
76
83
  # parse raw binary data
84
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
77
85
  def parse_data_from_io(data)
78
86
  buf = data.is_a?(String) ? StringIO.new(data) : data
79
87
 
80
- @ver = buf.read(4).unpack("V")[0]
88
+ @ver = buf.read(4).unpack('V')[0]
81
89
 
82
90
  return false if buf.eof?
83
91
 
84
92
  # segwit serialization format is defined by https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki
85
- # Also note that it is impossible to parse 0 input transactions. Regular transactions with 0 inputs look
86
- # like malformed segwit transactions.
93
+ # Also note that it is impossible to parse 0 input transactions. Regular transactions
94
+ # with 0 inputs look like malformed segwit transactions.
87
95
  @marker = buf.read(1).unpack('c').first
88
96
  @flag = buf.read(1).unpack('c').first
89
97
 
90
- witness = @marker == 0 && @flag != 0
98
+ witness = @marker.zero? && !@flag.zero?
91
99
 
92
100
  # Non-segwit format does not contain marker or flag fields.
93
101
  buf.seek(buf.pos - 2) unless witness
@@ -95,19 +103,19 @@ module Bitcoin
95
103
  in_size = Protocol.unpack_var_int_from_io(buf)
96
104
 
97
105
  @in = []
98
- in_size.times{
106
+ in_size.times do
99
107
  break if buf.eof?
100
108
  @in << TxIn.from_io(buf)
101
- }
109
+ end
102
110
 
103
111
  return false if buf.eof?
104
112
 
105
113
  out_size = Protocol.unpack_var_int_from_io(buf)
106
114
  @out = []
107
- out_size.times{
115
+ out_size.times do
108
116
  break if buf.eof?
109
117
  @out << TxOut.from_io(buf)
110
- }
118
+ end
111
119
 
112
120
  return false if buf.eof?
113
121
 
@@ -121,7 +129,7 @@ module Bitcoin
121
129
  end
122
130
  end
123
131
 
124
- @lock_time = buf.read(4).unpack("V")[0]
132
+ @lock_time = buf.read(4).unpack('V')[0]
125
133
 
126
134
  @hash = hash_from_payload(to_old_payload)
127
135
  @payload = to_payload
@@ -132,8 +140,9 @@ module Bitcoin
132
140
  data.is_a?(StringIO) ? buf : buf.read
133
141
  end
134
142
  end
143
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
135
144
 
136
- alias :parse_data :parse_data_from_io
145
+ alias parse_data parse_data_from_io
137
146
 
138
147
  # output transaction in raw binary format
139
148
  def to_payload
@@ -141,12 +150,14 @@ module Bitcoin
141
150
  end
142
151
 
143
152
  def to_old_payload
144
- pin = ""
145
- @in.each{|input| pin << input.to_payload }
146
- pout = ""
147
- @out.each{|output| pout << output.to_payload }
153
+ pin = ''
154
+ @in.each { |input| pin << input.to_payload }
155
+ pout = ''
156
+ @out.each { |output| pout << output.to_payload }
148
157
 
149
- [@ver].pack("V") << Protocol.pack_var_int(@in.size) << pin << Protocol.pack_var_int(@out.size) << pout << [@lock_time].pack("V")
158
+ [@ver].pack('V') << Protocol.pack_var_int(@in.size) \
159
+ << pin << Protocol.pack_var_int(@out.size) \
160
+ << pout << [@lock_time].pack('V')
150
161
  end
151
162
 
152
163
  # output transaction in raw binary format with witness
@@ -168,7 +179,10 @@ module Bitcoin
168
179
 
169
180
  # generate a signature hash for input +input_idx+.
170
181
  # either pass the +outpoint_tx+ or the +script_pubkey+ directly.
171
- def signature_hash_for_input(input_idx, subscript, hash_type=nil, prev_out_value=nil, fork_id=nil)
182
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
183
+ def signature_hash_for_input(
184
+ input_idx, subscript, hash_type = nil, prev_out_value = nil, fork_id = nil
185
+ )
172
186
  # https://github.com/bitcoin/bitcoin/blob/e071a3f6c06f41068ad17134189a4ac3073ef76b/script.cpp#L834
173
187
  # http://code.google.com/p/bitcoinj/source/browse/trunk/src/com/google/bitcoin/core/Script.java#318
174
188
  # https://en.bitcoin.it/wiki/OP_CHECKSIG#How_it_works
@@ -181,31 +195,34 @@ module Bitcoin
181
195
  # Bitcoin Cash protocol will be respected.
182
196
  #
183
197
  # https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/abc/replay-protected-sighash.md
184
- if fork_id && (hash_type&SIGHASH_TYPE[:forkid]) != 0
185
- raise "SIGHASH_FORKID is enabled, so prev_out_value is required" if prev_out_value.nil?
198
+ if fork_id && (hash_type & SIGHASH_TYPE[:forkid]) != 0
199
+ raise 'SIGHASH_FORKID is enabled, so prev_out_value is required' if prev_out_value.nil?
186
200
 
187
201
  # According to the spec, we should modify the sighash by replacing the 24 most significant
188
202
  # bits with the fork ID. However, Bitcoin ABC does not currently implement this since the
189
203
  # fork_id is an implicit 0 and it would make the sighash JSON tests fail. Will leave as a
190
204
  # TODO for now.
191
- raise NotImplementedError, "fork_id must be 0" unless fork_id == 0
205
+ raise NotImplementedError, 'fork_id must be 0' unless fork_id.zero?
192
206
 
193
207
  script_code = Bitcoin::Protocol.pack_var_string(subscript)
194
208
  return signature_hash_for_input_bip143(input_idx, script_code, prev_out_value, hash_type)
195
209
  end
196
210
 
197
211
  # Note: BitcoinQT checks if input_idx >= @in.size and returns 1 with an error message.
198
- # But this check is never actually useful because BitcoinQT would crash
199
- # right before VerifyScript if input index is out of bounds (inside CScriptCheck::operator()()).
212
+ # But this check is never actually useful because BitcoinQT would crash right before
213
+ # VerifyScript if input index is out of bounds (inside CScriptCheck::operator()()).
200
214
  # That's why we don't need to do such a check here.
201
215
  #
202
- # However, if you look at the case SIGHASH_TYPE[:single] below, we must
203
- # return 1 because it's possible to have more inputs than outputs and BitcoinQT returns 1 as well.
204
- return "\x01".ljust(32, "\x00") if input_idx >= @in.size # ERROR: SignatureHash() : input_idx=%d out of range
216
+ # However, if you look at the case SIGHASH_TYPE[:single] below, we must return 1
217
+ # because it's possible to have more inputs than outputs and BitcoinQT returns 1 as well.
205
218
 
206
- pin = @in.map.with_index{|input,idx|
219
+ # ERROR: SignatureHash() : input_idx=%d out of range
220
+ return "\x01".ljust(32, "\x00") if input_idx >= @in.size
221
+
222
+ pin = @in.map.with_index do |input, idx|
207
223
  if idx == input_idx
208
- subscript = subscript.out[ input.prev_out_index ].script if subscript.respond_to?(:out) # legacy api (outpoint_tx)
224
+ # legacy api (outpoint_tx)
225
+ subscript = subscript.out[input.prev_out_index].script if subscript.respond_to?(:out)
209
226
 
210
227
  # Remove all instances of OP_CODESEPARATOR from the script.
211
228
  parsed_subscript = Script.new(subscript)
@@ -215,67 +232,93 @@ module Bitcoin
215
232
  input.to_payload(subscript)
216
233
  else
217
234
  case (hash_type & 0x1f)
218
- when SIGHASH_TYPE[:none]; input.to_payload("", "\x00\x00\x00\x00")
219
- when SIGHASH_TYPE[:single]; input.to_payload("", "\x00\x00\x00\x00")
220
- else; input.to_payload("")
235
+ when SIGHASH_TYPE[:none] then input.to_payload('', "\x00\x00\x00\x00")
236
+ when SIGHASH_TYPE[:single] then input.to_payload('', "\x00\x00\x00\x00")
237
+ else; input.to_payload('')
221
238
  end
222
239
  end
223
- }
240
+ end
224
241
 
225
242
  pout = @out.map(&:to_payload)
226
- in_size, out_size = Protocol.pack_var_int(@in.size), Protocol.pack_var_int(@out.size)
243
+ in_size = Protocol.pack_var_int(@in.size)
244
+ out_size = Protocol.pack_var_int(@out.size)
227
245
 
228
246
  case (hash_type & 0x1f)
229
247
  when SIGHASH_TYPE[:none]
230
- pout = ""
248
+ pout = ''
231
249
  out_size = Protocol.pack_var_int(0)
232
250
  when SIGHASH_TYPE[:single]
233
- return "\x01".ljust(32, "\x00") if input_idx >= @out.size # ERROR: SignatureHash() : input_idx=%d out of range (SIGHASH_SINGLE)
234
- pout = @out[0...(input_idx+1)].map.with_index{|out,idx| (idx==input_idx) ? out.to_payload : out.to_null_payload }.join
235
- out_size = Protocol.pack_var_int(input_idx+1)
251
+ # ERROR: SignatureHash() : input_idx=%d out of range (SIGHASH_SINGLE)
252
+ return "\x01".ljust(32, "\x00") if input_idx >= @out.size
253
+
254
+ pout = @out[0...(input_idx + 1)].map.with_index do |out, idx|
255
+ idx == input_idx ? out.to_payload : out.to_null_payload
256
+ end.join
257
+
258
+ out_size = Protocol.pack_var_int(input_idx + 1)
236
259
  end
237
260
 
238
261
  if (hash_type & SIGHASH_TYPE[:anyonecanpay]) != 0
239
- in_size, pin = Protocol.pack_var_int(1), [ pin[input_idx] ]
262
+ in_size = Protocol.pack_var_int(1)
263
+ pin = [pin[input_idx]]
240
264
  end
241
265
 
242
- buf = [ [@ver].pack("V"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join
243
- Digest::SHA256.digest( Digest::SHA256.digest( buf ) )
266
+ buf = [
267
+ [@ver].pack('V'), in_size, pin, out_size,
268
+ pout, [@lock_time, hash_type].pack('VV')
269
+ ].join
270
+ Digest::SHA256.digest(Digest::SHA256.digest(buf))
244
271
  end
272
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
245
273
 
246
274
  # generate a witness signature hash for input +input_idx+.
247
275
  # https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
248
- def signature_hash_for_witness_input(input_idx, witness_program, prev_out_value, witness_script = nil, hash_type=nil, skip_separator_index = 0)
249
- return "\x01".ljust(32, "\x00") if input_idx >= @in.size # ERROR: SignatureHash() : input_idx=%d out of range
276
+ # rubocop:disable Metrics/ParameterLists
277
+ def signature_hash_for_witness_input(
278
+ input_idx, witness_program, prev_out_value,
279
+ witness_script = nil, hash_type = nil, skip_separator_index = 0
280
+ )
281
+ # ERROR: SignatureHash() : input_idx=%d out of range
282
+ return "\x01".ljust(32, "\x00") if input_idx >= @in.size
250
283
 
251
284
  hash_type ||= SIGHASH_TYPE[:all]
252
-
253
285
  script = Bitcoin::Script.new(witness_program)
254
- raise "ScriptPubkey does not contain witness program." unless script.is_witness?
286
+ raise 'ScriptPubkey does not contain witness program.' unless script.is_witness?
255
287
 
256
288
  if script.is_witness_v0_keyhash?
257
- script_code = [["1976a914", script.get_hash160, "88ac"].join].pack("H*")
289
+ script_code = [['1976a914', script.get_hash160, '88ac'].join].pack('H*')
258
290
  elsif script.is_witness_v0_scripthash?
259
- raise "witness script does not match script pubkey" unless Bitcoin::Script.to_witness_p2sh_script(Digest::SHA256.digest(witness_script).bth) == witness_program
260
- script = skip_separator_index > 0 ? Bitcoin::Script.new(witness_script).subscript_codeseparator(skip_separator_index) : witness_script
291
+ witness_pubkey_script_match = Bitcoin::Script.to_witness_p2sh_script(
292
+ Digest::SHA256.digest(witness_script).bth
293
+ ) == witness_program
294
+ raise 'witness script does not match script pubkey' unless witness_pubkey_script_match
295
+
296
+ script = if skip_separator_index > 0
297
+ s = Bitcoin::Script.new(witness_script)
298
+ s.subscript_codeseparator(skip_separator_index)
299
+ else
300
+ witness_script
301
+ end
261
302
  script_code = Bitcoin::Protocol.pack_var_string(script)
262
303
  end
263
304
 
264
305
  signature_hash_for_input_bip143(input_idx, script_code, prev_out_value, hash_type)
265
306
  end
307
+ # rubocop:enable Metrics/ParameterLists
266
308
 
267
309
  # verify input signature +in_idx+ against the corresponding
268
310
  # output in +outpoint_tx+
269
311
  # outpoint. This arg can also be a Script or TxOut.
270
312
  #
271
- # options are: verify_sigpushonly, verify_minimaldata, verify_cleanstack, verify_dersig, verify_low_s, verify_strictenc, fork_id
272
- def verify_input_signature(in_idx, outpoint_data, block_timestamp=Time.now.to_i, opts={})
313
+ # options are: verify_sigpushonly, verify_minimaldata, verify_cleanstack,
314
+ # verify_dersig, verify_low_s, verify_strictenc, fork_id
315
+ def verify_input_signature(in_idx, outpoint_data, block_timestamp = Time.now.to_i, opts = {})
273
316
  if @enable_bitcoinconsensus
274
317
  return bitcoinconsensus_verify_script(in_idx, outpoint_data, block_timestamp, opts)
275
318
  end
276
319
 
277
320
  # If FORKID is enabled, we also ensure strict encoding.
278
- opts[:verify_strictenc] ||= !!opts[:fork_id]
321
+ opts[:verify_strictenc] ||= !opts[:fork_id].nil?
279
322
 
280
323
  outpoint_idx = @in[in_idx].prev_out_index
281
324
  script_sig = @in[in_idx].script_sig
@@ -284,29 +327,36 @@ module Bitcoin
284
327
  script_pubkey = script_pubkey_from_outpoint_data(outpoint_data, outpoint_idx)
285
328
 
286
329
  if opts[:fork_id] && amount.nil?
287
- raise "verify_input_signature must be called with a previous transaction or " \
288
- "transaction output if SIGHASH_FORKID is enabled"
330
+ raise 'verify_input_signature must be called with a previous transaction or ' \
331
+ 'transaction output if SIGHASH_FORKID is enabled'
289
332
  end
290
333
 
291
334
  @scripts[in_idx] = Bitcoin::Script.new(script_sig, script_pubkey)
292
335
  return false if opts[:verify_sigpushonly] && !@scripts[in_idx].is_push_only?(script_sig)
293
336
  return false if opts[:verify_minimaldata] && !@scripts[in_idx].pushes_are_canonical?
294
- sig_valid = @scripts[in_idx].run(block_timestamp, opts) do |pubkey,sig,hash_type,subscript|
337
+ sig_valid = @scripts[in_idx].run(
338
+ block_timestamp, opts
339
+ ) do |pubkey, sig, hash_type, subscript|
295
340
  hash = signature_hash_for_input(in_idx, subscript, hash_type, amount, opts[:fork_id])
296
- Bitcoin.verify_signature( hash, sig, pubkey.unpack("H*")[0] )
341
+ Bitcoin.verify_signature(hash, sig, pubkey.unpack('H*')[0])
297
342
  end
298
343
  # BIP62 rule #6
299
344
  return false if opts[:verify_cleanstack] && !@scripts[in_idx].stack.empty?
300
345
 
301
- return sig_valid
346
+ sig_valid
302
347
  end
303
348
 
304
349
  # verify witness input signature +in_idx+ against the corresponding
305
350
  # output in +outpoint_tx+
306
351
  # outpoint. This arg can also be a Script or TxOut
307
352
  #
308
- # options are: verify_sigpushonly, verify_minimaldata, verify_cleanstack, verify_dersig, verify_low_s, verify_strictenc
309
- def verify_witness_input_signature(in_idx, outpoint_data, prev_out_amount, block_timestamp=Time.now.to_i, opts={})
353
+ # options are: verify_sigpushonly, verify_minimaldata, verify_cleanstack,
354
+ # verify_dersig, verify_low_s, verify_strictenc
355
+ #
356
+ # rubocop:disable CyclomaticComplexity,PerceivedComplexity
357
+ def verify_witness_input_signature(
358
+ in_idx, outpoint_data, prev_out_amount, block_timestamp = Time.now.to_i, opts = {}
359
+ )
310
360
  if @enable_bitcoinconsensus
311
361
  return bitcoinconsensus_verify_script(in_idx, outpoint_data, block_timestamp, opts)
312
362
  end
@@ -319,52 +369,69 @@ module Bitcoin
319
369
 
320
370
  if script_pubkey.is_p2sh?
321
371
  redeem_script = Bitcoin::Script.new(@in[in_idx].script_sig).get_pubkey
322
- script_pubkey = Bitcoin::Script.new(redeem_script.htb) if Bitcoin.hash160(redeem_script) == script_pubkey.get_hash160 # P2SH-P2WPKH or P2SH-P2WSH
372
+
373
+ # P2SH-P2WPKH or P2SH-P2WSH
374
+ script_pubkey = if Bitcoin.hash160(redeem_script) == script_pubkey.get_hash160
375
+ Bitcoin::Script.new(redeem_script.htb)
376
+ end
323
377
  end
324
378
 
325
- @in[in_idx].script_witness.stack.each{|s|script_sig << Bitcoin::Script.pack_pushdata(s)}
379
+ @in[in_idx].script_witness.stack.each { |s| script_sig << Bitcoin::Script.pack_pushdata(s) }
326
380
  code_separator_index = 0
327
381
 
328
382
  if script_pubkey.is_witness_v0_keyhash? # P2WPKH
329
- @scripts[in_idx] = Bitcoin::Script.new(script_sig, Bitcoin::Script.to_hash160_script(script_pubkey.get_hash160))
383
+ @scripts[in_idx] = Bitcoin::Script.new(
384
+ script_sig, Bitcoin::Script.to_hash160_script(script_pubkey.get_hash160)
385
+ )
330
386
  elsif script_pubkey.is_witness_v0_scripthash? # P2WSH
331
387
  witness_hex = @in[in_idx].script_witness.stack.last.bth
332
388
  witness_script = Bitcoin::Script.new(witness_hex.htb)
333
389
  return false unless Bitcoin.sha256(witness_hex) == script_pubkey.get_hash160
334
- @scripts[in_idx] = Bitcoin::Script.new(script_sig, Bitcoin::Script.to_p2sh_script(Bitcoin.hash160(witness_hex)))
390
+ @scripts[in_idx] = Bitcoin::Script.new(
391
+ script_sig, Bitcoin::Script.to_p2sh_script(Bitcoin.hash160(witness_hex))
392
+ )
335
393
  else
336
394
  return false
337
395
  end
338
396
 
339
397
  return false if opts[:verify_sigpushonly] && !@scripts[in_idx].is_push_only?(script_sig)
340
398
  return false if opts[:verify_minimaldata] && !@scripts[in_idx].pushes_are_canonical?
341
- sig_valid = @scripts[in_idx].run(block_timestamp, opts) do |pubkey,sig,hash_type,subscript|
399
+ sig_valid = @scripts[in_idx].run(block_timestamp, opts) do |pubkey, sig, hash_type, _|
342
400
  if script_pubkey.is_witness_v0_keyhash?
343
- hash = signature_hash_for_witness_input(in_idx, script_pubkey.to_payload, prev_out_amount, nil, hash_type)
401
+ hash = signature_hash_for_witness_input(
402
+ in_idx, script_pubkey.to_payload, prev_out_amount, nil, hash_type
403
+ )
344
404
  elsif script_pubkey.is_witness_v0_scripthash?
345
- hash = signature_hash_for_witness_input(in_idx, script_pubkey.to_payload, prev_out_amount, witness_hex.htb, hash_type, code_separator_index)
405
+ hash = signature_hash_for_witness_input(
406
+ in_idx, script_pubkey.to_payload, prev_out_amount,
407
+ witness_hex.htb, hash_type, code_separator_index
408
+ )
346
409
  code_separator_index += 1 if witness_script.codeseparator_count > code_separator_index
347
410
  end
348
- Bitcoin.verify_signature( hash, sig, pubkey.unpack("H*")[0] )
411
+ Bitcoin.verify_signature(hash, sig, pubkey.unpack('H*')[0])
349
412
  end
350
413
  # BIP62 rule #6
351
414
  return false if opts[:verify_cleanstack] && !@scripts[in_idx].stack.empty?
352
415
 
353
- return sig_valid
416
+ sig_valid
354
417
  end
418
+ # rubocop:enable CyclomaticComplexity,PerceivedComplexity
355
419
 
356
- def bitcoinconsensus_verify_script(in_idx, outpoint_data, block_timestamp=Time.now.to_i, opts={})
357
- raise "Bitcoin::BitcoinConsensus shared library not found" unless Bitcoin::BitcoinConsensus.lib_available?
420
+ def bitcoinconsensus_verify_script(
421
+ in_idx, outpoint_data, block_timestamp = Time.now.to_i, opts = {}
422
+ )
423
+ consensus_available = Bitcoin::BitcoinConsensus.lib_available?
424
+ raise 'Bitcoin::BitcoinConsensus shared library not found' unless consensus_available
358
425
 
359
426
  outpoint_idx = @in[in_idx].prev_out_index
360
427
  script_pubkey = script_pubkey_from_outpoint_data(outpoint_data, outpoint_idx)
361
428
 
362
429
  flags = Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_NONE
363
- flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_P2SH if block_timestamp >= 1333238400
430
+ flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_P2SH if block_timestamp >= 1_333_238_400
364
431
  flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_SIGPUSHONLY if opts[:verify_sigpushonly]
365
432
  flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_MINIMALDATA if opts[:verify_minimaldata]
366
- flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_CLEANSTACK if opts[:verify_cleanstack]
367
- flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_LOW_S if opts[:verify_low_s]
433
+ flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_CLEANSTACK if opts[:verify_cleanstack]
434
+ flags |= Bitcoin::BitcoinConsensus::SCRIPT_VERIFY_LOW_S if opts[:verify_low_s]
368
435
 
369
436
  payload ||= to_payload
370
437
  Bitcoin::BitcoinConsensus.verify_script(in_idx, script_pubkey, payload, flags)
@@ -377,38 +444,37 @@ module Bitcoin
377
444
  'hash' => @hash, 'ver' => @ver, # 'nid' => normalized_hash,
378
445
  'vin_sz' => @in.size, 'vout_sz' => @out.size,
379
446
  'lock_time' => @lock_time, 'size' => (@payload ||= to_payload).bytesize,
380
- 'in' => @in.map{|i|i.to_hash(options)},
381
- 'out' => @out.map{|o| o.to_hash(options) }
447
+ 'in' => @in.map { |i| i.to_hash(options) },
448
+ 'out' => @out.map { |o| o.to_hash(options) }
382
449
  }
383
- h['nid'] = normalized_hash if options[:with_nid]
450
+ h['nid'] = normalized_hash if options[:with_nid]
384
451
  h
385
452
  end
386
453
 
387
454
  # generates rawblock json as seen in the block explorer.
388
- def to_json(options = {:space => ''}, *a)
389
- JSON.pretty_generate( to_hash(options), options )
455
+ def to_json(options = { space: '' }, *_a)
456
+ JSON.pretty_generate(to_hash(options), options)
390
457
  end
391
458
 
392
459
  # write json representation to a file
393
460
  # (see also #to_json)
394
461
  def to_json_file(path)
395
- File.open(path, 'wb'){|f| f.print to_json; }
462
+ File.open(path, 'wb') { |f| f.print to_json; }
396
463
  end
397
464
 
398
465
  # parse ruby hash (see also #to_hash)
399
- def self.from_hash(h, do_raise=true)
466
+ def self.from_hash(h, do_raise = true)
400
467
  tx = new(nil)
401
- tx.ver, tx.lock_time = (h['ver'] || h['version']), h['lock_time']
468
+ tx.ver = (h['ver'] || h['version'])
469
+ tx.lock_time = h['lock_time']
402
470
  ins = h['in'] || h['inputs']
403
471
  outs = h['out'] || h['outputs']
404
- ins .each{|input|
405
- tx.add_in(TxIn.from_hash(input))
406
- }
407
- outs.each{|output| tx.add_out TxOut.from_hash(output) }
408
- tx.instance_eval{
472
+ ins.each { |input| tx.add_in(TxIn.from_hash(input)) }
473
+ outs.each { |output| tx.add_out TxOut.from_hash(output) }
474
+ tx.instance_eval do
409
475
  @hash = hash_from_payload(to_old_payload)
410
476
  @payload = to_payload
411
- }
477
+ end
412
478
  if h['hash'] && (h['hash'] != tx.hash)
413
479
  raise "Tx hash mismatch! Claimed: #{h['hash']}, Actual: #{tx.hash}" if do_raise
414
480
  end
@@ -422,61 +488,86 @@ module Bitcoin
422
488
  end
423
489
 
424
490
  # parse json representation
425
- def self.from_json(json_string); from_hash( JSON.load(json_string) ); end
491
+ def self.from_json(json_string)
492
+ from_hash(JSON.parse(json_string))
493
+ end
426
494
 
427
495
  # convert json representation to raw binary
428
- def self.binary_from_json(json_string); from_json(json_string).to_payload; end
496
+ def self.binary_from_json(json_string)
497
+ from_json(json_string).to_payload
498
+ end
429
499
 
430
500
  # read binary block from a file
431
- def self.from_file(path); new( Bitcoin::Protocol.read_binary_file(path) ); end
501
+ def self.from_file(path)
502
+ new(Bitcoin::Protocol.read_binary_file(path))
503
+ end
432
504
 
433
505
  # read json block from a file
434
- def self.from_json_file(path); from_json( Bitcoin::Protocol.read_binary_file(path) ); end
506
+ def self.from_json_file(path)
507
+ from_json(Bitcoin::Protocol.read_binary_file(path))
508
+ end
435
509
 
436
510
  def size
437
511
  payload.bytesize
438
512
  end
439
-
440
- # Checks if transaction is final taking into account height and time
513
+
514
+ def is_final?(block_height, block_time) # rubocop:disable Naming/PredicateName
515
+ warn '[DEPRECATION] `Tx.is_final?` is deprecated. Use `final?` instead.'
516
+ final?(block_height, block_time)
517
+ end
518
+
519
+ # Checks if transaction is final taking into account height and time
441
520
  # of a block in which it is located (or about to be included if it's unconfirmed tx).
442
- def is_final?(block_height, block_time)
521
+ def final?(block_height, block_time)
443
522
  # No time lock - tx is final.
444
- return true if lock_time == 0
523
+ return true if lock_time.zero?
445
524
 
446
525
  # Time based nLockTime implemented in 0.1.6
447
526
  # If lock_time is below the magic threshold treat it as a block height.
448
527
  # If lock_time is above the threshold, it's a unix timestamp.
449
- return true if lock_time < (lock_time < Bitcoin::LOCKTIME_THRESHOLD ? block_height : block_time)
528
+ lock_threshold = lock_time < Bitcoin::LOCKTIME_THRESHOLD ? block_height : block_time
529
+ return true if lock_time < lock_threshold
450
530
 
451
- inputs.each{|input| return false if !input.is_final? }
531
+ inputs.each { |input| return false unless input.final? }
452
532
 
453
- return true
533
+ true
454
534
  end
455
-
535
+
456
536
  def legacy_sigops_count
457
- # Note: input scripts normally never have any opcodes since every input script
537
+ # Note: input scripts normally never have any opcodes since every input script
458
538
  # can be statically reduced to a pushdata-only script.
459
- # However, anyone is allowed to create a non-standard transaction with any opcodes in the inputs.
539
+ # However, anyone is allowed to create a non-standard transaction
540
+ # with any opcodes in the inputs.
460
541
  count = 0
461
542
  self.in.each do |txin|
462
543
  count += Bitcoin::Script.new(txin.script_sig).sigops_count_accurate(false)
463
544
  end
464
- self.out.each do |txout|
545
+ out.each do |txout|
465
546
  count += Bitcoin::Script.new(txout.pk_script).sigops_count_accurate(false)
466
547
  end
467
548
  count
468
549
  end
469
550
 
470
- DEFAULT_BLOCK_PRIORITY_SIZE = 27000
551
+ DEFAULT_BLOCK_PRIORITY_SIZE = 27_000
471
552
 
472
- def minimum_relay_fee; calculate_minimum_fee(allow_free=true, :relay); end
473
- def minimum_block_fee; calculate_minimum_fee(allow_free=true, :block); end
553
+ def minimum_relay_fee
554
+ calculate_minimum_fee(true, :relay)
555
+ end
474
556
 
475
- def calculate_minimum_fee(allow_free=true, mode=:block)
557
+ def minimum_block_fee
558
+ calculate_minimum_fee(true, :block)
559
+ end
560
+
561
+ # rubocop:disable PerceivedComplexity
562
+ def calculate_minimum_fee(allow_free = true, mode = :block)
476
563
  # Base fee is either nMinTxFee or nMinRelayTxFee
477
- base_fee = (mode == :relay) ? Bitcoin.network[:min_relay_tx_fee] : Bitcoin.network[:min_tx_fee]
478
- tx_size = to_payload.bytesize
479
- min_fee = (1 + tx_size / 1_000) * base_fee
564
+ base_fee = if mode == :relay
565
+ Bitcoin.network[:min_relay_tx_fee]
566
+ else
567
+ Bitcoin.network[:min_tx_fee]
568
+ end
569
+ tx_size = to_payload.bytesize
570
+ min_fee = (1 + tx_size / 1_000) * base_fee
480
571
 
481
572
  if allow_free
482
573
  # There is a free transaction area in blocks created by most miners,
@@ -485,7 +576,12 @@ module Bitcoin
485
576
  # multiple transactions instead of one big transaction to avoid fees.
486
577
  # * If we are creating a transaction we allow transactions up to 1,000 bytes
487
578
  # to be considered safe and assume they can likely make it into this section.
488
- min_fee = 0 if tx_size < (mode == :block ? Bitcoin.network[:free_tx_bytes] : DEFAULT_BLOCK_PRIORITY_SIZE - 1_000)
579
+ min_free_size = if mode == :block
580
+ Bitcoin.network[:free_tx_bytes]
581
+ else
582
+ DEFAULT_BLOCK_PRIORITY_SIZE - 1_000
583
+ end
584
+ min_fee = 0 if tx_size < min_free_size
489
585
  end
490
586
 
491
587
  # This code can be removed after enough miners have upgraded to version 0.9.
@@ -505,18 +601,27 @@ module Bitcoin
505
601
  end
506
602
  end
507
603
 
508
- min_fee = Bitcoin::network[:max_money] unless min_fee.between?(0, Bitcoin::network[:max_money])
604
+ min_fee = Bitcoin.network[:max_money] unless min_fee.between?(
605
+ 0, Bitcoin.network[:max_money]
606
+ )
509
607
  min_fee
510
608
  end
609
+ # rubocop:enable PerceivedComplexity
511
610
 
512
- def is_coinbase?
513
- inputs.size == 1 and inputs.first.coinbase?
611
+ def is_coinbase? # rubocop:disable Naming/PredicateName
612
+ warn '[DEPRECATION] `Tx.is_coinbase?` is deprecated. Use `coinbase?` instead.'
613
+ coinbase?
614
+ end
615
+
616
+ def coinbase?
617
+ inputs.size == 1 && inputs.first.coinbase?
514
618
  end
515
619
 
516
620
  def normalized_hash
517
621
  signature_hash_for_input(-1, nil, SIGHASH_TYPE[:all]).reverse.hth
518
622
  end
519
- alias :nhash :normalized_hash
623
+
624
+ alias nhash normalized_hash
520
625
 
521
626
  # get witness hash
522
627
  def witness_hash
@@ -526,37 +631,45 @@ module Bitcoin
526
631
  # sort transaction inputs and outputs under BIP 69
527
632
  # https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
528
633
  def lexicographical_sort!
529
- inputs.sort_by!{|i| [i.previous_output, i.prev_out_index]}
530
- outputs.sort_by!{|o| [o.amount, o.pk_script.bth]}
634
+ inputs.sort_by! { |i| [i.previous_output, i.prev_out_index] }
635
+ outputs.sort_by! { |o| [o.amount, o.pk_script.bth] }
531
636
  end
532
637
 
533
638
  private
534
639
 
535
640
  def signature_hash_for_input_bip143(input_idx, script_code, prev_out_value, hash_type)
536
- hash_prevouts = Digest::SHA256.digest(Digest::SHA256.digest(@in.map{|i| [i.prev_out_hash, i.prev_out_index].pack("a32V")}.join))
537
- hash_sequence = Digest::SHA256.digest(Digest::SHA256.digest(@in.map{|i|i.sequence}.join))
538
- outpoint = [@in[input_idx].prev_out_hash, @in[input_idx].prev_out_index].pack("a32V")
539
- amount = [prev_out_value].pack("Q")
641
+ hash_prevouts = Digest::SHA256.digest(
642
+ Digest::SHA256.digest(
643
+ @in.map { |i| [i.prev_out_hash, i.prev_out_index].pack('a32V') }.join
644
+ )
645
+ )
646
+ hash_sequence = Digest::SHA256.digest(Digest::SHA256.digest(@in.map(&:sequence).join))
647
+ outpoint = [@in[input_idx].prev_out_hash, @in[input_idx].prev_out_index].pack('a32V')
648
+ amount = [prev_out_value].pack('Q')
540
649
  nsequence = @in[input_idx].sequence
541
650
 
542
- hash_outputs = Digest::SHA256.digest(Digest::SHA256.digest(@out.map{|o|o.to_payload}.join))
651
+ hash_outputs = Digest::SHA256.digest(Digest::SHA256.digest(@out.map(&:to_payload).join))
543
652
 
544
653
  case (hash_type & 0x1f)
545
- when SIGHASH_TYPE[:single]
546
- hash_outputs = input_idx >= @out.size ? "\x00".ljust(32, "\x00") : Digest::SHA256.digest(Digest::SHA256.digest(@out[input_idx].to_payload))
547
- hash_sequence = "\x00".ljust(32, "\x00")
548
- when SIGHASH_TYPE[:none]
549
- hash_sequence = hash_outputs = "\x00".ljust(32, "\x00")
654
+ when SIGHASH_TYPE[:single]
655
+ hash_outputs = if input_idx >= @out.size
656
+ "\x00".ljust(32, "\x00")
657
+ else
658
+ Digest::SHA256.digest(Digest::SHA256.digest(@out[input_idx].to_payload))
659
+ end
660
+ hash_sequence = "\x00".ljust(32, "\x00")
661
+ when SIGHASH_TYPE[:none]
662
+ hash_sequence = hash_outputs = "\x00".ljust(32, "\x00")
550
663
  end
551
664
 
552
665
  if (hash_type & SIGHASH_TYPE[:anyonecanpay]) != 0
553
- hash_prevouts = hash_sequence ="\x00".ljust(32, "\x00")
666
+ hash_prevouts = hash_sequence = "\x00".ljust(32, "\x00")
554
667
  end
555
668
 
556
- buf = [ [@ver].pack("V"), hash_prevouts, hash_sequence, outpoint,
557
- script_code, amount, nsequence, hash_outputs, [@lock_time, hash_type].pack("VV")].join
669
+ buf = [[@ver].pack('V'), hash_prevouts, hash_sequence, outpoint, script_code,
670
+ amount, nsequence, hash_outputs, [@lock_time, hash_type].pack('VV')].join
558
671
 
559
- Digest::SHA256.digest( Digest::SHA256.digest( buf ) )
672
+ Digest::SHA256.digest(Digest::SHA256.digest(buf))
560
673
  end
561
674
 
562
675
  def script_pubkey_from_outpoint_data(outpoint_data, outpoint_idx)