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