bitcoin-ruby 0.0.6 → 0.0.7

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -7
  4. data/COPYING +1 -1
  5. data/Gemfile +2 -6
  6. data/Gemfile.lock +34 -0
  7. data/README.rdoc +16 -68
  8. data/Rakefile +3 -6
  9. data/bin/bitcoin_shell +0 -1
  10. data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
  11. data/lib/bitcoin.rb +350 -296
  12. data/lib/bitcoin/builder.rb +3 -1
  13. data/lib/bitcoin/connection.rb +2 -1
  14. data/lib/bitcoin/contracthash.rb +76 -0
  15. data/lib/bitcoin/dogecoin.rb +97 -0
  16. data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
  17. data/lib/bitcoin/ffi/openssl.rb +98 -2
  18. data/lib/bitcoin/ffi/secp256k1.rb +144 -0
  19. data/lib/bitcoin/key.rb +12 -2
  20. data/lib/bitcoin/logger.rb +3 -12
  21. data/lib/bitcoin/protocol/block.rb +3 -9
  22. data/lib/bitcoin/protocol/parser.rb +6 -2
  23. data/lib/bitcoin/protocol/tx.rb +44 -13
  24. data/lib/bitcoin/protocol/txin.rb +4 -2
  25. data/lib/bitcoin/protocol/txout.rb +2 -2
  26. data/lib/bitcoin/script.rb +212 -37
  27. data/lib/bitcoin/trezor/mnemonic.rb +130 -0
  28. data/lib/bitcoin/version.rb +1 -1
  29. data/spec/bitcoin/bitcoin_spec.rb +32 -3
  30. data/spec/bitcoin/builder_spec.rb +18 -0
  31. data/spec/bitcoin/contracthash_spec.rb +45 -0
  32. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  33. data/spec/bitcoin/ffi_openssl.rb +45 -0
  34. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  35. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  36. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  37. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  38. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  39. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  40. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  41. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  42. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  43. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  44. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  45. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  46. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  47. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  48. data/spec/bitcoin/protocol/block_spec.rb +0 -22
  49. data/spec/bitcoin/protocol/tx_spec.rb +145 -2
  50. data/spec/bitcoin/script/script_spec.rb +282 -0
  51. data/spec/bitcoin/secp256k1_spec.rb +48 -0
  52. data/spec/bitcoin/spec_helper.rb +0 -51
  53. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  54. metadata +48 -98
  55. data/bin/bitcoin_dns_seed +0 -130
  56. data/bin/bitcoin_gui +0 -80
  57. data/bin/bitcoin_node +0 -153
  58. data/bin/bitcoin_node_cli +0 -81
  59. data/bin/bitcoin_wallet +0 -402
  60. data/doc/CONFIG.rdoc +0 -66
  61. data/doc/EXAMPLES.rdoc +0 -13
  62. data/doc/NAMECOIN.rdoc +0 -34
  63. data/doc/NODE.rdoc +0 -225
  64. data/doc/STORAGE.rdoc +0 -33
  65. data/doc/WALLET.rdoc +0 -102
  66. data/examples/balance.rb +0 -66
  67. data/examples/forwarder.rb +0 -73
  68. data/examples/index_nhash.rb +0 -24
  69. data/examples/reindex_p2sh_addrs.rb +0 -44
  70. data/examples/relay_tx.rb +0 -22
  71. data/examples/verify_tx.rb +0 -57
  72. data/lib/bitcoin/config.rb +0 -58
  73. data/lib/bitcoin/gui/addr_view.rb +0 -44
  74. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  75. data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
  76. data/lib/bitcoin/gui/conn_view.rb +0 -38
  77. data/lib/bitcoin/gui/connection.rb +0 -70
  78. data/lib/bitcoin/gui/em_gtk.rb +0 -30
  79. data/lib/bitcoin/gui/gui.builder +0 -1643
  80. data/lib/bitcoin/gui/gui.rb +0 -292
  81. data/lib/bitcoin/gui/helpers.rb +0 -115
  82. data/lib/bitcoin/gui/tree_view.rb +0 -84
  83. data/lib/bitcoin/gui/tx_view.rb +0 -69
  84. data/lib/bitcoin/namecoin.rb +0 -280
  85. data/lib/bitcoin/network/command_client.rb +0 -104
  86. data/lib/bitcoin/network/command_handler.rb +0 -570
  87. data/lib/bitcoin/network/connection_handler.rb +0 -387
  88. data/lib/bitcoin/network/node.rb +0 -565
  89. data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
  90. data/lib/bitcoin/storage/models.rb +0 -171
  91. data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
  92. data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
  93. data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
  94. data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
  95. data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
  96. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
  97. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
  98. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
  99. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
  100. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
  101. data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
  102. data/lib/bitcoin/storage/storage.rb +0 -517
  103. data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
  104. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
  105. data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
  106. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
  107. data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
  108. data/lib/bitcoin/validation.rb +0 -400
  109. data/lib/bitcoin/wallet/coinselector.rb +0 -33
  110. data/lib/bitcoin/wallet/keygenerator.rb +0 -77
  111. data/lib/bitcoin/wallet/keystore.rb +0 -207
  112. data/lib/bitcoin/wallet/txdp.rb +0 -118
  113. data/lib/bitcoin/wallet/wallet.rb +0 -281
  114. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
  115. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
  116. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
  117. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
  118. data/spec/bitcoin/namecoin_spec.rb +0 -182
  119. data/spec/bitcoin/node/command_api_spec.rb +0 -663
  120. data/spec/bitcoin/storage/models_spec.rb +0 -104
  121. data/spec/bitcoin/storage/reorg_spec.rb +0 -236
  122. data/spec/bitcoin/storage/storage_spec.rb +0 -387
  123. data/spec/bitcoin/storage/validation_spec.rb +0 -300
  124. data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
  125. data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
  126. data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
  127. data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
  128. data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
@@ -1,300 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require_relative '../spec_helper'
4
-
5
- include Bitcoin::Builder
6
- include Bitcoin::Storage
7
- include Bitcoin::Validation
8
-
9
- Bitcoin.network = :spec
10
-
11
- [
12
- [:sequel, :sqlite],
13
- [:utxo, :sqlite, index_all_addrs: true],
14
- [:sequel, :postgres],
15
- [:utxo, :postgres, index_all_addrs: true],
16
- [:sequel, :mysql],
17
- [:utxo, :mysql, index_all_addrs: true],
18
- ].compact.each do |options|
19
-
20
- next unless storage = setup_db(*options)
21
-
22
- describe "block rules (#{options[0]} - #{options[1]})" do
23
-
24
- def balance addr
25
- @store.get_balance(Bitcoin.hash160_from_address(addr))
26
- end
27
-
28
- before do
29
- @store = storage
30
- @store.reset
31
- @store.log.level = :warn
32
- Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("f"*64)
33
- @key = Bitcoin::Key.generate
34
- @block0 = create_block "00"*32, false, [], @key
35
- Bitcoin.network[:genesis_hash] = @block0.hash
36
- @store.store_block(@block0)
37
- @store.get_head.should == @block0
38
- @block1 = create_block @block0.hash, true, [], @key
39
- @store.get_head.should == @block1
40
- @block = create_block @block1.hash, false
41
- end
42
-
43
- def check_block blk, error
44
- b = blk.dup
45
- if block_given?
46
- yield(b); b.bits = Bitcoin.network[:proof_of_work_limit]; b.recalc_block_hash
47
- end
48
-
49
- validator = b.validator(@store)
50
- validator.validate.should == false
51
- validator.error.should == error
52
- end
53
-
54
- it "1. Check syntactic correctness" do
55
- block = create_block @block1.hash, false
56
- block.hash = "00" * 32
57
- block.bits = Bitcoin.network[:proof_of_work_limit]
58
- validator = block.validator(@store)
59
- validator.validate.should == false
60
- validator.error.should == [:hash, ["00"*32, block.hash]]
61
- end
62
-
63
- it "3. Transaction list must be non-empty" do
64
- check_block(@block, [:tx_list, 0]) {|b| b.tx = [] }
65
- end
66
-
67
- it "4. Block hash must satisfy claimed nBits proof of work" do
68
- @block.bits = Bitcoin.encode_compact_bits("0000#{"ff" * 30}")
69
- @block.recalc_block_hash
70
- target = Bitcoin.decode_compact_bits(@block.bits).to_i(16)
71
- check_block(@block, [:bits, [@block.hash.to_i(16), target]])
72
- end
73
-
74
- it "5. Block timestamp must not be more than two hours in the future" do
75
- Time.freeze do
76
- fake_time = (Time.now + 3 * 60 * 60).to_i
77
- check_block(@block, [:max_timestamp, [fake_time, Time.now.to_i + 7200]]) {|b|
78
- b.time = fake_time }
79
- end
80
- end
81
-
82
- it "6. First transaction must be coinbase (i.e. only 1 input, with hash=0, n=-1), the rest must not be" do
83
- block = create_block @block1.hash, false, [
84
- ->(tx) { create_tx(tx, @block1.tx.first, 0, [[50, @key]]) } ], @key
85
- check_block(block, [:coinbase, [0, 1]]) {|b| b.tx = b.tx.reverse }
86
- check_block(block, [:coinbase, [1, 1]]) {|b| b.tx << b.tx[0] }
87
- end
88
-
89
- it "8. For the coinbase (first) transaction, scriptSig length must be 2-100" do
90
- check_block(@block, [:coinbase_scriptsig, [1, 2, 100]]) {|b|
91
- b.tx[0].in[0].script_sig = "\x01" }
92
- check_block(@block, [:coinbase_scriptsig, [101, 2, 100]]) {|b|
93
- b.tx[0].in[0].script_sig = "\x01" * 101 }
94
- end
95
-
96
- it "10. Verify Merkle hash" do
97
- check_block(@block, [:mrkl_root, ["00"*32, @block.mrkl_root.reverse_hth]]) {|b|
98
- b.mrkl_root = "\x00" * 32 }
99
- end
100
-
101
- it "12. Check that nBits value matches the difficulty rules" do
102
- block = create_block @block1.hash, false, [], @key
103
- Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("0000#{"ff"*30}")
104
- validator = block.validator(@store)
105
- validator.validate.should == false
106
- validator.error.should == [:difficulty, [553713663, 520159231]]
107
- end
108
-
109
- it "13. Reject if timestamp is the median time of the last 11 blocks or before" do
110
- prev_block = @block1
111
- 12.times do |i|
112
- prev_block = create_block(prev_block.hash, false, [])
113
- prev_block.time = i
114
- prev_block.recalc_block_hash
115
- @store.store_block(prev_block).should == [i+2, 0]
116
- end
117
-
118
- block = create_block(prev_block.hash, false, [], @key)
119
-
120
- fake_time = @store.get_block_by_depth(8).time - 1
121
- times = @store.db[:blk].where("depth > 2").map{|b|b[:time]}.sort
122
- m, r = times.size.divmod(2)
123
- min_time = (r == 0 ? times[m-1, 2].inject(:+) / 2.0 : times[m])
124
-
125
- # reject before median time
126
- check_block(block, [:min_timestamp, [fake_time, min_time]]) {|b| b.time = fake_time }
127
-
128
- # reject at exactly median time
129
- fake_time = @store.get_block_by_depth(8).time
130
- check_block(block, [:min_timestamp, [fake_time, fake_time]]) {|b| b.time = fake_time }
131
-
132
- # accept after median time
133
- block.time = @store.get_block_by_depth(8).time + 1; block.recalc_block_hash
134
- @store.store_block(block).should == [14, 0]
135
- end
136
-
137
- it "should allow chains of unconfirmed transactions" do
138
- tx1 = build_tx {|t| create_tx(t, @block1.tx.first, 0, [[50, @key]]) }
139
- tx2 = build_tx {|t| create_tx(t, tx1, 0, [[50, @key]]) }
140
- block = create_block(@block1.hash, false, [], @key)
141
- block.tx << tx1; block.tx << tx2
142
- block.bits = Bitcoin.encode_compact_bits("f"*64)
143
- block.mrkl_root = [Bitcoin.hash_mrkl_tree(block.tx.map(&:hash)).last].pack("H*").reverse
144
- block.recalc_block_hash
145
- @store.store_block(block).should == [2, 0]
146
- end
147
-
148
- it "should check coinbase output value" do
149
- block2 = create_block(@block1.hash, false, [
150
- ->(tx) { create_tx(tx, @block1.tx.first, 0, [[40e8, @key]])}
151
- ], @key, 60e8)
152
- @store.store_block(block2).should == [2, 0]
153
-
154
- block3 = create_block(block2.hash, false, [], @key, 60e8)
155
- -> { @store.store_block(block3) }.should.raise(ValidationError)
156
-
157
- Bitcoin::REWARD_DROP = 2
158
- block4 = create_block(block2.hash, false, [], @key, 50e8)
159
- -> { @store.store_block(block4) }.should.raise(ValidationError)
160
-
161
- block5 = create_block(block2.hash, false, [], @key, 25e8)
162
- @store.store_block(block5).should == [3, 0]
163
- Bitcoin::REWARD_DROP = 210_000
164
- end
165
-
166
- end
167
-
168
- describe "transaction rules (#{options[0]} - #{options[1]})" do
169
-
170
- before do
171
- Bitcoin.network = :spec
172
- @store = storage
173
- @store.reset
174
- @store.log.level = :warn
175
-
176
- Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("f"*64)
177
- @key = Bitcoin::Key.generate
178
- @block0 = create_block "00"*32, false, [], @key
179
- Bitcoin.network[:genesis_hash] = @block0.hash
180
- @store.store_block(@block0)
181
- @store.get_head.should == @block0
182
- @block1 = create_block @block0.hash, true, [], @key
183
- @store.get_head.should == @block1
184
- @tx = build_tx {|t| create_tx(t, @block1.tx.first, 0, [[50, @key]]) }
185
- end
186
-
187
- def check_tx tx, error
188
- t = tx.dup
189
- yield(t) && t.instance_eval { @hash = generate_hash(to_payload) } if block_given?
190
- validator = t.validator(@store)
191
- validator.validate.should == false
192
- validator.error.should == error
193
- end
194
-
195
- it "should validate" do
196
- validator = @tx.validator(@store)
197
- validator.validate.should == true
198
- validator.validate(raise_errors: true).should == true
199
- hash = @tx.hash; @tx.instance_eval { @hash = "f"*64 }
200
- validator = @tx.validator(@store)
201
- validator.validate.should == false
202
- validator.error.should == [:hash, ["f"*64, hash]]
203
- -> { validator.validate(raise_errors: true) }.should.raise(ValidationError)
204
- end
205
-
206
- it "1. Check syntactic correctness" do
207
- hash = @tx.hash; @tx.instance_eval { @hash = "ff"*32 }
208
- validator = @tx.validator(@store)
209
- validator.validate.should == false
210
- validator.error.should == [:hash, ["ff"*32, hash]]
211
- end
212
-
213
- it "2. Make sure neither in or out lists are empty" do
214
- check_tx(@tx, [:lists, [0, 1]]) {|tx| tx.instance_eval { @in = [] } }
215
- check_tx(@tx, [:lists, [1, 0]]) {|tx| tx.instance_eval { @out = [] } }
216
- end
217
-
218
- it "3. Size in bytes < MAX_BLOCK_SIZE" do
219
- max = Bitcoin::MAX_BLOCK_SIZE; Bitcoin::MAX_BLOCK_SIZE = 1000
220
- check_tx(@tx, [:max_size, [@tx.payload.bytesize+978, 1000]]) {|tx|
221
- tx.out[0].pk_script = "\x00" * 1001 }
222
- Bitcoin::MAX_BLOCK_SIZE = max
223
- end
224
-
225
- it "4. Each output value, as well as the total, must be in legal money range" do
226
- check_tx(@tx, [:output_values, [Bitcoin::network[:max_money] + 1, Bitcoin::network[:max_money]]]) {|tx|
227
- tx.out[0].value = Bitcoin::network[:max_money] + 1 }
228
- end
229
-
230
- it "5. Make sure none of the inputs have hash=0, n=-1" do
231
- check_tx(@tx, [:inputs, [0]]) do |tx|
232
- tx.in.first.prev_out = "\x00"*32
233
- tx.in.first.prev_out_index = 4294967295
234
- end
235
- end
236
-
237
- it "6. Check that nLockTime <= UINT32_MAX, size in bytes >= 100, and sig opcount <= 2" do
238
- check_tx(@tx, [:lock_time, [Bitcoin::UINT32_MAX + 1, Bitcoin::UINT32_MAX]]) {|tx| tx.lock_time = Bitcoin::UINT32_MAX + 1 }
239
- # TODO: validate sig opcount
240
- end
241
-
242
- # it "7. Reject 'nonstandard' transactions: scriptSig doing anything other than pushing numbers on the stack, or scriptPubkey not matching the two usual forms" do
243
- # check_tx(@tx, /standard/) {|tx| tx.out[0].pk_script = Bitcoin::Script.from_string("OP_ADD OP_DUP OP_DROP").raw }
244
- # end
245
-
246
- # it "9. Reject if any other tx in the pool uses the same transaction output as one used by this tx." do
247
- # end
248
-
249
- it "11. For each input, if we are using the nth output of the earlier transaction, but it has fewer than n+1 outputs, reject this transaction" do
250
- check_tx(@tx, [:prev_out, [[@tx.in[0].prev_out.reverse_hth, 2]]]) {|tx| tx.in[0].prev_out_index = 2 }
251
- end
252
-
253
- it "13. Verify crypto signatures for each input; reject if any are bad" do
254
- check_tx(@tx, [:signatures, [0]]) {|tx| @tx.in[0].script_sig = "bad sig" }
255
- end
256
-
257
- it "14. For each input, if the referenced output has already been spent by a transaction in the main branch, reject this transaction" do
258
- block2 = create_block(@block1.hash, true, [
259
- ->(tx) {create_tx(tx, @block1.tx.first, 0, [[50, @key]])}], @key)
260
- if @store.class.name =~ /Utxo/
261
- check_tx(@tx, [:prev_out, [[@tx.in[0].prev_out.reverse_hth, 0]]])
262
- else
263
- check_tx(@tx, [:not_spent, [0]])
264
- end
265
- end
266
-
267
- it "15. Using the referenced output transactions to get input values, check that each input value, as well as the sum, are in legal money range" do
268
- @store.db[@store.class.name =~ /Utxo/ ? :utxo : :txout].order(:id).reverse.limit(1).update(value: 22e14)
269
- check_tx(@tx, [:input_values, [22e14, 21e14]])
270
- end
271
-
272
- it "16. Reject if the sum of input values < sum of output values" do
273
- tx = build_tx {|t| create_tx(t, @block1.tx.first, 0, [[100e8, @key]]) }
274
- check_tx(tx, [:output_sum, [100e8, 50e8]])
275
- end
276
-
277
-
278
- it "should not allow double spend within the same block" do
279
- # double-spend output from previous block
280
- prev_tx = @block1.tx[0]
281
- block = create_block @block1.hash, false, [
282
- ->(t) { create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, @key]]) },
283
- ->(t) { create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, @key]]) }
284
- ]
285
- -> { @store.store_block(block) }.should.raise(Bitcoin::Validation::ValidationError)
286
-
287
- # double-spend output from current block
288
- block = create_block @block1.hash, false, [
289
- ->(t) { create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, @key]]) }
290
- ]
291
- prev_tx = block.tx[1]
292
- block.tx << build_tx {|t| create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, @key]]) }
293
- block.tx << build_tx {|t| create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, @key]]) }
294
- block.recalc_mrkl_root; block.recalc_block_hash
295
- -> { @store.store_block(block) }.should.raise(Bitcoin::Validation::ValidationError)
296
- end
297
-
298
- end
299
-
300
- end
@@ -1,38 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require_relative '../spec_helper'
4
-
5
- include MiniTest
6
- include Bitcoin::Wallet
7
-
8
- describe Bitcoin::Wallet::SimpleCoinSelector do
9
-
10
- def txout_mock(value, next_in = true, in_block = true)
11
- tx, txout = Mock.new, Mock.new
12
- 2.times { tx.expect(:get_block, in_block) }
13
- 5.times { txout.expect(:value, value) }
14
- 2.times do
15
- txout.expect(:get_next_in, next_in)
16
- txout.expect(:get_address, "addr")
17
- txout.expect(:get_tx, tx)
18
- end
19
- txout
20
- end
21
-
22
- it "should select only txouts which have not been spent" do
23
- txouts = [txout_mock(1000, nil), txout_mock(2000, nil),
24
- txout_mock(1000), txout_mock(3000, nil)]
25
- cs = SimpleCoinSelector.new(txouts)
26
- cs.select(2000).should == txouts[0..1]
27
- cs.select(4000).should == [txouts[0], txouts[1], txouts[3]]
28
- end
29
-
30
- it "should select only txouts which are in a block" do
31
- txouts = [txout_mock(1000, nil, false), txout_mock(2000, nil),
32
- txout_mock(1000), txout_mock(3000, nil)]
33
- cs = SimpleCoinSelector.new(txouts)
34
- cs.select(2000).should == txouts[1..1]
35
- cs.select(4000).should == [txouts[1], txouts[3]]
36
- end
37
-
38
- end
@@ -1,69 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require_relative '../spec_helper'
4
-
5
-
6
- include Bitcoin::Wallet
7
- describe "Bitcoin::KeyGenerator" do
8
-
9
- @target = ("\x00\xff" + "\x00"*30).unpack("H*")[0].to_i(16)
10
-
11
- before do
12
- Bitcoin.network = :bitcoin
13
- end
14
-
15
- it "should use random data if no seed given" do
16
- g = KeyGenerator.new(nil, nil, @target)
17
- g.seed.size.should == 64
18
- end
19
-
20
- it "should find the nonce if not given" do
21
- KeyGenerator.new("etd").nonce.should == 622
22
- KeyGenerator.new("foo").nonce.should == 2116
23
- # KeyGenerator.new("bar").nonce.should == 72353
24
- # KeyGenerator.new("baz").nonce.should == 385471
25
- # KeyGenerator.new("qux").nonce.should == 29559
26
- end
27
-
28
- it "should use given nonce" do
29
- g = KeyGenerator.new("foo", 2116)
30
- g.nonce.should == 2116
31
- key = g.get_key(0)
32
- key.addr.should == '1JvRdnShvscPtoP44VxPk5VaFBAo7ozRPb'
33
- key.instance_eval { @pubkey_compressed = false }
34
- key.addr.should == '1GjyUrY3XcR4BvfgL8HqoAJbNDEgxSJdm1'
35
- end
36
-
37
- it "should check nonce if given" do
38
- -> { KeyGenerator.new("foo", 42) }.should.raise ArgumentError
39
- end
40
-
41
- it "should use different target if given" do
42
- g = KeyGenerator.new("foo", nil, @target)
43
- g.nonce.should == 127
44
- g.get_key(0).addr.should == "1KLBACvBnz9BTdBnuJmNuQpKQrsi55sstj"
45
- g = KeyGenerator.new("bar", nil, @target)
46
- g.nonce.should == 40
47
- g.get_key(0).addr.should == "14T4deW5BGVA7wXpR3eoU9U8xprUJepxcy"
48
- end
49
-
50
- it "should find keys" do
51
- g = KeyGenerator.new("foo")
52
- [
53
- "05221211a9c3edb9bdf0c120770dc58d2359098c6f16f6e269f722f7dda27cc9",
54
- "7f27bb0ca02e558c4b4b4e267417437adac01403e0d0bb9b07797d1dbb1adfd1",
55
- "da53dec9916406bb9a412bfdc81a3892bbcb1560ab394cb9b9fc3ee2a41101ff",
56
- "7d63c88d0ab023de3441ff268548dc5f59623efe38fdf481bdebc8bb5047c2f2",
57
- "f582838dcba2a1739307448405905028e330e2c9de2a8ec24eed1648b8bddaa4",
58
- "f438a3ff8ea0ee4422f83a456fa6cadf853381c09a4734ae5fbbae616c535a91",
59
- "3a7442aa54f66ae1c8a0d352346587492269b7c800a0319c9789a8164054c59e",
60
- "523d76467f9c091b0c7240dcc509797c8900d4303b720c6afdc4f218b43a1329",
61
- "a11bfa40a0e920bf449ef0ec1d170513c7c82daafd8c4ae3c0e321ddf5fa5cce",
62
- "86a60cbbad2aadfba910f63dc558dd87777561297810674bec020f0f9f86f630",
63
- "cd1fca7ec2bddddc57fa696aefa1391bf5eeea332b79a1f29cfccfccf082a474",
64
- ].map{|h| [h].pack("H*")}.each_with_index do |key, i|
65
- g.get_key(i).priv.should == key.unpack("H*")[0]
66
- end
67
- end
68
-
69
- end
@@ -1,190 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require_relative '../spec_helper'
4
- require 'json'
5
- require 'fileutils'
6
- include Bitcoin
7
- include Bitcoin::Wallet
8
-
9
- describe "Bitcoin::Wallet::SimpleKeyStore" do
10
-
11
- @test1 = [
12
- {:label => "test1", :addr => "174xCfTggAovtDezgswTgfUeCp1hWJ1i7F", :pub => "040795786162a1a2fb5bb82310fc1b0da3ced5ed8fc3495bbf848b0156eca465688b0cf08d5389c026556213b7e5ccf471d259575e1756e3352ded2a3eec6a59c8", :priv => "c04ea613926036d2782d43eca89512724c9f33f3e8484adb8b952a3837564bcb", :mine => true, :hidden => false},
13
- # 5J4iJt8Co9uzmAK7SnLLkvP6dY9s6882kiF4ZCJCNBpZf8QHjVf
14
- {:addr => "135o74rH4r7vxEuDdozehLeTuzBG7ABdCA", :pub => "04608f68aafef3f216dcb0851bbda7834097a43a0b25794611ebea1177d60c52b25d944ee8c1974f4c9de3d2069cb7ebff803b75487f1f725a6c36a68c2a5ec4ad", :priv => "20c1bb60d9242db6240ae125baa0c2eea838e1e33085ff23e36b7dc4e76bb869", :mine => true, :hidden => false},
15
- # 5JPbwuNwBWDAsKHzSCUWjvZUkwMFooSXEZrDmnQo5wpEGXcfjJY
16
- {:label => "test3", :addr => "1Esx52p3MXsjkWWvUM8Pwm2NP14Rj5GkDF",
17
- :mine => false, :hidden => false},
18
- # 5Hz9HLAm4t8Mgh8i5mGQm7dgqb2R4V88yVUX6RUf2o77uZus7NP
19
- {:label => "test4", :addr => "1F17yu83Rhtg78f8ZoEseXo6aprC1D9fwi",
20
- :mine => false, :hidden => true},
21
- # 5JQnYo4DNdUKKwMiMwQQxova9NExAgPjZybipjx73RxzTTwARch
22
- {:label => "test5", :addr => "17NgKZgaDphrfvdBxmX1EssLX7Jyq4ZA22",
23
- :mine => true, :hidden => false},
24
- # 5KD3KboVn9a31FWZKZ7NxbbvWcbc5f32D3MkU8kfBzFkw7abRZL
25
- {:addr => "1MnSMHjyVSEJE8eC4GUHtuDbvzHbnDBGP7", :pub => "04d4aa8b12642e533a8c3c63a8d99d03b77e642b23134cc4dde11065845a24bca86dd3fa2d4d8801bbc2c032597f9f780e72940a90081be743c0051f9cd286b935", :mine => false, :hidden => false},
26
- ]
27
-
28
- before do
29
- Bitcoin.network = :bitcoin
30
- file_stub = StringIO.new
31
- file_stub.write(@test1.to_json); file_stub.rewind
32
- @ks = SimpleKeyStore.new(file: file_stub)
33
- @key = Bitcoin::Key.generate
34
- end
35
-
36
- it "should create new store" do
37
- file_stub = StringIO.new
38
- file_stub.write(@test1.to_json); file_stub.rewind
39
- ks = SimpleKeyStore.new(file: file_stub)
40
- ks.keys.size.should == 6
41
- end
42
-
43
- it "should load store" do
44
- @ks.keys.size.should == 6
45
- end
46
-
47
- it "should save store" do
48
- file_stub = StringIO.new
49
- file_stub.write(@test1.to_json); file_stub.rewind
50
- ks = SimpleKeyStore.new(file: file_stub)
51
- ks.save_keys
52
- ks2 = SimpleKeyStore.new(file: file_stub)
53
- ks2.keys.should == ks.keys
54
- end
55
-
56
- it "should create new key" do
57
- key = @ks.new_key
58
- @ks.keys.last.should == {:label => nil, :addr => key.addr, :key => key}
59
- end
60
-
61
- it "should delete key" do
62
- @ks.delete(@ks.keys.last[:addr])
63
- @ks.keys.size.should == 5
64
- end
65
-
66
- it "should get key" do
67
- k1 = @ks.key('174xCfTggAovtDezgswTgfUeCp1hWJ1i7F')[:key]
68
- k2 = @ks.key('test1')[:key]
69
- k3 = @ks.key(k2.pub)[:key]
70
- [k1,k2,k3].each{|k| k.priv.should ==
71
- 'c04ea613926036d2782d43eca89512724c9f33f3e8484adb8b952a3837564bcb'}
72
- end
73
-
74
- it "should get keys" do
75
- @ks.key('test1')[:key].priv.should ==
76
- 'c04ea613926036d2782d43eca89512724c9f33f3e8484adb8b952a3837564bcb'
77
- end
78
-
79
- it "should export key" do
80
- k1 = @ks.export('174xCfTggAovtDezgswTgfUeCp1hWJ1i7F')
81
- k2 = @ks.export('test1')
82
- k3 = @ks.export(@ks.key('test1')[:key].pub)
83
- [k1,k2,k3].uniq.should == ['5KGyp1k36dqprA9zBuzEJzf327vw4bTkJARcW13zAKBhAfVmeT3']
84
- end
85
-
86
- it "should import key" do
87
- @ks.import('5JUw75N58166KuA4Pb9s2iJARfu6MC7VaQtFZn523VMuXVYUVSm')
88
- @ks.key('1JovdwZKSby5q3kHLMCX3cCais5YBKVA9x')[:key].priv.should ==
89
- '57c0aea88323c96a75e461499571482ee90d98670a023213f8000047dfa3755c'
90
- @ks.delete('1JovdwZKSby5q3kHLMCX3cCais5YBKVA9x')
91
- @ks.import('5JUw75N58166KuA4Pb9s2iJARfu6MC7VaQtFZn523VMuXVYUVSm', "test2")
92
- @ks.key('test2')[:key].priv.should ==
93
- '57c0aea88323c96a75e461499571482ee90d98670a023213f8000047dfa3755c'
94
- end
95
-
96
- it "should not allow the same label twice" do
97
- -> { @ks.new_key("test1") }.should.raise ArgumentError
98
- -> { @ks.add_key({:label => "test1", :addr => "12345"}) }.should.raise ArgumentError
99
- -> { @ks.import("foobar", "test1") }.should.raise ArgumentError
100
- end
101
-
102
- it "should not allow invalid addrs" do
103
- -> { @ks.add_key({:addr => "foobar"}) }.should.raise ArgumentError
104
- end
105
-
106
- it "should store only address" do
107
- k = {:label => 'test6', :addr => @key.addr}
108
- @ks.add_key(k)
109
- @ks.keys.size.should == 7
110
- @ks.key('test6').should == k
111
- @ks.key(@key.addr).should == k
112
- end
113
-
114
- it "should store only pubkey and addr" do
115
- k = {:label => 'test6', :addr => @key.addr, :pub => @key.pub}
116
- @ks.add_key(k)
117
- @ks.keys.size.should == 7
118
- @ks.key('test6').should == k
119
- @ks.key(@key.addr).should == k
120
- end
121
-
122
- it "should store flags" do
123
- @ks.key('test1')[:mine].should == true
124
- @ks.key('test1')[:hidden].should == false
125
- @ks.flag_key 'test1', :hidden, true
126
- @ks.key('test1')[:hidden].should == true
127
- end
128
-
129
- it "should list only keys which have a label" do
130
- @ks.keys(:label).size.should == 4
131
- end
132
-
133
- it "should list only keys which have a pubkey" do
134
- @ks.keys(:pub).size.should == 3
135
- end
136
-
137
- it "should list only keys which have a privkey" do
138
- @ks.keys(:priv).size.should == 2
139
- end
140
-
141
- it "should list only hidden keys" do
142
- @ks.keys(:hidden).size.should == 1
143
- end
144
-
145
- it "should list only keys which are 'mine'" do
146
- @ks.keys(:mine).size.should == 3
147
- end
148
-
149
- end
150
-
151
-
152
- describe "Bitcoin::Wallet::DeterministicKeyStore" do
153
-
154
- before do
155
- @ks = DeterministicKeyStore.new(:seed => "foo", :keys => 1, :nonce => 2116)
156
- end
157
-
158
- it "should create new store" do
159
- ks = DeterministicKeyStore.new(:seed => "etd", :keys => 3)
160
- ks.keys.size.should == 3
161
- ks.generator.nonce.should == 622
162
- end
163
-
164
- it "should load store" do
165
- @ks.keys.map(&:priv).should ==
166
- ['7f27bb0ca02e558c4b4b4e267417437adac01403e0d0bb9b07797d1dbb1adfd1']
167
- end
168
-
169
- it "should create new key" do
170
- key = @ks.new_key
171
- key.priv.should == 'da53dec9916406bb9a412bfdc81a3892bbcb1560ab394cb9b9fc3ee2a41101ff'
172
- @ks.keys.last.should == key
173
- end
174
-
175
- it "should get key" do
176
- @ks.key('1GKjKQemNRhxL1ChTRFJNLZCXeCDxut2d7').priv.should ==
177
- '7f27bb0ca02e558c4b4b4e267417437adac01403e0d0bb9b07797d1dbb1adfd1'
178
- end
179
-
180
- it "should get keys" do
181
- @ks.keys.map(&:priv).should ==
182
- ['7f27bb0ca02e558c4b4b4e267417437adac01403e0d0bb9b07797d1dbb1adfd1']
183
- end
184
-
185
- it "should export key" do
186
- @ks.export('1GKjKQemNRhxL1ChTRFJNLZCXeCDxut2d7').should ==
187
- 'L1UtDvpnffnVg1szqSmQAgFexzvcysZrs3jwLH1FT4uREpZqcXaR'
188
- end
189
-
190
- end