bitcoin-ruby 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|