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.
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