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.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +2 -2
  4. data/COPYING +1 -1
  5. data/Gemfile +5 -11
  6. data/README.rdoc +11 -5
  7. data/Rakefile +5 -0
  8. data/bin/bitcoin_node +11 -29
  9. data/bin/bitcoin_node_cli +81 -0
  10. data/bin/bitcoin_wallet +9 -6
  11. data/doc/NODE.rdoc +79 -26
  12. data/examples/bbe_verify_tx.rb +1 -1
  13. data/examples/index_nhash.rb +24 -0
  14. data/examples/reindex_p2sh_addrs.rb +44 -0
  15. data/lib/bitcoin.rb +135 -20
  16. data/lib/bitcoin/builder.rb +233 -63
  17. data/lib/bitcoin/key.rb +89 -16
  18. data/lib/bitcoin/litecoin.rb +13 -11
  19. data/lib/bitcoin/namecoin.rb +5 -4
  20. data/lib/bitcoin/network/command_client.rb +23 -13
  21. data/lib/bitcoin/network/command_handler.rb +336 -131
  22. data/lib/bitcoin/network/connection_handler.rb +14 -13
  23. data/lib/bitcoin/network/node.rb +61 -20
  24. data/lib/bitcoin/protocol.rb +5 -1
  25. data/lib/bitcoin/protocol/block.rb +15 -3
  26. data/lib/bitcoin/protocol/parser.rb +3 -3
  27. data/lib/bitcoin/protocol/tx.rb +82 -20
  28. data/lib/bitcoin/protocol/txin.rb +7 -0
  29. data/lib/bitcoin/protocol/txout.rb +12 -9
  30. data/lib/bitcoin/script.rb +329 -75
  31. data/lib/bitcoin/storage/dummy/dummy_store.rb +23 -4
  32. data/lib/bitcoin/storage/models.rb +6 -11
  33. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +14 -0
  34. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +31 -0
  35. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +16 -0
  36. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +31 -0
  37. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +56 -0
  38. data/lib/bitcoin/storage/sequel/sequel_store.rb +168 -70
  39. data/lib/bitcoin/storage/storage.rb +161 -97
  40. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +1 -1
  41. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +14 -0
  42. data/lib/bitcoin/storage/utxo/utxo_store.rb +25 -12
  43. data/lib/bitcoin/validation.rb +87 -56
  44. data/lib/bitcoin/version.rb +1 -1
  45. data/spec/bitcoin/bitcoin_spec.rb +38 -0
  46. data/spec/bitcoin/builder_spec.rb +177 -0
  47. data/spec/bitcoin/fixtures/litecoin-tx-f5aa30f574e3b6f1a3d99c07a6356ba812aabb9661e1d5f71edff828cbd5c996.json +259 -0
  48. data/spec/bitcoin/fixtures/rawblock-testnet-265322.bin +0 -0
  49. data/spec/bitcoin/fixtures/tx-0295028ef826b2a188409cb905b631faebb9bb3cdf14510571c5f4bd8591338f.json +64 -0
  50. data/spec/bitcoin/fixtures/tx-03339a725007a279484fb6f5361f522dd1cf4d0923d30e6b973290dba4275f92.json +64 -0
  51. data/spec/bitcoin/fixtures/tx-0ce7e5238fbdb6c086cf1b384b21b827e91cc23f360417265874a5a0d86ce367.json +64 -0
  52. data/spec/bitcoin/fixtures/tx-0ef34c49f630aea17df0080728b0fc67bf5f87fbda936934a4b11b4a69d7821e.json +64 -0
  53. data/spec/bitcoin/fixtures/tx-1129d2a8bd5bb3a81e54dc96a90f1f6b2544575748caa17243470935c5dd91b7.json +28 -0
  54. data/spec/bitcoin/fixtures/tx-19aa42fee0fa57c45d3b16488198b27caaacc4ff5794510d0c17f173f05587ff.json +23 -0
  55. data/spec/bitcoin/fixtures/tx-1a4f3b9dc4494aeedeb39f30dd37e60541b2abe3ed4977992017cc0ad4f44956.json +64 -0
  56. data/spec/bitcoin/fixtures/tx-1f9191dcf2b1844ca28c6ef4b969e1d5fab70a5e3c56b7007949e55851cb0c4f.json +64 -0
  57. data/spec/bitcoin/fixtures/tx-22cd5fef23684d7b304e119bedffde6f54538d3d54a5bfa237e20dc2d9b4b5ad.json +64 -0
  58. data/spec/bitcoin/fixtures/tx-2958fb00b4fd6fe0353503b886eb9a193d502f4fd5fc042d5e03216ba918bbd6.json +64 -0
  59. data/spec/bitcoin/fixtures/tx-29f277145749ad6efbed3ae6ce301f8d33c585ec26b7c044ad93c2f866e9e942.json +64 -0
  60. data/spec/bitcoin/fixtures/tx-2c5e5376c20e9cc78d0fb771730e5d840cc2096eff0ef045b599fe92475ace1c.json +28 -0
  61. data/spec/bitcoin/fixtures/tx-2c63aa814701cef5dbd4bbaddab3fea9117028f2434dddcdab8339141e9b14d1.json +30 -0
  62. data/spec/bitcoin/fixtures/tx-326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e.json +23 -0
  63. data/spec/bitcoin/fixtures/tx-345bed8785c3282a264ffb0dbee61cde54854f10e16f1b3e75b7f2d9f62946f2.json +64 -0
  64. data/spec/bitcoin/fixtures/tx-39ba7440b7103557560cc8ce258009936796485aaf8b478e66ab4cb97c66e31b.json +32 -0
  65. data/spec/bitcoin/fixtures/tx-3a04d57a833367f1655cc5ec3beb587888ef4977a86caa8c8ad4ba7cc717eae7.json +64 -0
  66. data/spec/bitcoin/fixtures/tx-4142ee4877eb116abf955a7ec6ef2dc38133b793df762b76d75e3d7d4d8badc9.json +38 -0
  67. data/spec/bitcoin/fixtures/tx-46224764c7870f95b58f155bce1e38d4da8e99d42dbb632d0dd7c07e092ee5aa.json +23 -0
  68. data/spec/bitcoin/fixtures/tx-5df1375ffe61ac35ca178ebb0cab9ea26dedbd0e96005dfcee7e379fa513232f.json +30 -0
  69. data/spec/bitcoin/fixtures/tx-62d9a565bd7b5344c5352e3e9e5f40fa4bbd467fa19c87357216ec8777ba1cce.json +64 -0
  70. data/spec/bitcoin/fixtures/tx-6327783a064d4e350c454ad5cd90201aedf65b1fc524e73709c52f0163739190.json +23 -0
  71. data/spec/bitcoin/fixtures/tx-6606c366a487bff9e412d0b6c09c14916319932db5954bf5d8719f43f828a3ba.json +27 -0
  72. data/spec/bitcoin/fixtures/tx-6aaf18b9f1283b939d8e5d40ff5f8a435229f4178372659cc3a0bce4e262bf78.json +28 -0
  73. data/spec/bitcoin/fixtures/tx-6b48bba6f6d2286d7ec0883c0fc3085955090813a4c94980466611c798b868cc.json +64 -0
  74. data/spec/bitcoin/fixtures/tx-70cfbc6690f9ab46712db44e3079ac227962b2771a9341d4233d898b521619ef.json +40 -0
  75. data/spec/bitcoin/fixtures/tx-7a1a9db42f065f75110fcdb1bc415549c8ef7670417ba1d35a67f1b8adc562c1.json +64 -0
  76. data/spec/bitcoin/fixtures/tx-9a768fc7d0c4bdc86e25154357ef7c0063ca21310e5740a2f12f90b7455184a7.json +64 -0
  77. data/spec/bitcoin/fixtures/tx-9cad8d523a0694f2509d092c39cebc8046adae62b4e4297102d568191d9478d8.json +64 -0
  78. data/spec/bitcoin/fixtures/tx-9e052eb694bd7e15906433f064dff0161a12fd325c1124537766377004023c6f.json +64 -0
  79. data/spec/bitcoin/fixtures/tx-a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944.json +23 -0
  80. data/spec/bitcoin/fixtures/tx-aab7ef280abbb9cc6fbaf524d2645c3daf4fcca2b3f53370e618d9cedf65f1f8.json +23 -0
  81. data/spec/bitcoin/fixtures/tx-ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742.json +27 -0
  82. data/spec/bitcoin/fixtures/tx-ad4bcf3241e5d2ad140564e20db3567d41594cf4c2012433fe46a2b70e0d87b8.json +64 -0
  83. data/spec/bitcoin/fixtures/tx-b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9.json +27 -0
  84. data/spec/bitcoin/fixtures/tx-b8fd633e7713a43d5ac87266adc78444669b987a56b3a65fb92d58c2c4b0e84d.json +28 -0
  85. data/spec/bitcoin/fixtures/tx-bbca0628c42cb8bf7c3f4b2ad688fa56da5308dd2a10255da89fb1f46e6e413d.json +36 -0
  86. data/spec/bitcoin/fixtures/tx-bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224.json +23 -0
  87. data/spec/bitcoin/fixtures/tx-c192b74844e4837a34c4a5a97b438f1c111405b01b99e2d12b7c96d07fc74c04.json +28 -0
  88. data/spec/bitcoin/fixtures/tx-e335562f7e297aadeed88e5954bc4eeb8dc00b31d829eedb232e39d672b0c009.json +406 -0
  89. data/spec/bitcoin/fixtures/tx-eb3b82c0884e3efa6d8b0be55b4915eb20be124c9766245bcc7f34fdac32bccb.json +35 -0
  90. data/spec/bitcoin/fixtures/tx-fee1b9b85531c8fb6cd7831f83490c7f2aa768b6eefe29854ef5e89ce7b9ecb1.json +64 -0
  91. data/spec/bitcoin/fixtures/txscript-invalid-too-many-sigops-followed-by-invalid-pushdata.bin +1 -0
  92. data/spec/bitcoin/helpers/fake_blockchain.rb +183 -0
  93. data/spec/bitcoin/key_spec.rb +79 -8
  94. data/spec/bitcoin/namecoin_spec.rb +1 -1
  95. data/spec/bitcoin/node/command_api_spec.rb +373 -86
  96. data/spec/bitcoin/performance/storage_spec.rb +41 -0
  97. data/spec/bitcoin/protocol/addr_spec.rb +7 -5
  98. data/spec/bitcoin/protocol/aux_pow_spec.rb +1 -0
  99. data/spec/bitcoin/protocol/block_spec.rb +6 -0
  100. data/spec/bitcoin/protocol/tx_spec.rb +184 -1
  101. data/spec/bitcoin/protocol/txin_spec.rb +27 -0
  102. data/spec/bitcoin/protocol/txout_spec.rb +27 -0
  103. data/spec/bitcoin/script/opcodes_spec.rb +74 -3
  104. data/spec/bitcoin/script/script_spec.rb +271 -0
  105. data/spec/bitcoin/spec_helper.rb +34 -6
  106. data/spec/bitcoin/storage/models_spec.rb +104 -0
  107. data/spec/bitcoin/storage/reorg_spec.rb +42 -11
  108. data/spec/bitcoin/storage/storage_spec.rb +58 -15
  109. data/spec/bitcoin/storage/validation_spec.rb +44 -14
  110. data/spec/bitcoin/wallet/keygenerator_spec.rb +6 -3
  111. data/spec/bitcoin/wallet/keystore_spec.rb +3 -3
  112. data/spec/bitcoin/wallet/wallet_spec.rb +87 -89
  113. 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
@@ -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
- basedir = File.join(File.dirname(__FILE__), 'fixtures')
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.new, coinbase_value = 50e8, opts = {}
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 @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