class Tapyrus::Validation

Public Instance Methods

check_block(block, state) click to toggle source
# File lib/tapyrus/validation.rb, line 55
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) click to toggle source

check proof of work

# File lib/tapyrus/validation.rb, line 50
def check_block_header(header, state)
  header.block_hash
  header.bits
end
check_tx(tx, state) click to toggle source

check transaction validation

# File lib/tapyrus/validation.rb, line 4
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

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