bitcoin-ruby 0.0.18 → 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -86,7 +86,7 @@ module Bitcoin
86
86
  new_key.depth = depth + 1
87
87
  new_key.number = number
88
88
  new_key.parent_fingerprint = fingerprint
89
- if number > (2**31 -1)
89
+ if number > (2**31 - 1)
90
90
  data = [0x00].pack('C') << priv_key.priv.htb << [number].pack('N')
91
91
  else
92
92
  data = priv_key.pub.htb << [number].pack('N')
@@ -164,7 +164,7 @@ module Bitcoin
164
164
  new_key.depth = depth + 1
165
165
  new_key.number = number
166
166
  new_key.parent_fingerprint = fingerprint
167
- raise 'hardened key is not support' if number > (2**31 -1)
167
+ raise 'hardened key is not support' if number > (2**31 - 1)
168
168
  data = pub.htb << [number].pack('N')
169
169
  l = Bitcoin.hmac_sha512(chain_code, data)
170
170
  left = OpenSSL::BN.from_hex(l[0..31].bth)
@@ -188,4 +188,4 @@ module Bitcoin
188
188
  end
189
189
  end
190
190
 
191
- end
191
+ end
@@ -2,11 +2,10 @@
2
2
 
3
3
  require 'ffi'
4
4
 
5
- # binding for src/.libs/bitcoinconsensus.so (https://github.com/bitcoin/bitcoin)
6
- # tag: v0.11.0
7
- # commit: d26f951802c762de04fb68e1a112d611929920ba
8
-
9
5
  module Bitcoin
6
+ # binding for src/.libs/bitcoinconsensus.so (https://github.com/bitcoin/bitcoin)
7
+ # tag: v0.11.0
8
+ # commit: d26f951802c762de04fb68e1a112d611929920ba
10
9
  module BitcoinConsensus
11
10
  extend FFI::Library
12
11
 
@@ -21,10 +20,10 @@ module Bitcoin
21
20
  SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7)
22
21
  SCRIPT_VERIFY_CLEANSTACK = (1 << 8)
23
22
 
24
- ERR_CODES = { 0 => :ok, 1 => :tx_index, 2 => :tx_size_mismatch, 3 => :tx_deserialize }
23
+ ERR_CODES = { 0 => :ok, 1 => :tx_index, 2 => :tx_size_mismatch, 3 => :tx_deserialize }.freeze
25
24
 
26
25
  def self.ffi_load_functions(file)
27
- class_eval <<-RUBY
26
+ class_eval <<-RUBY # rubocop:disable Style/EvalWithLocation
28
27
  ffi_lib [ %[#{file}] ]
29
28
  attach_function :bitcoinconsensus_version, [], :uint
30
29
 
@@ -36,7 +35,9 @@ module Bitcoin
36
35
  end
37
36
 
38
37
  def self.lib_available?
39
- @__lib_path ||= [ ENV['BITCOINCONSENSUS_LIB_PATH'], 'vendor/bitcoin/src/.libs/libbitcoinconsensus.so' ].find{|f| File.exists?(f.to_s) }
38
+ @__lib_path ||= [ # rubocop:disable Naming/MemoizedInstanceVariableName
39
+ ENV['BITCOINCONSENSUS_LIB_PATH'], 'vendor/bitcoin/src/.libs/libbitcoinconsensus.so'
40
+ ].find { |f| File.exist?(f.to_s) }
40
41
  end
41
42
 
42
43
  def self.init
@@ -55,21 +56,24 @@ module Bitcoin
55
56
  def self.verify_script(input_index, script_pubkey, tx_payload, script_flags)
56
57
  init
57
58
 
58
- scriptPubKey = FFI::MemoryPointer.new(:uchar, script_pubkey.bytesize).put_bytes(0, script_pubkey)
59
- txTo = FFI::MemoryPointer.new(:uchar, tx_payload.bytesize).put_bytes(0, tx_payload)
59
+ script_pub_key = FFI::MemoryPointer.new(
60
+ :uchar, script_pubkey.bytesize
61
+ ).put_bytes(0, script_pubkey)
62
+ tx_to = FFI::MemoryPointer.new(:uchar, tx_payload.bytesize).put_bytes(0, tx_payload)
60
63
  error_ret = FFI::MemoryPointer.new(:uint)
61
64
 
62
- ret = bitcoinconsensus_verify_script(scriptPubKey, scriptPubKey.size, txTo, txTo.size, input_index, script_flags, error_ret)
65
+ ret = bitcoinconsensus_verify_script(
66
+ script_pub_key, script_pub_key.size, tx_to, tx_to.size, input_index, script_flags, error_ret
67
+ )
63
68
 
64
69
  case ret
65
70
  when 0
66
71
  false
67
72
  when 1
68
- (ERR_CODES[error_ret.read_int] == :ok) ? true : false
73
+ ERR_CODES[error_ret.read_int] == :ok
69
74
  else
70
- raise "error invalid result"
75
+ raise 'error invalid result'
71
76
  end
72
77
  end
73
-
74
78
  end
75
79
  end
@@ -1,388 +1,405 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # autoload when you need to re-generate a public_key from only its private_key.
4
- # ported from: https://github.com/sipa/bitcoin/blob/2d40fe4da9ea82af4b652b691a4185431d6e47a8/key.h
5
-
6
3
  require 'ffi'
7
4
 
8
5
  module Bitcoin
9
- module OpenSSL_EC
10
- extend FFI::Library
11
- if FFI::Platform.windows?
12
- ffi_lib 'libeay32', 'ssleay32'
13
- else
14
- ffi_lib [ 'libssl.so.1.0.0', 'ssl' ]
15
- end
16
-
17
- NID_secp256k1 = 714
18
- POINT_CONVERSION_COMPRESSED = 2
19
- POINT_CONVERSION_UNCOMPRESSED = 4
20
-
21
- attach_function :SSL_library_init, [], :int
22
- attach_function :ERR_load_crypto_strings, [], :void
23
- attach_function :SSL_load_error_strings, [], :void
24
- attach_function :RAND_poll, [], :int
25
-
26
- attach_function :BN_CTX_free, [:pointer], :int
27
- attach_function :BN_CTX_new, [], :pointer
28
- attach_function :BN_add, [:pointer, :pointer, :pointer], :int
29
- attach_function :BN_bin2bn, [:pointer, :int, :pointer], :pointer
30
- attach_function :BN_bn2bin, [:pointer, :pointer], :int
31
- attach_function :BN_cmp, [:pointer, :pointer], :int
32
- attach_function :BN_copy, [:pointer, :pointer], :pointer
33
- attach_function :BN_dup, [:pointer], :pointer
34
- attach_function :BN_free, [:pointer], :int
35
- attach_function :BN_mod_inverse, [:pointer, :pointer, :pointer, :pointer], :pointer
36
- attach_function :BN_mod_mul, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
37
- attach_function :BN_mod_sub, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
38
- attach_function :BN_mul_word, [:pointer, :int], :int
39
- attach_function :BN_new, [], :pointer
40
- attach_function :BN_rshift, [:pointer, :pointer, :int], :int
41
- attach_function :BN_rshift1, [:pointer, :pointer], :int
42
- attach_function :BN_set_word, [:pointer, :int], :int
43
- attach_function :BN_sub, [:pointer, :pointer, :pointer], :int
44
- attach_function :EC_GROUP_get_curve_GFp, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
45
- attach_function :EC_GROUP_get_degree, [:pointer], :int
46
- attach_function :EC_GROUP_get_order, [:pointer, :pointer, :pointer], :int
47
- attach_function :EC_KEY_free, [:pointer], :int
48
- attach_function :EC_KEY_get0_group, [:pointer], :pointer
49
- attach_function :EC_KEY_get0_private_key, [:pointer], :pointer
50
- attach_function :EC_KEY_new_by_curve_name, [:int], :pointer
51
- attach_function :EC_KEY_set_conv_form, [:pointer, :int], :void
52
- attach_function :EC_KEY_set_private_key, [:pointer, :pointer], :int
53
- attach_function :EC_KEY_set_public_key, [:pointer, :pointer], :int
54
- attach_function :EC_POINT_free, [:pointer], :int
55
- attach_function :EC_POINT_is_at_infinity, [:pointer, :pointer], :int
56
- attach_function :EC_POINT_mul, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
57
- attach_function :EC_POINT_new, [:pointer], :pointer
58
- attach_function :EC_POINT_set_compressed_coordinates_GFp, [:pointer, :pointer, :pointer, :int, :pointer], :int
59
- attach_function :d2i_ECPrivateKey, [:pointer, :pointer, :long], :pointer
60
- attach_function :i2d_ECPrivateKey, [:pointer, :pointer], :int
61
- attach_function :i2o_ECPublicKey, [:pointer, :pointer], :uint
62
- attach_function :EC_KEY_check_key, [:pointer], :uint
63
- attach_function :ECDSA_do_sign, [:pointer, :uint, :pointer], :pointer
64
- attach_function :BN_num_bits, [:pointer], :int
65
- attach_function :ECDSA_SIG_free, [:pointer], :void
66
- attach_function :EC_POINT_add, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
67
- attach_function :EC_POINT_point2hex, [:pointer, :pointer, :int, :pointer], :string
68
- attach_function :EC_POINT_hex2point, [:pointer, :string, :pointer, :pointer], :pointer
69
- attach_function :ECDSA_SIG_new, [], :pointer
70
- attach_function :d2i_ECDSA_SIG, [:pointer, :pointer, :long], :pointer
71
- attach_function :i2d_ECDSA_SIG, [:pointer, :pointer], :int
72
- attach_function :OPENSSL_free, :CRYPTO_free, [:pointer], :void
73
-
74
- def self.BN_num_bytes(ptr); (BN_num_bits(ptr) + 7) / 8; end
75
-
76
-
77
- # resolve public from private key, using ffi and libssl.so
78
- # example:
79
- # keypair = Bitcoin.generate_key; Bitcoin::OpenSSL_EC.regenerate_key(keypair.first) == keypair
80
- def self.regenerate_key(private_key)
81
- private_key = [private_key].pack("H*") if private_key.bytesize >= (32*2)
82
- private_key_hex = private_key.unpack("H*")[0]
83
-
84
- #private_key = FFI::MemoryPointer.new(:uint8, private_key.bytesize)
85
- # .put_bytes(0, private_key, 0, private_key.bytesize)
86
- private_key = FFI::MemoryPointer.from_string(private_key)
87
-
88
- init_ffi_ssl
89
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
90
- #priv_key = BN_bin2bn(private_key, private_key.size, BN_new())
91
- priv_key = BN_bin2bn(private_key, private_key.size-1, BN_new())
92
-
93
- group, order, ctx = EC_KEY_get0_group(eckey), BN_new(), BN_CTX_new()
94
- EC_GROUP_get_order(group, order, ctx)
95
-
96
- pub_key = EC_POINT_new(group)
97
- EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
98
- EC_KEY_set_private_key(eckey, priv_key)
99
- EC_KEY_set_public_key(eckey, pub_key)
100
-
101
- BN_free(order)
102
- BN_CTX_free(ctx)
103
- EC_POINT_free(pub_key)
104
- BN_free(priv_key)
105
-
106
-
107
- length = i2d_ECPrivateKey(eckey, nil)
108
- buf = FFI::MemoryPointer.new(:uint8, length)
109
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
110
- priv_hex = if i2d_ECPrivateKey(eckey, ptr) == length
111
- size = buf.get_array_of_uint8(8, 1)[0]
112
- buf.get_array_of_uint8(9, size).pack("C*").rjust(32, "\x00").unpack("H*")[0]
113
- #der_to_private_key( ptr.read_pointer.read_string(length).unpack("H*")[0] )
114
- end
115
-
116
- if priv_hex != private_key_hex
117
- raise "regenerated wrong private_key, raise here before generating a faulty public_key too!"
6
+ # autoload when you need to re-generate a public_key from only its private_key.
7
+ # ported from: https://github.com/sipa/bitcoin/blob/2d40fe4da9ea82af4b652b691a4185431d6e47a8/key.h
8
+ module OpenSSL_EC # rubocop:disable Naming/ClassAndModuleCamelCase
9
+ extend FFI::Library
10
+ if FFI::Platform.windows?
11
+ ffi_lib 'libeay32', 'ssleay32'
12
+ else
13
+ ffi_lib ['libssl.so.1.0.0', 'ssl']
118
14
  end
119
15
 
120
-
121
- length = i2o_ECPublicKey(eckey, nil)
122
- buf = FFI::MemoryPointer.new(:uint8, length)
123
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
124
- pub_hex = if i2o_ECPublicKey(eckey, ptr) == length
125
- buf.read_string(length).unpack("H*")[0]
16
+ NID_secp256k1 = 714 # rubocop:disable Naming/ConstantName
17
+ POINT_CONVERSION_COMPRESSED = 2
18
+ POINT_CONVERSION_UNCOMPRESSED = 4
19
+
20
+ attach_function :SSL_library_init, [], :int
21
+ attach_function :ERR_load_crypto_strings, [], :void
22
+ attach_function :SSL_load_error_strings, [], :void
23
+ attach_function :RAND_poll, [], :int
24
+
25
+ attach_function :BN_CTX_free, [:pointer], :int
26
+ attach_function :BN_CTX_new, [], :pointer
27
+ attach_function :BN_add, %i[pointer pointer pointer], :int
28
+ attach_function :BN_bin2bn, %i[pointer int pointer], :pointer
29
+ attach_function :BN_bn2bin, %i[pointer pointer], :int
30
+ attach_function :BN_cmp, %i[pointer pointer], :int
31
+ attach_function :BN_copy, %i[pointer pointer], :pointer
32
+ attach_function :BN_dup, [:pointer], :pointer
33
+ attach_function :BN_free, [:pointer], :int
34
+ attach_function :BN_mod_inverse, %i[pointer pointer pointer pointer], :pointer
35
+ attach_function :BN_mod_mul, %i[pointer pointer pointer pointer pointer], :int
36
+ attach_function :BN_mod_sub, %i[pointer pointer pointer pointer pointer], :int
37
+ attach_function :BN_mul_word, %i[pointer int], :int
38
+ attach_function :BN_new, [], :pointer
39
+ attach_function :BN_rshift, %i[pointer pointer int], :int
40
+ attach_function :BN_rshift1, %i[pointer pointer], :int
41
+ attach_function :BN_set_word, %i[pointer int], :int
42
+ attach_function :BN_sub, %i[pointer pointer pointer], :int
43
+ attach_function :EC_GROUP_get_curve_GFp, %i[pointer pointer pointer pointer pointer], :int
44
+ attach_function :EC_GROUP_get_degree, [:pointer], :int
45
+ attach_function :EC_GROUP_get_order, %i[pointer pointer pointer], :int
46
+ attach_function :EC_KEY_free, [:pointer], :int
47
+ attach_function :EC_KEY_get0_group, [:pointer], :pointer
48
+ attach_function :EC_KEY_get0_private_key, [:pointer], :pointer
49
+ attach_function :EC_KEY_new_by_curve_name, [:int], :pointer
50
+ attach_function :EC_KEY_set_conv_form, %i[pointer int], :void
51
+ attach_function :EC_KEY_set_private_key, %i[pointer pointer], :int
52
+ attach_function :EC_KEY_set_public_key, %i[pointer pointer], :int
53
+ attach_function :EC_POINT_free, [:pointer], :int
54
+ attach_function :EC_POINT_is_at_infinity, %i[pointer pointer], :int
55
+ attach_function :EC_POINT_mul, %i[pointer pointer pointer pointer pointer pointer], :int
56
+ attach_function :EC_POINT_new, [:pointer], :pointer
57
+ attach_function :EC_POINT_set_compressed_coordinates_GFp,
58
+ %i[pointer pointer pointer int pointer], :int
59
+ attach_function :d2i_ECPrivateKey, %i[pointer pointer long], :pointer
60
+ attach_function :i2d_ECPrivateKey, %i[pointer pointer], :int
61
+ attach_function :i2o_ECPublicKey, %i[pointer pointer], :uint
62
+ attach_function :EC_KEY_check_key, [:pointer], :uint
63
+ attach_function :ECDSA_do_sign, %i[pointer uint pointer], :pointer
64
+ attach_function :BN_num_bits, [:pointer], :int
65
+ attach_function :ECDSA_SIG_free, [:pointer], :void
66
+ attach_function :EC_POINT_add, %i[pointer pointer pointer pointer pointer], :int
67
+ attach_function :EC_POINT_point2hex, %i[pointer pointer int pointer], :string
68
+ attach_function :EC_POINT_hex2point, %i[pointer string pointer pointer], :pointer
69
+ attach_function :ECDSA_SIG_new, [], :pointer
70
+ attach_function :d2i_ECDSA_SIG, %i[pointer pointer long], :pointer
71
+ attach_function :i2d_ECDSA_SIG, %i[pointer pointer], :int
72
+ attach_function :OPENSSL_free, :CRYPTO_free, [:pointer], :void
73
+
74
+ def self.BN_num_bytes(ptr) # rubocop:disable Naming/MethodName
75
+ (BN_num_bits(ptr) + 7) / 8
126
76
  end
127
77
 
128
- EC_KEY_free(eckey)
129
-
130
- [ priv_hex, pub_hex ]
131
- end
132
-
133
- # extract private key from uncompressed DER format
134
- def self.der_to_private_key(der_hex)
135
- init_ffi_ssl
136
- #k = EC_KEY_new_by_curve_name(NID_secp256k1)
137
- #kp = FFI::MemoryPointer.new(:pointer).put_pointer(0, eckey)
138
-
139
- buf = FFI::MemoryPointer.from_string([der_hex].pack("H*"))
140
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
141
-
142
- #ec_key = d2i_ECPrivateKey(kp, ptr, buf.size-1)
143
- ec_key = d2i_ECPrivateKey(nil, ptr, buf.size-1)
144
- return nil if ec_key.null?
145
- bn = EC_KEY_get0_private_key(ec_key)
146
- BN_bn2bin(bn, buf)
147
- buf.read_string(32).unpack("H*")[0]
148
- end
78
+ # resolve public from private key, using ffi and libssl.so
79
+ # example:
80
+ # keypair = Bitcoin.generate_key; Bitcoin::OpenSSL_EC.regenerate_key(keypair.first) == keypair
81
+ def self.regenerate_key(private_key)
82
+ private_key = [private_key].pack('H*') if private_key.bytesize >= (32 * 2)
83
+ private_key_hex = private_key.unpack('H*')[0]
84
+
85
+ # private_key = FFI::MemoryPointer.new(:uint8, private_key.bytesize)
86
+ # .put_bytes(0, private_key, 0, private_key.bytesize)
87
+ private_key = FFI::MemoryPointer.from_string(private_key)
88
+
89
+ init_ffi_ssl
90
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
91
+ # priv_key = BN_bin2bn(private_key, private_key.size, BN_new())
92
+ priv_key = BN_bin2bn(private_key, private_key.size - 1, BN_new())
93
+
94
+ group = EC_KEY_get0_group(eckey)
95
+ order = BN_new()
96
+ ctx = BN_CTX_new()
97
+ EC_GROUP_get_order(group, order, ctx)
98
+
99
+ pub_key = EC_POINT_new(group)
100
+ EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
101
+ EC_KEY_set_private_key(eckey, priv_key)
102
+ EC_KEY_set_public_key(eckey, pub_key)
103
+
104
+ BN_free(order)
105
+ BN_CTX_free(ctx)
106
+ EC_POINT_free(pub_key)
107
+ BN_free(priv_key)
108
+
109
+ length = i2d_ECPrivateKey(eckey, nil)
110
+ buf = FFI::MemoryPointer.new(:uint8, length)
111
+ ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
112
+ priv_hex = if i2d_ECPrivateKey(eckey, ptr) == length
113
+ size = buf.get_array_of_uint8(8, 1)[0]
114
+ buf.get_array_of_uint8(9, size).pack('C*').rjust(32, "\x00").unpack('H*')[0]
115
+ # der_to_private_key( ptr.read_pointer.read_string(length).unpack("H*")[0] )
116
+ end
117
+
118
+ if priv_hex != private_key_hex
119
+ raise 'regenerated wrong private_key, raise here before generating a faulty public_key too!'
120
+ end
121
+
122
+ length = i2o_ECPublicKey(eckey, nil)
123
+ buf = FFI::MemoryPointer.new(:uint8, length)
124
+ ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
125
+ pub_hex = buf.read_string(length).unpack('H*')[0] if i2o_ECPublicKey(eckey, ptr) == length
149
126
 
150
- # Given the components of a signature and a selector value, recover and
151
- # return the public key that generated the signature according to the
152
- # algorithm in SEC1v2 section 4.1.6.
153
- #
154
- # rec_id is an index from 0 to 3 that indicates which of the 4 possible
155
- # keys is the correct one. Because the key recovery operation yields
156
- # multiple potential keys, the correct key must either be stored alongside
157
- # the signature, or you must be willing to try each rec_id in turn until
158
- # you find one that outputs the key you are expecting.
159
- #
160
- # If this method returns nil, it means recovery was not possible and rec_id
161
- # should be iterated.
162
- #
163
- # Given the above two points, a correct usage of this method is inside a
164
- # for loop from 0 to 3, and if the output is nil OR a key that is not the
165
- # one you expect, you try again with the next rec_id.
166
- #
167
- # message_hash = hash of the signed message.
168
- # signature = the R and S components of the signature, wrapped.
169
- # rec_id = which possible key to recover.
170
- # is_compressed = whether or not the original pubkey was compressed.
171
- def self.recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
172
- return nil if rec_id < 0 or signature.bytesize != 65
173
- init_ffi_ssl
174
-
175
- signature = FFI::MemoryPointer.from_string(signature)
176
- #signature_bn = BN_bin2bn(signature, 65, BN_new())
177
- r = BN_bin2bn(signature[1], 32, BN_new())
178
- s = BN_bin2bn(signature[33], 32, BN_new())
179
-
180
- n, i = 0, rec_id / 2
181
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
182
-
183
- EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
184
-
185
- group = EC_KEY_get0_group(eckey)
186
- order = BN_new()
187
- EC_GROUP_get_order(group, order, nil)
188
- x = BN_dup(order)
189
- BN_mul_word(x, i)
190
- BN_add(x, x, r)
191
-
192
- field = BN_new()
193
- EC_GROUP_get_curve_GFp(group, field, nil, nil, nil)
194
-
195
- if BN_cmp(x, field) >= 0
196
- [r, s, order, x, field].each{|i| BN_free(i) }
197
127
  EC_KEY_free(eckey)
198
- return nil
128
+
129
+ [priv_hex, pub_hex]
199
130
  end
200
131
 
201
- big_r = EC_POINT_new(group)
202
- EC_POINT_set_compressed_coordinates_GFp(group, big_r, x, rec_id % 2, nil)
203
-
204
- big_q = EC_POINT_new(group)
205
- n = EC_GROUP_get_degree(group)
206
- e = BN_bin2bn(message_hash, message_hash.bytesize, BN_new())
207
- BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
208
-
209
- ctx = BN_CTX_new()
210
- zero, rr, sor, eor = BN_new(), BN_new(), BN_new(), BN_new()
211
- BN_set_word(zero, 0)
212
- BN_mod_sub(e, zero, e, order, ctx)
213
- BN_mod_inverse(rr, r, order, ctx)
214
- BN_mod_mul(sor, s, rr, order, ctx)
215
- BN_mod_mul(eor, e, rr, order, ctx)
216
- EC_POINT_mul(group, big_q, eor, big_r, sor, ctx)
217
- EC_KEY_set_public_key(eckey, big_q)
218
- BN_CTX_free(ctx)
219
-
220
- [r, s, order, x, field, e, zero, rr, sor, eor].each{|i| BN_free(i) }
221
- [big_r, big_q].each{|i| EC_POINT_free(i) }
222
-
223
- length = i2o_ECPublicKey(eckey, nil)
224
- buf = FFI::MemoryPointer.new(:uint8, length)
225
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
226
- pub_hex = if i2o_ECPublicKey(eckey, ptr) == length
227
- buf.read_string(length).unpack("H*")[0]
132
+ # extract private key from uncompressed DER format
133
+ def self.der_to_private_key(der_hex)
134
+ init_ffi_ssl
135
+ # k = EC_KEY_new_by_curve_name(NID_secp256k1)
136
+ # kp = FFI::MemoryPointer.new(:pointer).put_pointer(0, eckey)
137
+
138
+ buf = FFI::MemoryPointer.from_string([der_hex].pack('H*'))
139
+ ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
140
+
141
+ # ec_key = d2i_ECPrivateKey(kp, ptr, buf.size-1)
142
+ ec_key = d2i_ECPrivateKey(nil, ptr, buf.size - 1)
143
+ return nil if ec_key.null?
144
+ bn = EC_KEY_get0_private_key(ec_key)
145
+ BN_bn2bin(bn, buf)
146
+ buf.read_string(32).unpack('H*')[0]
228
147
  end
229
148
 
230
- EC_KEY_free(eckey)
149
+ # Given the components of a signature and a selector value, recover and
150
+ # return the public key that generated the signature according to the
151
+ # algorithm in SEC1v2 section 4.1.6.
152
+ #
153
+ # rec_id is an index from 0 to 3 that indicates which of the 4 possible
154
+ # keys is the correct one. Because the key recovery operation yields
155
+ # multiple potential keys, the correct key must either be stored alongside
156
+ # the signature, or you must be willing to try each rec_id in turn until
157
+ # you find one that outputs the key you are expecting.
158
+ #
159
+ # If this method returns nil, it means recovery was not possible and rec_id
160
+ # should be iterated.
161
+ #
162
+ # Given the above two points, a correct usage of this method is inside a
163
+ # for loop from 0 to 3, and if the output is nil OR a key that is not the
164
+ # one you expect, you try again with the next rec_id.
165
+ #
166
+ # message_hash = hash of the signed message.
167
+ # signature = the R and S components of the signature, wrapped.
168
+ # rec_id = which possible key to recover.
169
+ # is_compressed = whether or not the original pubkey was compressed.
170
+ def self.recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
171
+ return nil if rec_id < 0 || signature.bytesize != 65
172
+ init_ffi_ssl
173
+
174
+ signature = FFI::MemoryPointer.from_string(signature)
175
+ # signature_bn = BN_bin2bn(signature, 65, BN_new())
176
+ r = BN_bin2bn(signature[1], 32, BN_new())
177
+ s = BN_bin2bn(signature[33], 32, BN_new())
178
+
179
+ i = rec_id / 2
180
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
181
+
182
+ EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
183
+
184
+ group = EC_KEY_get0_group(eckey)
185
+ order = BN_new()
186
+ EC_GROUP_get_order(group, order, nil)
187
+ x = BN_dup(order)
188
+ BN_mul_word(x, i)
189
+ BN_add(x, x, r)
190
+
191
+ field = BN_new()
192
+ EC_GROUP_get_curve_GFp(group, field, nil, nil, nil)
193
+
194
+ if BN_cmp(x, field) >= 0
195
+ [r, s, order, x, field].each { |item| BN_free(item) }
196
+ EC_KEY_free(eckey)
197
+ return nil
198
+ end
199
+
200
+ big_r = EC_POINT_new(group)
201
+ EC_POINT_set_compressed_coordinates_GFp(group, big_r, x, rec_id % 2, nil)
202
+
203
+ big_q = EC_POINT_new(group)
204
+ n = EC_GROUP_get_degree(group)
205
+ e = BN_bin2bn(message_hash, message_hash.bytesize, BN_new())
206
+ BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
207
+
208
+ ctx = BN_CTX_new()
209
+ zero = BN_new()
210
+ rr = BN_new()
211
+ sor = BN_new()
212
+ eor = BN_new()
213
+ BN_set_word(zero, 0)
214
+ BN_mod_sub(e, zero, e, order, ctx)
215
+ BN_mod_inverse(rr, r, order, ctx)
216
+ BN_mod_mul(sor, s, rr, order, ctx)
217
+ BN_mod_mul(eor, e, rr, order, ctx)
218
+ EC_POINT_mul(group, big_q, eor, big_r, sor, ctx)
219
+ EC_KEY_set_public_key(eckey, big_q)
220
+ BN_CTX_free(ctx)
221
+
222
+ [r, s, order, x, field, e, zero, rr, sor, eor].each { |item| BN_free(item) }
223
+ [big_r, big_q].each { |item| EC_POINT_free(item) }
224
+
225
+ length = i2o_ECPublicKey(eckey, nil)
226
+ buf = FFI::MemoryPointer.new(:uint8, length)
227
+ ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
228
+ pub_hex = buf.read_string(length).unpack('H*')[0] if i2o_ECPublicKey(eckey, ptr) == length
231
229
 
232
- pub_hex
233
- end
230
+ EC_KEY_free(eckey)
234
231
 
235
- # Regenerate a DER-encoded signature such that the S-value complies with the BIP62
236
- # specification.
237
- #
238
- def self.signature_to_low_s(signature)
239
- init_ffi_ssl
240
-
241
- buf = FFI::MemoryPointer.new(:uint8, 34)
242
- temp = signature.unpack("C*")
243
- length_r = temp[3]
244
- length_s = temp[5+length_r]
245
- sig = FFI::MemoryPointer.from_string(signature)
246
-
247
- # Calculate the lower s value
248
- s = BN_bin2bn(sig[6 + length_r], length_s, BN_new())
249
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
250
- group, order, halforder, ctx = EC_KEY_get0_group(eckey), BN_new(), BN_new(), BN_CTX_new()
251
-
252
- EC_GROUP_get_order(group, order, ctx)
253
- BN_rshift1(halforder, order)
254
- if BN_cmp(s, halforder) > 0
255
- BN_sub(s, order, s)
232
+ pub_hex
256
233
  end
257
234
 
258
- BN_free(halforder)
259
- BN_free(order)
260
- BN_CTX_free(ctx)
261
-
262
- length_s = BN_bn2bin(s, buf)
263
- # p buf.read_string(length_s).unpack("H*")
264
-
265
- # Re-encode the signature in DER format
266
- sig = [0x30, 0, 0x02, length_r]
267
- sig.concat(temp.slice(4, length_r))
268
- sig << 0x02
269
- sig << length_s
270
- sig.concat(buf.read_string(length_s).unpack("C*"))
271
- sig[1] = sig.size - 2
235
+ # Regenerate a DER-encoded signature such that the S-value complies with the BIP62
236
+ # specification.
237
+ #
238
+ def self.signature_to_low_s(signature)
239
+ init_ffi_ssl
240
+
241
+ buf = FFI::MemoryPointer.new(:uint8, 34)
242
+ temp = signature.unpack('C*')
243
+ length_r = temp[3]
244
+ length_s = temp[5 + length_r]
245
+ sig = FFI::MemoryPointer.from_string(signature)
246
+
247
+ # Calculate the lower s value
248
+ s = BN_bin2bn(sig[6 + length_r], length_s, BN_new())
249
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
250
+ group = EC_KEY_get0_group(eckey)
251
+ order = BN_new()
252
+ halforder = BN_new()
253
+ ctx = BN_CTX_new()
254
+
255
+ EC_GROUP_get_order(group, order, ctx)
256
+ BN_rshift1(halforder, order)
257
+ BN_sub(s, order, s) if BN_cmp(s, halforder) > 0
258
+
259
+ BN_free(halforder)
260
+ BN_free(order)
261
+ BN_CTX_free(ctx)
262
+
263
+ length_s = BN_bn2bin(s, buf)
264
+ # p buf.read_string(length_s).unpack("H*")
265
+
266
+ # Re-encode the signature in DER format
267
+ sig = [0x30, 0, 0x02, length_r]
268
+ sig.concat(temp.slice(4, length_r))
269
+ sig << 0x02
270
+ sig << length_s
271
+ sig.concat(buf.read_string(length_s).unpack('C*'))
272
+ sig[1] = sig.size - 2
273
+
274
+ BN_free(s)
275
+ EC_KEY_free(eckey)
272
276
 
273
- BN_free(s)
274
- EC_KEY_free(eckey)
277
+ sig.pack('C*')
278
+ end
275
279
 
276
- sig.pack("C*")
277
- end
280
+ def self.sign_compact(hash, private_key, public_key_hex = nil, pubkey_compressed = nil)
281
+ msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
278
282
 
279
- def self.sign_compact(hash, private_key, public_key_hex = nil, pubkey_compressed = nil)
280
- msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
283
+ private_key = [private_key].pack('H*') if private_key.bytesize >= 64
284
+ private_key_hex = private_key.unpack('H*')[0]
281
285
 
282
- private_key = [private_key].pack("H*") if private_key.bytesize >= 64
283
- private_key_hex = private_key.unpack("H*")[0]
286
+ public_key_hex ||= regenerate_key(private_key_hex).last
287
+ pubkey_compressed ||= public_key_hex[0..1] != '04'
284
288
 
285
- public_key_hex = regenerate_key(private_key_hex).last unless public_key_hex
286
- pubkey_compressed = (public_key_hex[0..1] == "04" ? false : true) unless pubkey_compressed
289
+ init_ffi_ssl
290
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
291
+ priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
287
292
 
288
- init_ffi_ssl
289
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
290
- priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
293
+ group = EC_KEY_get0_group(eckey)
294
+ order = BN_new()
295
+ ctx = BN_CTX_new()
296
+ EC_GROUP_get_order(group, order, ctx)
291
297
 
292
- group, order, ctx = EC_KEY_get0_group(eckey), BN_new(), BN_CTX_new()
293
- EC_GROUP_get_order(group, order, ctx)
298
+ pub_key = EC_POINT_new(group)
299
+ EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
300
+ EC_KEY_set_private_key(eckey, priv_key)
301
+ EC_KEY_set_public_key(eckey, pub_key)
294
302
 
295
- pub_key = EC_POINT_new(group)
296
- EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
297
- EC_KEY_set_private_key(eckey, priv_key)
298
- EC_KEY_set_public_key(eckey, pub_key)
303
+ signature = ECDSA_do_sign(msg32, msg32.size, eckey)
299
304
 
300
- signature = ECDSA_do_sign(msg32, msg32.size, eckey)
305
+ BN_free(order)
306
+ BN_CTX_free(ctx)
307
+ EC_POINT_free(pub_key)
308
+ BN_free(priv_key)
309
+ EC_KEY_free(eckey)
301
310
 
302
- BN_free(order)
303
- BN_CTX_free(ctx)
304
- EC_POINT_free(pub_key)
305
- BN_free(priv_key)
306
- EC_KEY_free(eckey)
311
+ buf = FFI::MemoryPointer.new(:uint8, 32)
312
+ head = nil
313
+ r, s = signature.get_array_of_pointer(0, 2).map do |i|
314
+ BN_bn2bin(i, buf)
315
+ buf.read_string(BN_num_bytes(i)).rjust(32, "\x00")
316
+ end
317
+
318
+ rec_id = nil
319
+ if signature.get_array_of_pointer(0, 2).all? { |i| BN_num_bits(i) <= 256 }
320
+ 4.times do |i|
321
+ head = [27 + i + (pubkey_compressed ? 4 : 0)].pack('C')
322
+ recovered_key = recover_public_key_from_signature(
323
+ msg32.read_string(32), [head, r, s].join, i, pubkey_compressed
324
+ )
325
+ if public_key_hex == recovered_key
326
+ rec_id = i
327
+ break
328
+ end
329
+ end
330
+ end
307
331
 
308
- buf, rec_id, head = FFI::MemoryPointer.new(:uint8, 32), nil, nil
309
- r, s = signature.get_array_of_pointer(0, 2).map{|i| BN_bn2bin(i, buf); buf.read_string(BN_num_bytes(i)).rjust(32, "\x00") }
332
+ ECDSA_SIG_free(signature)
310
333
 
311
- if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
312
- 4.times{|i|
313
- head = [ 27 + i + (pubkey_compressed ? 4 : 0) ].pack("C")
314
- if public_key_hex == recover_public_key_from_signature(msg32.read_string(32), [head, r, s].join, i, pubkey_compressed)
315
- rec_id = i; break
316
- end
317
- }
334
+ [head, [r, s]].join if rec_id
318
335
  end
319
336
 
320
- ECDSA_SIG_free(signature)
321
-
322
- [ head, [r,s] ].join if rec_id
323
- end
337
+ def self.recover_compact(hash, signature)
338
+ return false if signature.bytesize != 65
339
+ msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
324
340
 
325
- def self.recover_compact(hash, signature)
326
- return false if signature.bytesize != 65
327
- msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
341
+ version = signature.unpack('C')[0]
342
+ return false if version < 27 || version > 34
328
343
 
329
- version = signature.unpack('C')[0]
330
- return false if version < 27 or version > 34
344
+ compressed = version >= 31
345
+ version -= 4 if compressed
331
346
 
332
- compressed = (version >= 31) ? (version -= 4; true) : false
333
- pubkey = recover_public_key_from_signature(msg32.read_string(32), signature, version-27, compressed)
334
- end
347
+ recover_public_key_from_signature(msg32.read_string(32), signature, version - 27, compressed)
348
+ end
335
349
 
336
- # lifted from https://github.com/GemHQ/money-tree
337
- def self.ec_add(point_0, point_1)
338
- init_ffi_ssl
350
+ # lifted from https://github.com/GemHQ/money-tree
351
+ def self.ec_add(point0, point1)
352
+ init_ffi_ssl
339
353
 
340
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
341
- group = EC_KEY_get0_group(eckey)
354
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
355
+ group = EC_KEY_get0_group(eckey)
342
356
 
343
- point_0_hex = point_0.to_bn.to_s(16)
344
- point_0_pt = EC_POINT_hex2point(group, point_0_hex, nil, nil)
345
- point_1_hex = point_1.to_bn.to_s(16)
346
- point_1_pt = EC_POINT_hex2point(group, point_1_hex, nil, nil)
357
+ point_0_hex = point0.to_bn.to_s(16)
358
+ point_0_pt = EC_POINT_hex2point(group, point_0_hex, nil, nil)
359
+ point_1_hex = point1.to_bn.to_s(16)
360
+ point_1_pt = EC_POINT_hex2point(group, point_1_hex, nil, nil)
347
361
 
348
- sum_point = EC_POINT_new(group)
349
- success = EC_POINT_add(group, sum_point, point_0_pt, point_1_pt, nil)
350
- hex = EC_POINT_point2hex(group, sum_point, POINT_CONVERSION_UNCOMPRESSED, nil)
351
- EC_KEY_free(eckey)
352
- EC_POINT_free(sum_point)
353
- hex
354
- end
362
+ sum_point = EC_POINT_new(group)
363
+ EC_POINT_add(group, sum_point, point_0_pt, point_1_pt, nil)
364
+ hex = EC_POINT_point2hex(group, sum_point, POINT_CONVERSION_UNCOMPRESSED, nil)
365
+ EC_KEY_free(eckey)
366
+ EC_POINT_free(sum_point)
367
+ hex
368
+ end
355
369
 
356
- # repack signature for OpenSSL 1.0.1k handling of DER signatures
357
- # https://github.com/bitcoin/bitcoin/pull/5634/files
358
- def self.repack_der_signature(signature)
359
- init_ffi_ssl
370
+ # repack signature for OpenSSL 1.0.1k handling of DER signatures
371
+ # https://github.com/bitcoin/bitcoin/pull/5634/files
372
+ def self.repack_der_signature(signature)
373
+ init_ffi_ssl
360
374
 
361
- return false if signature.empty?
375
+ return false if signature.empty?
362
376
 
363
- # New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
364
- norm_der = FFI::MemoryPointer.new(:pointer)
365
- sig_ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, FFI::MemoryPointer.from_string(signature))
377
+ # New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
378
+ norm_der = FFI::MemoryPointer.new(:pointer)
379
+ sig_ptr = FFI::MemoryPointer.new(:pointer).put_pointer(
380
+ 0, FFI::MemoryPointer.from_string(signature)
381
+ )
366
382
 
367
- norm_sig = d2i_ECDSA_SIG(nil, sig_ptr, signature.bytesize)
383
+ norm_sig = d2i_ECDSA_SIG(nil, sig_ptr, signature.bytesize)
368
384
 
369
- derlen = i2d_ECDSA_SIG(norm_sig, norm_der)
370
- ECDSA_SIG_free(norm_sig)
371
- return false if derlen <= 0
385
+ derlen = i2d_ECDSA_SIG(norm_sig, norm_der)
386
+ ECDSA_SIG_free(norm_sig)
387
+ return false if derlen <= 0
372
388
 
373
- ret = norm_der.read_pointer.read_string(derlen)
374
- OPENSSL_free(norm_der.read_pointer)
389
+ ret = norm_der.read_pointer.read_string(derlen)
390
+ OPENSSL_free(norm_der.read_pointer)
375
391
 
376
- ret
377
- end
392
+ ret
393
+ end
378
394
 
379
- def self.init_ffi_ssl
380
- return if @ssl_loaded
381
- SSL_library_init()
382
- ERR_load_crypto_strings()
383
- SSL_load_error_strings()
384
- RAND_poll()
385
- @ssl_loaded = true
395
+ def self.init_ffi_ssl
396
+ @ssl_loaded ||= false
397
+ return if @ssl_loaded
398
+ SSL_library_init()
399
+ ERR_load_crypto_strings()
400
+ SSL_load_error_strings()
401
+ RAND_poll()
402
+ @ssl_loaded = true
403
+ end
386
404
  end
387
405
  end
388
- end