Commit 817cbff711147530e3698ca7379faa54d7801d77

Authored by comboy
Committed by Julian Langschaedel
1 parent 65a24e02ed

check for double spends within currently validated block

Showing 2 changed files with 16 additions and 3 deletions Side-by-side Diff

lib/bitcoin/validation.rb
... ... @@ -130,6 +130,9 @@
130 130  
131 131 # check transactions
132 132 def transactions_syntax
  133 + # check if there are no double spends within this block
  134 + return false if block.tx.map(&:in).flatten.map {|i| [i.prev_out, i.prev_out_index] }.uniq! != nil
  135 +
133 136 tx_validators.all?{|v|
134 137 begin
135 138 v.validate(rules: [:syntax], raise_errors: true)
... ... @@ -199,7 +202,7 @@
199 202  
200 203 RULES = {
201 204 syntax: [:hash, :lists, :max_size, :output_values, :inputs, :lock_time, :standard],
202   - context: [:prev_out, :signatures, :spent, :input_values, :output_sum]
  205 + context: [:prev_out, :signatures, :not_spent, :input_values, :output_sum]
203 206 }
204 207  
205 208 # validate tx rules. +opts+ are:
... ... @@ -303,8 +306,8 @@
303 306 sigs.all? || sigs.map.with_index {|s, i| s ? nil : i }.compact
304 307 end
305 308  
306   - # check that none of the prev_outs are already spent in the main chain
307   - def spent
  309 + # check that none of the prev_outs are already spent in the main chain or in the current block
  310 + def not_spent
308 311 # find all spent txouts
309 312 # OPTIMIZE: these could be fetched in one query for all transactions and cached
310 313 next_ins = store.get_txins_for_txouts(tx.in.map.with_index {|txin, idx| [prev_txs[idx].hash, txin.prev_out_index] })
spec/bitcoin/storage/validation_spec.rb
... ... @@ -272,6 +272,16 @@
272 272 check_tx(tx, [:output_sum, [100e8, 50e8]])
273 273 end
274 274  
  275 +
  276 + it "should not allow double spend within a block" do
  277 + prev_tx = @block1.tx[0]
  278 + block = create_block @block1.hash, false, [
  279 + ->(t) { create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, Bitcoin::Key.generate]], @key) },
  280 + ->(t) { create_tx(t, prev_tx, 0, [[prev_tx.out[0].value, Bitcoin::Key.generate]], @key) }
  281 + ]
  282 + -> { @store.store_block(block) }.should.raise(Bitcoin::Validation::ValidationError)
  283 + end
  284 +
275 285 end
276 286  
277 287 end