Class: Bitcoin::Validation
- Inherits:
-
Object
- Object
- Bitcoin::Validation
- Defined in:
- lib/bitcoin/validation.rb
Instance Method Summary collapse
- #check_block(block, state) ⇒ Object
-
#check_block_header(header, state) ⇒ Object
check proof of work.
-
#check_tx(tx, state) ⇒ Object
check transaction validation.
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 |