Class: Bitcoin::Validation

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/validation.rb

Instance Method Summary collapse

Instance Method Details

#check_block(block, state) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/bitcoin/validation.rb', line 57

def check_block(block, state)
  # check block header
  return false unless check_block_header(block.header, state)

  # check merkle root

  # size limits

  # first tx is coinbase?

  # check tx count

  # check sigop count
end

#check_block_header(header, state) ⇒ Object

check proof of work



51
52
53
54
55
# File 'lib/bitcoin/validation.rb', line 51

def check_block_header(header, state)
  header.block_hash
  header.bits

end

#check_tx(tx, state) ⇒ Object

check transaction validation



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/bitcoin/validation.rb', line 6

def check_tx(tx, state)
  # Basic checks that don't depend on any context
  if tx.inputs.empty?
    return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vin-empty')
  end

  if tx.outputs.empty?
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-empty')
  end

  # Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
  if tx.serialize_old_format.bytesize * Bitcoin::WITNESS_SCALE_FACTOR > Bitcoin::MAX_BLOCK_WEIGHT
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-oversize')
  end

  # Check for negative or overflow output values
  amount = 0
  tx.outputs.each do |o|
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-negative') if o.value < 0
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge') if MAX_MONEY < o.value
    amount += o.value
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge') if MAX_MONEY < amount
  end

  # Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
  out_points = tx.inputs.map{|i|i.out_point.to_payload}
  unless out_points.size == out_points.uniq.size
    return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-inputs-duplicate')
  end

  if tx.coinbase_tx?
    if tx.inputs[0].script_sig.size < 2 || tx.inputs[0].script_sig.size > 100
      return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-cb-length')
    end
  else
    tx.inputs.each do |i|
      if i.out_point.nil? || !i.out_point.valid?
        return state.DoS(10, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-prevout-null')
      end
    end
  end
  true
end