bitcoin-ruby 0.0.5 → 0.0.6
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 +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +2 -2
- data/COPYING +1 -1
- data/Gemfile +5 -11
- data/README.rdoc +11 -5
- data/Rakefile +5 -0
- data/bin/bitcoin_node +11 -29
- data/bin/bitcoin_node_cli +81 -0
- data/bin/bitcoin_wallet +9 -6
- data/doc/NODE.rdoc +79 -26
- data/examples/bbe_verify_tx.rb +1 -1
- data/examples/index_nhash.rb +24 -0
- data/examples/reindex_p2sh_addrs.rb +44 -0
- data/lib/bitcoin.rb +135 -20
- data/lib/bitcoin/builder.rb +233 -63
- data/lib/bitcoin/key.rb +89 -16
- data/lib/bitcoin/litecoin.rb +13 -11
- data/lib/bitcoin/namecoin.rb +5 -4
- data/lib/bitcoin/network/command_client.rb +23 -13
- data/lib/bitcoin/network/command_handler.rb +336 -131
- data/lib/bitcoin/network/connection_handler.rb +14 -13
- data/lib/bitcoin/network/node.rb +61 -20
- data/lib/bitcoin/protocol.rb +5 -1
- data/lib/bitcoin/protocol/block.rb +15 -3
- data/lib/bitcoin/protocol/parser.rb +3 -3
- data/lib/bitcoin/protocol/tx.rb +82 -20
- data/lib/bitcoin/protocol/txin.rb +7 -0
- data/lib/bitcoin/protocol/txout.rb +12 -9
- data/lib/bitcoin/script.rb +329 -75
- data/lib/bitcoin/storage/dummy/dummy_store.rb +23 -4
- data/lib/bitcoin/storage/models.rb +6 -11
- data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +14 -0
- data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +31 -0
- data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +16 -0
- data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +31 -0
- data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +56 -0
- data/lib/bitcoin/storage/sequel/sequel_store.rb +168 -70
- data/lib/bitcoin/storage/storage.rb +161 -97
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +1 -1
- data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +14 -0
- data/lib/bitcoin/storage/utxo/utxo_store.rb +25 -12
- data/lib/bitcoin/validation.rb +87 -56
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bitcoin_spec.rb +38 -0
- data/spec/bitcoin/builder_spec.rb +177 -0
- data/spec/bitcoin/fixtures/litecoin-tx-f5aa30f574e3b6f1a3d99c07a6356ba812aabb9661e1d5f71edff828cbd5c996.json +259 -0
- data/spec/bitcoin/fixtures/rawblock-testnet-265322.bin +0 -0
- data/spec/bitcoin/fixtures/tx-0295028ef826b2a188409cb905b631faebb9bb3cdf14510571c5f4bd8591338f.json +64 -0
- data/spec/bitcoin/fixtures/tx-03339a725007a279484fb6f5361f522dd1cf4d0923d30e6b973290dba4275f92.json +64 -0
- data/spec/bitcoin/fixtures/tx-0ce7e5238fbdb6c086cf1b384b21b827e91cc23f360417265874a5a0d86ce367.json +64 -0
- data/spec/bitcoin/fixtures/tx-0ef34c49f630aea17df0080728b0fc67bf5f87fbda936934a4b11b4a69d7821e.json +64 -0
- data/spec/bitcoin/fixtures/tx-1129d2a8bd5bb3a81e54dc96a90f1f6b2544575748caa17243470935c5dd91b7.json +28 -0
- data/spec/bitcoin/fixtures/tx-19aa42fee0fa57c45d3b16488198b27caaacc4ff5794510d0c17f173f05587ff.json +23 -0
- data/spec/bitcoin/fixtures/tx-1a4f3b9dc4494aeedeb39f30dd37e60541b2abe3ed4977992017cc0ad4f44956.json +64 -0
- data/spec/bitcoin/fixtures/tx-1f9191dcf2b1844ca28c6ef4b969e1d5fab70a5e3c56b7007949e55851cb0c4f.json +64 -0
- data/spec/bitcoin/fixtures/tx-22cd5fef23684d7b304e119bedffde6f54538d3d54a5bfa237e20dc2d9b4b5ad.json +64 -0
- data/spec/bitcoin/fixtures/tx-2958fb00b4fd6fe0353503b886eb9a193d502f4fd5fc042d5e03216ba918bbd6.json +64 -0
- data/spec/bitcoin/fixtures/tx-29f277145749ad6efbed3ae6ce301f8d33c585ec26b7c044ad93c2f866e9e942.json +64 -0
- data/spec/bitcoin/fixtures/tx-2c5e5376c20e9cc78d0fb771730e5d840cc2096eff0ef045b599fe92475ace1c.json +28 -0
- data/spec/bitcoin/fixtures/tx-2c63aa814701cef5dbd4bbaddab3fea9117028f2434dddcdab8339141e9b14d1.json +30 -0
- data/spec/bitcoin/fixtures/tx-326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e.json +23 -0
- data/spec/bitcoin/fixtures/tx-345bed8785c3282a264ffb0dbee61cde54854f10e16f1b3e75b7f2d9f62946f2.json +64 -0
- data/spec/bitcoin/fixtures/tx-39ba7440b7103557560cc8ce258009936796485aaf8b478e66ab4cb97c66e31b.json +32 -0
- data/spec/bitcoin/fixtures/tx-3a04d57a833367f1655cc5ec3beb587888ef4977a86caa8c8ad4ba7cc717eae7.json +64 -0
- data/spec/bitcoin/fixtures/tx-4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9.json +38 -0
- data/spec/bitcoin/fixtures/tx-46224764c7870f95b58f155bce1e38d4da8e99d42dbb632d0dd7c07e092ee5aa.json +23 -0
- data/spec/bitcoin/fixtures/tx-5df1375ffe61ac35ca178ebb0cab9ea26dedbd0e96005dfcee7e379fa513232f.json +30 -0
- data/spec/bitcoin/fixtures/tx-62d9a565bd7b5344c5352e3e9e5f40fa4bbd467fa19c87357216ec8777ba1cce.json +64 -0
- data/spec/bitcoin/fixtures/tx-6327783a064d4e350c454ad5cd90201aedf65b1fc524e73709c52f0163739190.json +23 -0
- data/spec/bitcoin/fixtures/tx-6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba.json +27 -0
- data/spec/bitcoin/fixtures/tx-6aaf18b9f1283b939d8e5d40ff5f8a435229f4178372659cc3a0bce4e262bf78.json +28 -0
- data/spec/bitcoin/fixtures/tx-6b48bba6f6d2286d7ec0883c0fc3085955090813a4c94980466611c798b868cc.json +64 -0
- data/spec/bitcoin/fixtures/tx-70cfbc6690f9ab46712db44e3079ac227962b2771a9341d4233d898b521619ef.json +40 -0
- data/spec/bitcoin/fixtures/tx-7a1a9db42f065f75110fcdb1bc415549c8ef7670417ba1d35a67f1b8adc562c1.json +64 -0
- data/spec/bitcoin/fixtures/tx-9a768fc7d0c4bdc86e25154357ef7c0063ca21310e5740a2f12f90b7455184a7.json +64 -0
- data/spec/bitcoin/fixtures/tx-9cad8d523a0694f2509d092c39cebc8046adae62b4e4297102d568191d9478d8.json +64 -0
- data/spec/bitcoin/fixtures/tx-9e052eb694bd7e15906433f064dff0161a12fd325c1124537766377004023c6f.json +64 -0
- data/spec/bitcoin/fixtures/tx-a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944.json +23 -0
- data/spec/bitcoin/fixtures/tx-aab7ef280abbb9cc6fbaf524d2645c3daf4fcca2b3f53370e618d9cedf65f1f8.json +23 -0
- data/spec/bitcoin/fixtures/tx-ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742.json +27 -0
- data/spec/bitcoin/fixtures/tx-ad4bcf3241e5d2ad140564e20db3567d41594cf4c2012433fe46a2b70e0d87b8.json +64 -0
- data/spec/bitcoin/fixtures/tx-b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9.json +27 -0
- data/spec/bitcoin/fixtures/tx-b8fd633e7713a43d5ac87266adc78444669b987a56b3a65fb92d58c2c4b0e84d.json +28 -0
- data/spec/bitcoin/fixtures/tx-bbca0628c42cb8bf7c3f4b2ad688fa56da5308dd2a10255da89fb1f46e6e413d.json +36 -0
- data/spec/bitcoin/fixtures/tx-bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224.json +23 -0
- data/spec/bitcoin/fixtures/tx-c192b74844e4837a34c4a5a97b438f1c111405b01b99e2d12b7c96d07fc74c04.json +28 -0
- data/spec/bitcoin/fixtures/tx-e335562f7e297aadeed88e5954bc4eeb8dc00b31d829eedb232e39d672b0c009.json +406 -0
- data/spec/bitcoin/fixtures/tx-eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb.json +35 -0
- data/spec/bitcoin/fixtures/tx-fee1b9b85531c8fb6cd7831f83490c7f2aa768b6eefe29854ef5e89ce7b9ecb1.json +64 -0
- data/spec/bitcoin/fixtures/txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin +1 -0
- data/spec/bitcoin/helpers/fake_blockchain.rb +183 -0
- data/spec/bitcoin/key_spec.rb +79 -8
- data/spec/bitcoin/namecoin_spec.rb +1 -1
- data/spec/bitcoin/node/command_api_spec.rb +373 -86
- data/spec/bitcoin/performance/storage_spec.rb +41 -0
- data/spec/bitcoin/protocol/addr_spec.rb +7 -5
- data/spec/bitcoin/protocol/aux_pow_spec.rb +1 -0
- data/spec/bitcoin/protocol/block_spec.rb +6 -0
- data/spec/bitcoin/protocol/tx_spec.rb +184 -1
- data/spec/bitcoin/protocol/txin_spec.rb +27 -0
- data/spec/bitcoin/protocol/txout_spec.rb +27 -0
- data/spec/bitcoin/script/opcodes_spec.rb +74 -3
- data/spec/bitcoin/script/script_spec.rb +271 -0
- data/spec/bitcoin/spec_helper.rb +34 -6
- data/spec/bitcoin/storage/models_spec.rb +104 -0
- data/spec/bitcoin/storage/reorg_spec.rb +42 -11
- data/spec/bitcoin/storage/storage_spec.rb +58 -15
- data/spec/bitcoin/storage/validation_spec.rb +44 -14
- data/spec/bitcoin/wallet/keygenerator_spec.rb +6 -3
- data/spec/bitcoin/wallet/keystore_spec.rb +3 -3
- data/spec/bitcoin/wallet/wallet_spec.rb +87 -89
- metadata +117 -11
|
@@ -13,12 +13,14 @@ describe 'Bitcoin::Script' do
|
|
|
13
13
|
"524104573b6e9f3a714440048a7b87d606bcbf9e45b8586e70a67a3665ea720c095658471a523e5d923f3f3e015626e7c900bd08560ddffeb17d33c5b52c96edb875954104039c2f4e413a26901e67ad4adbb6a4759af87bc16c7120459ecc9482fed3dd4a4502947f7b4c7782dcadc2bed513ed14d5e770452b97ae246ac2030f13b80a5141048b0f9d04e495c3c754f8c3c109196d713d0778882ef098f785570ee6043f8c192d8f84df43ebafbcc168f5d95a074dc4010b62c003e560abc163c312966b74b653ae", # multisig 2 of 3
|
|
14
14
|
"5141040ee607b584b36e995f2e96dec35457dbb40845d0ce0782c84002134e816a6b8cbc65e9eed047ae05e10760e4113f690fd49ad73b86b04a1d7813d843f8690ace4104220a78f5f6741bb0739675c2cc200643516b02cfdfda5cba21edeaa62c0f954936b30dfd956e3e99af0a8e7665cff6ac5b429c54c418184c81fbcd4bde4088f552ae", # multisig 1 of 2
|
|
15
15
|
"a9149471864495192e39f5f74574b6c8c513588a820487", # p2sh
|
|
16
|
+
"6a04deadbeef" # OP_RETURN deadbeef
|
|
16
17
|
].map{|s|[s].pack("H*")}
|
|
17
18
|
PUBKEYS = [
|
|
18
19
|
"04fb0123fe2c399981bc77d522e2ae3268d2ab15e9a84ae49338a4b1db3886a1ea04cdab955d81e9fa1fcb0c062cb9a5af1ad5dd5064f4afcca322402b07030ec2",
|
|
19
20
|
"0423b8161514560bc8638054b6637ab78f400b24e5694ec8061db635d1f28a17902b14dbf4f80780da659ab24f11ded3095c780452a4004c30ab58dffac33d839a",
|
|
20
21
|
"04f43e76afac66bf3927638b6c4f7e324513ce56d2d658ac9d24c420d09993a4464eea6141a68a4748c092ad0e8f4ac29c4a2f661ef4d22b21f20110f42fcd6f6d",
|
|
21
22
|
]
|
|
23
|
+
|
|
22
24
|
describe "serialization" do
|
|
23
25
|
it '#to_string' do
|
|
24
26
|
Script.new(SCRIPT[0]).to_string.should ==
|
|
@@ -199,6 +201,16 @@ describe 'Bitcoin::Script' do
|
|
|
199
201
|
.should == ["1JiaVc3N3U3CwwcLtzNX1Q4eYfeYxVjtuj",
|
|
200
202
|
"19Fm2gY7qDTXriNTEhFY2wjxbHna3Gvenk", "1B6k6g1d2L975i7beAbiBRxfBWhxomPxvy"]
|
|
201
203
|
end
|
|
204
|
+
|
|
205
|
+
it "should get op_return data" do
|
|
206
|
+
Script.new(SCRIPT[6]).get_op_return_data.should == "deadbeef"
|
|
207
|
+
Script.new(SCRIPT[1]).get_op_return_data.should == nil
|
|
208
|
+
Script.from_string("OP_RETURN").get_op_return_data.should == nil
|
|
209
|
+
Script.from_string("OP_RETURN dead beef").get_op_return_data.should == nil
|
|
210
|
+
Script.from_string("OP_RETURN deadbeef").get_op_return_data.should == "deadbeef"
|
|
211
|
+
Script.from_string("OP_RETURN OP_CHECKSIG").get_op_return_data.should == "ac00"
|
|
212
|
+
end
|
|
213
|
+
|
|
202
214
|
end
|
|
203
215
|
|
|
204
216
|
describe "determine type" do
|
|
@@ -210,6 +222,7 @@ describe 'Bitcoin::Script' do
|
|
|
210
222
|
Script.new(SCRIPT[3]).is_standard?.should == true
|
|
211
223
|
Script.new(SCRIPT[4]).is_standard?.should == true
|
|
212
224
|
Script.new(SCRIPT[5]).is_standard?.should == true
|
|
225
|
+
Script.new(SCRIPT[6]).is_standard?.should == true
|
|
213
226
|
end
|
|
214
227
|
|
|
215
228
|
it '#is_pubkey?' do
|
|
@@ -219,6 +232,8 @@ describe 'Bitcoin::Script' do
|
|
|
219
232
|
Script.new(SCRIPT[3]).is_pubkey?.should == false
|
|
220
233
|
Script.new(SCRIPT[4]).is_send_to_ip?.should == false
|
|
221
234
|
Script.new(SCRIPT[5]).is_pubkey?.should == false
|
|
235
|
+
Script.new(SCRIPT[6]).is_pubkey?.should == false
|
|
236
|
+
Script.from_string("0 OP_CHECKSIG").is_pubkey?.should == false # testnet aba0441c4c9933dcd7db789c39053739ec435ab742ed2c23c05f22f1488c0bfd
|
|
222
237
|
end
|
|
223
238
|
|
|
224
239
|
it "#is_hash160?" do
|
|
@@ -228,12 +243,14 @@ describe 'Bitcoin::Script' do
|
|
|
228
243
|
Script.from_string("OP_DUP OP_HASH160 0 OP_EQUALVERIFY OP_CHECKSIG")
|
|
229
244
|
.is_hash160?.should == false
|
|
230
245
|
Script.new(SCRIPT[5]).is_hash160?.should == false
|
|
246
|
+
Script.new(SCRIPT[6]).is_hash160?.should == false
|
|
231
247
|
end
|
|
232
248
|
|
|
233
249
|
it "#is_multisig?" do
|
|
234
250
|
Script.new(SCRIPT[3]).is_multisig?.should == true
|
|
235
251
|
Script.new(SCRIPT[4]).is_multisig?.should == true
|
|
236
252
|
Script.new(SCRIPT[0]).is_multisig?.should == false
|
|
253
|
+
Script.new(SCRIPT[6]).is_multisig?.should == false
|
|
237
254
|
Script.new("OP_DUP OP_DROP 2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG")
|
|
238
255
|
.is_multisig?.should == false
|
|
239
256
|
Script.new("OP_DROP OP_CHECKMULTISIG").is_multisig?.should == false
|
|
@@ -247,6 +264,20 @@ describe 'Bitcoin::Script' do
|
|
|
247
264
|
Script.new(SCRIPT[3]).is_p2sh?.should == false
|
|
248
265
|
Script.new(SCRIPT[4]).is_p2sh?.should == false
|
|
249
266
|
Script.new(SCRIPT[5]).is_p2sh?.should == true
|
|
267
|
+
Script.new(SCRIPT[6]).is_p2sh?.should == false
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it '#is_op_return?' do
|
|
271
|
+
Script.new(SCRIPT[0]).is_op_return?.should == false
|
|
272
|
+
Script.new(SCRIPT[1]).is_op_return?.should == false
|
|
273
|
+
Script.new(SCRIPT[2]).is_op_return?.should == false
|
|
274
|
+
Script.new(SCRIPT[3]).is_op_return?.should == false
|
|
275
|
+
Script.new(SCRIPT[4]).is_op_return?.should == false
|
|
276
|
+
Script.new(SCRIPT[5]).is_op_return?.should == false
|
|
277
|
+
Script.new(SCRIPT[6]).is_op_return?.should == true
|
|
278
|
+
Script.from_string("OP_RETURN dead beef").is_op_return?.should == false
|
|
279
|
+
Script.from_string("OP_RETURN deadbeef").is_op_return?.should == true
|
|
280
|
+
Script.from_string("OP_RETURN OP_CHECKSIG").is_op_return?.should == true
|
|
250
281
|
end
|
|
251
282
|
|
|
252
283
|
it "#type" do
|
|
@@ -256,6 +287,9 @@ describe 'Bitcoin::Script' do
|
|
|
256
287
|
Script.new(SCRIPT[3]).type.should == :multisig
|
|
257
288
|
Script.new(SCRIPT[4]).type.should == :multisig
|
|
258
289
|
Script.new(SCRIPT[5]).type.should == :p2sh
|
|
290
|
+
Script.new(SCRIPT[6]).type.should == :op_return
|
|
291
|
+
Script.from_string("OP_RETURN OP_CHECKSIG").type.should == :op_return
|
|
292
|
+
Script.from_string("OP_RETURN dead beef").type.should == :unknown
|
|
259
293
|
end
|
|
260
294
|
|
|
261
295
|
end
|
|
@@ -284,6 +318,13 @@ describe 'Bitcoin::Script' do
|
|
|
284
318
|
Script.from_string("2 #{PUBKEYS[0..2].join(' ')} 3 OP_CHECKMULTISIG").raw
|
|
285
319
|
Script.to_multisig_script(1, *PUBKEYS[0..1]).should ==
|
|
286
320
|
Script.from_string("1 #{PUBKEYS[0..1].join(' ')} 2 OP_CHECKMULTISIG").raw
|
|
321
|
+
|
|
322
|
+
m=n=16; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
|
|
323
|
+
.should == "16 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 16 OP_CHECKMULTISIG"
|
|
324
|
+
m=n=17; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
|
|
325
|
+
.should == "0:1:11 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 0:1:11 OP_CHECKMULTISIG"
|
|
326
|
+
m=n=20; Bitcoin::Script.new(Bitcoin::Script.to_multisig_script(m, *(["a"]*n))).to_string
|
|
327
|
+
.should == "0:1:14 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 0:1:14 OP_CHECKMULTISIG"
|
|
287
328
|
end
|
|
288
329
|
|
|
289
330
|
it "should generate p2sh script" do
|
|
@@ -293,6 +334,11 @@ describe 'Bitcoin::Script' do
|
|
|
293
334
|
Script.from_string("OP_HASH160 #{hash160} OP_EQUAL").raw
|
|
294
335
|
end
|
|
295
336
|
|
|
337
|
+
it "should generate op_return script" do
|
|
338
|
+
Script.to_op_return_script("deadbeef").should == SCRIPT[6]
|
|
339
|
+
Script.to_op_return_script.should == Script.from_string("OP_RETURN").raw
|
|
340
|
+
end
|
|
341
|
+
|
|
296
342
|
it "should determine type for address script" do
|
|
297
343
|
address = '16Tc7znw2mfpWcqS84vBFfJ7PyoeHaXSz9'
|
|
298
344
|
hash160 = Bitcoin.hash160_from_address address
|
|
@@ -335,6 +381,117 @@ describe 'Bitcoin::Script' do
|
|
|
335
381
|
end
|
|
336
382
|
end
|
|
337
383
|
|
|
384
|
+
|
|
385
|
+
describe "signatures_count" do
|
|
386
|
+
|
|
387
|
+
it "should be zero in data-only scripts" do
|
|
388
|
+
[false, true].each do |accurate|
|
|
389
|
+
Script.from_string("").sigops_count_accurate(accurate).should == 0
|
|
390
|
+
Script.from_string("DEADBEEF").sigops_count_accurate(accurate).should == 0
|
|
391
|
+
Script.from_string("DEAD BEEF").sigops_count_accurate(accurate).should == 0
|
|
392
|
+
Script.from_string("DE AD BE EF").sigops_count_accurate(accurate).should == 0
|
|
393
|
+
Script.from_string("OP_NOP").sigops_count_accurate(accurate).should == 0
|
|
394
|
+
Script.from_string("0").sigops_count_accurate(accurate).should == 0
|
|
395
|
+
Script.from_string("0 1").sigops_count_accurate(accurate).should == 0
|
|
396
|
+
Script.from_string("0 1 2 3").sigops_count_accurate(accurate).should == 0
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it "should count sigops" do
|
|
401
|
+
[false, true].each do |accurate|
|
|
402
|
+
Script.from_string("OP_CHECKSIG").sigops_count_accurate(accurate).should == 1
|
|
403
|
+
Script.from_string("OP_CHECKSIGVERIFY").sigops_count_accurate(accurate).should == 1
|
|
404
|
+
Script.from_string("OP_CHECKSIG OP_CHECKSIGVERIFY").sigops_count_accurate(accurate).should == 2
|
|
405
|
+
Script.from_string("OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG OP_CHECKSIG").sigops_count_accurate(accurate).should == 4
|
|
406
|
+
Script.from_string("1 OP_CHECKSIG 2 OP_CHECKSIG DEADBEEF OP_CHECKSIG 3 OP_CHECKSIG 4").sigops_count_accurate(accurate).should == 4
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it "should count multisig as 20 sigops in legact inaccurate mode" do
|
|
411
|
+
Script.from_string("OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
|
|
412
|
+
Script.from_string("OP_CHECKMULTISIGVERIFY").sigops_count_accurate(false).should == 20
|
|
413
|
+
Script.from_string("OP_CHECKMULTISIG OP_CHECKMULTISIGVERIFY").sigops_count_accurate(false).should == 40
|
|
414
|
+
Script.from_string("1 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
|
|
415
|
+
Script.from_string("5 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
|
|
416
|
+
Script.from_string("40 OP_CHECKMULTISIG").sigops_count_accurate(false).should == 20
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it "should count multisig accurately using number of pubkeys" do
|
|
420
|
+
Script.from_string("1 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 1
|
|
421
|
+
Script.from_string("1 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 1
|
|
422
|
+
Script.from_string("2 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 2
|
|
423
|
+
Script.from_string("2 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 2
|
|
424
|
+
Script.from_string("15 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 15
|
|
425
|
+
Script.from_string("15 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 15
|
|
426
|
+
Script.from_string("16 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 16
|
|
427
|
+
Script.from_string("16 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 16
|
|
428
|
+
Script.from_string("4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 11
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
it "should count multisig as 20 sigops in accurate mode when the pubkey count is missing" do
|
|
432
|
+
Script.from_string("OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
|
|
433
|
+
Script.from_string("OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
it "should count multisig as 20 sigops when pubkey count is not OP_{1,...,16}, but bignum as pushdata" do
|
|
437
|
+
Script.from_string("#{Script::OP_PUSHDATA1}:1:01 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
|
|
438
|
+
Script.from_string("#{Script::OP_PUSHDATA1}:1:02 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "should count multisig as 20 sigops in accurate mode when the pubkey count is out of bounds" do
|
|
442
|
+
Script.from_string("0 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
|
|
443
|
+
Script.from_string("0 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 20
|
|
444
|
+
Script.from_string("0 OP_CHECKMULTISIG 0 OP_CHECKMULTISIGVERIFY").sigops_count_accurate(true).should == 40
|
|
445
|
+
Script.from_string("DEADBEEF OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
|
|
446
|
+
Script.from_string("#{Script::OP_PUSHDATA1}:1:11 OP_CHECKMULTISIG").sigops_count_accurate(true).should == 20
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
it "should extract signature count from P2SH scriptSig" do
|
|
450
|
+
|
|
451
|
+
# Given a P2SH input script (the one with the signatures and a serialized script inside)
|
|
452
|
+
# This should count as 12 sigops (1 + 4 + 7)
|
|
453
|
+
script = Script.from_string("OP_CHECKSIG 4 OP_CHECKMULTISIG 7 OP_CHECKMULTISIGVERIFY")
|
|
454
|
+
|
|
455
|
+
# Serialize the script to be used as a plain pushdata (which will be decoded as a script).
|
|
456
|
+
serialized_script = Script.new("").append_pushdata(script.to_binary)
|
|
457
|
+
|
|
458
|
+
# If empty should return 0.
|
|
459
|
+
Script.from_string("").sigops_count_for_p2sh.should == 0
|
|
460
|
+
|
|
461
|
+
# If ends with OP_N
|
|
462
|
+
Script.from_string("0").sigops_count_for_p2sh.should == 0
|
|
463
|
+
Script.from_string("1").sigops_count_for_p2sh.should == 0
|
|
464
|
+
Script.from_string("5").sigops_count_for_p2sh.should == 0
|
|
465
|
+
Script.from_string("16").sigops_count_for_p2sh.should == 0
|
|
466
|
+
|
|
467
|
+
# If ends with opcode
|
|
468
|
+
Script.from_string("OP_NOP").sigops_count_for_p2sh.should == 0
|
|
469
|
+
Script.from_string("OP_HASH160").sigops_count_for_p2sh.should == 0
|
|
470
|
+
Script.from_string("OP_CHECKSIG").sigops_count_for_p2sh.should == 0
|
|
471
|
+
Script.from_string("DEADBEEF OP_NOP").sigops_count_for_p2sh.should == 0
|
|
472
|
+
Script.from_string("DEADBEEF OP_HASH160").sigops_count_for_p2sh.should == 0
|
|
473
|
+
Script.from_string("DEADBEEF OP_CHECKSIG").sigops_count_for_p2sh.should == 0
|
|
474
|
+
|
|
475
|
+
# If only has the script, should parse it well
|
|
476
|
+
serialized_script.sigops_count_for_p2sh.should == 12
|
|
477
|
+
|
|
478
|
+
# If ends with the script, should also parse well.
|
|
479
|
+
Script.new(Script.from_string("DEADBEEF CAFEBABE").to_binary + serialized_script.to_binary).sigops_count_for_p2sh.should == 12
|
|
480
|
+
Script.new(Script.from_string("DEADBEEF 1").to_binary + serialized_script.to_binary).sigops_count_for_p2sh.should == 12
|
|
481
|
+
|
|
482
|
+
# If has the script, but ends with non-script, should return 0
|
|
483
|
+
# DEADBEEF is a script with OP_CHECKSIGVERIFY in it, so we wrap it in a serialized script with plain pushdata to have 0 count.
|
|
484
|
+
Script.new(serialized_script.to_binary + Script.new("").append_pushdata(Script.from_string("DEADBEEF").to_binary).to_binary).sigops_count_for_p2sh.should == 0
|
|
485
|
+
Script.new(serialized_script.to_binary + Script.from_string("1").to_binary).sigops_count_for_p2sh.should == 0
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
it "should count sigops up until an invalid OP_PUSHDATA" do
|
|
489
|
+
script_binary = Bitcoin::Protocol.read_binary_file(fixtures_path("txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin"))
|
|
490
|
+
Script.new(script_binary).sigops_count_accurate(false).should == 39998
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
end
|
|
494
|
+
|
|
338
495
|
it '#run' do
|
|
339
496
|
script = SCRIPT[1] + SCRIPT[0]
|
|
340
497
|
Script.new(script).run.should == true
|
|
@@ -364,4 +521,118 @@ describe 'Bitcoin::Script' do
|
|
|
364
521
|
script.run.should == true
|
|
365
522
|
end
|
|
366
523
|
|
|
524
|
+
it "should run op_checkmultisig p2sh script with empty signature" do
|
|
525
|
+
# mainnet tx: b78706427923f73b334fd68040f35900503da33c671723c41ca845f6fba6c29c
|
|
526
|
+
tx1 = Bitcoin::P::Tx.new("01000000023904cd3644c6d440a6d752c95f07737c46f5e70fb6fbb28f00aa17e281868b7b010000006b483045022100ac455750dc430957942e9766f88aecfe6eb17d4244eb2cb50ca4a25336fd4dd702202640cc943f4fe8f2166b03005bed3bd024f4762767322b60bf471ecf8e3f3ede012102348d4cad0084f88c4c02bdc1bf90cc6c0893a0b97af76ef644daf72e6786b4afffffffffb84057ae61ad22ac17c02635ee1b37d170ef785847ec28efe848a5607331568e020000006b483045022100d7fee595d7a1f9969767098f8582e7a563f08437f461f0a25395f35c1833839302205f565ab12d343478471a78669c4c3476714032f7758a781d7deab19f160784e0012102ea69c47753d8e0228c0c426294a6b4dc926aebbeb8561248d40be37d257d94e0ffffffff01a08601000000000017a91438430c4d1c214bf11d2c0c3dea8e5e9a5d11aab08700000000".htb)
|
|
527
|
+
# mainnet tx: 136becd0892fa38c5aca8104db8b90b3a0e6b40912b7d1462aed583c067054cd
|
|
528
|
+
tx2 = Bitcoin::P::Tx.new("01000000019cc2a6fbf645a81cc42317673ca33d500059f34080d64f333bf72379420687b70000000008000051005102ae91ffffffff0150c300000000000002ae9100000000".htb)
|
|
529
|
+
tx2.verify_input_signature(0, tx1).should == true
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it "should debug script branches (OP_IF/NOTIF/ELSE/ENDIF) correctly" do
|
|
533
|
+
|
|
534
|
+
script = Bitcoin::Script.from_string("1 OP_NOTIF OP_RETURN OP_ENDIF")
|
|
535
|
+
script.run {}
|
|
536
|
+
script.debug.should == [
|
|
537
|
+
[], "OP_1",
|
|
538
|
+
[1], "OP_NOTIF",
|
|
539
|
+
[], "OP_ENDIF",
|
|
540
|
+
[], "RESULT"
|
|
541
|
+
]
|
|
542
|
+
|
|
543
|
+
script = Bitcoin::Script.from_string("1 OP_IF OP_RETURN OP_ENDIF")
|
|
544
|
+
script.run {}
|
|
545
|
+
script.debug.should == [
|
|
546
|
+
[], "OP_1",
|
|
547
|
+
[1], "OP_IF",
|
|
548
|
+
[], "OP_RETURN",
|
|
549
|
+
[], "INVALID TRANSACTION", "RESULT"
|
|
550
|
+
]
|
|
551
|
+
|
|
552
|
+
script = Bitcoin::Script.from_string("1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
|
|
553
|
+
script.run {}
|
|
554
|
+
script.debug.should == [
|
|
555
|
+
[], "OP_1",
|
|
556
|
+
[1], "OP_IF",
|
|
557
|
+
[], "OP_2",
|
|
558
|
+
[2], "OP_ELSE",
|
|
559
|
+
[2], "OP_ENDIF",
|
|
560
|
+
[2], "OP_2",
|
|
561
|
+
[2, 2], "OP_EQUAL",
|
|
562
|
+
[1], "RESULT"]
|
|
563
|
+
|
|
564
|
+
script = Bitcoin::Script.from_string("0 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
|
|
565
|
+
script.run {}
|
|
566
|
+
script.debug.should == [
|
|
567
|
+
[], "OP_0",
|
|
568
|
+
[[""]], "OP_IF",
|
|
569
|
+
[], "OP_ELSE",
|
|
570
|
+
[], "OP_3",
|
|
571
|
+
[3], "OP_ENDIF",
|
|
572
|
+
[3], "OP_2",
|
|
573
|
+
[3, 2], "OP_EQUAL",
|
|
574
|
+
[0], "RESULT"]
|
|
575
|
+
|
|
576
|
+
script = Bitcoin::Script.from_string("0 OP_IF deadbeef OP_ELSE OP_3 OP_ENDIF OP_2 OP_EQUAL")
|
|
577
|
+
script.run {}
|
|
578
|
+
script.debug.should == [
|
|
579
|
+
[], "OP_0",
|
|
580
|
+
[[""]], "OP_IF",
|
|
581
|
+
[], "OP_ELSE",
|
|
582
|
+
[], "OP_3",
|
|
583
|
+
[3], "OP_ENDIF",
|
|
584
|
+
[3], "OP_2",
|
|
585
|
+
[3, 2], "OP_EQUAL",
|
|
586
|
+
[0], "RESULT"]
|
|
587
|
+
|
|
588
|
+
script = Bitcoin::Script.from_string("1 OP_IF 2 OP_ELSE 3 OP_ENDIF 2 OP_EQUAL")
|
|
589
|
+
script.run {}
|
|
590
|
+
script.debug.should == [[], "OP_1", [1], "OP_IF", [], "OP_2", [2], "OP_ELSE", [2], "OP_ENDIF", [2], "OP_2", [2, 2], "OP_EQUAL", [1], "RESULT"]
|
|
591
|
+
|
|
592
|
+
script = Bitcoin::Script.from_string("
|
|
593
|
+
0
|
|
594
|
+
3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501
|
|
595
|
+
304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301
|
|
596
|
+
1
|
|
597
|
+
635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853
|
|
598
|
+
OP_IF
|
|
599
|
+
2
|
|
600
|
+
022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc
|
|
601
|
+
02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd
|
|
602
|
+
2
|
|
603
|
+
OP_CHECKMULTISIG
|
|
604
|
+
OP_ELSE
|
|
605
|
+
2
|
|
606
|
+
025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d57885348
|
|
607
|
+
02b18808b3e6857e396167890a52f898cbd5215354f027b89fed895058e49a158b
|
|
608
|
+
2
|
|
609
|
+
OP_CHECKMULTISIG
|
|
610
|
+
OP_ENDIF")
|
|
611
|
+
script.run {}
|
|
612
|
+
script.debug.should == [
|
|
613
|
+
[], "OP_0",
|
|
614
|
+
[[""]], "PUSH DATA 3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501",
|
|
615
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"]], "PUSH DATA 304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301",
|
|
616
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"]], "OP_1",
|
|
617
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1], "PUSH DATA 635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853",
|
|
618
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, ["635221022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc2102ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd52ae675221025182b1ca9a1ea9358f61cb363ac80c80b145204d9c4d875c35873d3d578853"]], "OP_IF",
|
|
619
|
+
|
|
620
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1], "OP_2",
|
|
621
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2], "PUSH DATA 022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc",
|
|
622
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"]], "PUSH DATA 02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd",
|
|
623
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"], ["02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd"]], "OP_2",
|
|
624
|
+
[[""], ["3045022041ccefcad804c28fcd843afeb10df3bd09d93e56542cda4ae9bcac18ed69f6c7022100f24d891b69695099a66b81a4ef382ff0ef388ad211505cd32e2ad3adebe5f74501"], ["304502201124a34c8bcc6a41c9bda088bc28e4274af02872866fa926205b0799e0f3b28a022100d0bbe8382a4e6ff46968bb8c2990bb63ef7f413f5b7c3912b4948b3eb0e72fc301"], 1, 2, ["022d73c0041da9794fcaa7286fcce35e126f84f8b53563be6abb3b213f964bfbfc"], ["02ab2445a289939e49e326dd29ca068cb38d1c9ef7618b7272d14c79c1abdea5cd"], 2], "OP_CHECKMULTISIG",
|
|
625
|
+
[[""], 0], "OP_ELSE",
|
|
626
|
+
[[""], 0], "OP_ENDIF",
|
|
627
|
+
[[""], 0], "RESULT"]
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
it "should not execute p2sh recursively" do
|
|
631
|
+
# this script_sig includes a pattern that matches the p2sh template
|
|
632
|
+
script_sig = "0 a914b472a266d0bd89c13706a4132ccfb16f7c3b9fcb87"
|
|
633
|
+
pk_script = "OP_HASH160 92a04bc86e23f169691bd6926d11853cc61e1852 OP_EQUAL"
|
|
634
|
+
script = Bitcoin::Script.from_string(script_sig + " " + pk_script)
|
|
635
|
+
script.run.should == true
|
|
636
|
+
end
|
|
637
|
+
|
|
367
638
|
end
|
data/spec/bitcoin/spec_helper.rb
CHANGED
|
@@ -20,17 +20,21 @@ end
|
|
|
20
20
|
|
|
21
21
|
require 'bitcoin'
|
|
22
22
|
|
|
23
|
+
def fixtures_path(relative_path)
|
|
24
|
+
File.join(File.dirname(__FILE__), 'fixtures', relative_path)
|
|
25
|
+
end
|
|
26
|
+
|
|
23
27
|
def fixtures_file(relative_path)
|
|
24
|
-
|
|
25
|
-
Bitcoin::Protocol.read_binary_file( File.join(basedir, relative_path) )
|
|
28
|
+
Bitcoin::Protocol.read_binary_file( fixtures_path(relative_path) )
|
|
26
29
|
end
|
|
27
30
|
|
|
31
|
+
|
|
28
32
|
include Bitcoin::Builder
|
|
29
33
|
|
|
30
34
|
# create block for given +prev+ block
|
|
31
35
|
# if +store+ is true, save it to @store
|
|
32
36
|
# accepts an array of +tx+ callbacks
|
|
33
|
-
def create_block prev, store = true, tx = [], key = Bitcoin::Key.
|
|
37
|
+
def create_block prev, store = true, tx = [], key = Bitcoin::Key.generate, coinbase_value = 50e8, opts = {}
|
|
34
38
|
opts[:bits] ||= Bitcoin.network[:proof_of_work_limit]
|
|
35
39
|
block = build_block(Bitcoin.decode_compact_bits(opts[:bits])) do |b|
|
|
36
40
|
b.time opts[:time] if opts[:time]
|
|
@@ -47,8 +51,8 @@ end
|
|
|
47
51
|
|
|
48
52
|
# create transaction given builder +tx+
|
|
49
53
|
# +outputs+ is an array of [value, key] pairs
|
|
50
|
-
def create_tx(tx, prev_tx, prev_out_index, outputs)
|
|
51
|
-
tx.input {|i| i.prev_out prev_tx; i.prev_out_index prev_out_index; i.signature_key
|
|
54
|
+
def create_tx(tx, prev_tx, prev_out_index, outputs, key = @key)
|
|
55
|
+
tx.input {|i| i.prev_out prev_tx; i.prev_out_index prev_out_index; i.signature_key key }
|
|
52
56
|
outputs.each do |value, key|
|
|
53
57
|
tx.output {|o| o.value value; o.script {|s| s.recipient key.addr } }
|
|
54
58
|
end
|
|
@@ -90,7 +94,12 @@ Bitcoin::NETWORKS[:spec] = {
|
|
|
90
94
|
:proof_of_work_limit => 553713663,
|
|
91
95
|
:alert_pubkeys => [],
|
|
92
96
|
:known_nodes => [],
|
|
93
|
-
:checkpoints => {}
|
|
97
|
+
:checkpoints => {},
|
|
98
|
+
:min_tx_fee => 10_000,
|
|
99
|
+
:min_relay_tx_fee => 10_000,
|
|
100
|
+
:free_tx_bytes => 1_000,
|
|
101
|
+
:dust => 1_000_000,
|
|
102
|
+
:per_dust_fee => false,
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
begin
|
|
@@ -123,3 +132,22 @@ def setup_db backend, db = nil, conf = {}
|
|
|
123
132
|
end
|
|
124
133
|
Bitcoin::Storage.send(backend, conf.merge(db: uri, log_level: :warn))
|
|
125
134
|
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class Time
|
|
138
|
+
class << self
|
|
139
|
+
alias_method :real_new, :new
|
|
140
|
+
alias_method :new, :now
|
|
141
|
+
def now; @time || real_new; end
|
|
142
|
+
def freeze(time = nil)
|
|
143
|
+
begin
|
|
144
|
+
prev = @time
|
|
145
|
+
@time = time || now
|
|
146
|
+
yield
|
|
147
|
+
ensure
|
|
148
|
+
@time = prev
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
def frozen?; !@time.nil?; end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
2
|
+
|
|
3
|
+
require_relative '../spec_helper'
|
|
4
|
+
|
|
5
|
+
include Bitcoin
|
|
6
|
+
include Bitcoin::Storage
|
|
7
|
+
include Bitcoin::Storage::Backends
|
|
8
|
+
include Bitcoin::Builder
|
|
9
|
+
|
|
10
|
+
Bitcoin::network = :testnet
|
|
11
|
+
[
|
|
12
|
+
# [:dummy],
|
|
13
|
+
[:sequel, :sqlite],
|
|
14
|
+
# [:utxo, :sqlite, index_all_addrs: true],
|
|
15
|
+
[:sequel, :postgres],
|
|
16
|
+
[:utxo, :postgres, index_all_addrs: true],
|
|
17
|
+
[:sequel, :mysql],
|
|
18
|
+
[:utxo, :mysql, index_all_addrs: true],
|
|
19
|
+
].compact.each do |options|
|
|
20
|
+
next unless storage = setup_db(*options)
|
|
21
|
+
|
|
22
|
+
describe "Storage::Models (#{options[0].to_s.capitalize}Store, #{options[1]})" do
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
Bitcoin.network[:no_difficulty] = true
|
|
26
|
+
Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
|
|
27
|
+
|
|
28
|
+
@store = storage
|
|
29
|
+
def @store.in_sync?; true; end
|
|
30
|
+
@store.reset
|
|
31
|
+
|
|
32
|
+
@store.store_block(P::Block.new(fixtures_file('testnet/block_0.bin')))
|
|
33
|
+
@store.store_block(P::Block.new(fixtures_file('testnet/block_1.bin')))
|
|
34
|
+
@store.store_block(P::Block.new(fixtures_file('testnet/block_2.bin')))
|
|
35
|
+
@store.store_block(P::Block.new(fixtures_file('testnet/block_3.bin')))
|
|
36
|
+
|
|
37
|
+
unless @store.class.name =~ /UtxoStore/
|
|
38
|
+
@store.store_tx(P::Tx.new(fixtures_file('rawtx-01.bin')), false)
|
|
39
|
+
@store.store_tx(P::Tx.new(fixtures_file('rawtx-02.bin')), false)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@blk = P::Block.new(fixtures_file('testnet/block_4.bin'))
|
|
43
|
+
@tx = P::Tx.new(fixtures_file('rawtx-03.bin'))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
after do
|
|
47
|
+
Bitcoin.network.delete :no_difficulty
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "Block" do
|
|
51
|
+
|
|
52
|
+
before { @block = @store.get_block_by_depth(1) }
|
|
53
|
+
|
|
54
|
+
it "should get prev block" do
|
|
55
|
+
@block.get_prev_block.should == @store.get_block_by_depth(0)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should get next block" do
|
|
59
|
+
@block.get_next_block.should == @store.get_block_by_depth(2)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should get total out" do
|
|
63
|
+
@block.total_out.should == 5000000000
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should get total in" do
|
|
67
|
+
@block.total_in.should == 5000000000
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should get total fee" do
|
|
71
|
+
@block.total_fee.should == 0
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "Tx" do
|
|
77
|
+
|
|
78
|
+
before { @tx = @store.get_block_by_depth(1).tx[0] }
|
|
79
|
+
|
|
80
|
+
it "should get block" do
|
|
81
|
+
@tx.get_block.should == @store.get_block_by_depth(1)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should get confirmations" do
|
|
85
|
+
@tx.confirmations.should == 3
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should get total out" do
|
|
89
|
+
@tx.total_out.should == 5000000000
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should get total in" do
|
|
93
|
+
@tx.total_in.should == 5000000000
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "should get fee" do
|
|
97
|
+
@tx.fee.should == 0
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|