class Bitcoin::Store::SPVChain

Attributes

db[R]
logger[R]

Public Class Methods

new(db = Bitcoin::Store::DB::LevelDB.new) click to toggle source
# File lib/bitcoin/store/spv_chain.rb, line 17
def initialize(db = Bitcoin::Store::DB::LevelDB.new)
  @db = db # TODO multiple db switch
  @logger = Bitcoin::Logger.create(:debug)
  initialize_block
end

Public Instance Methods

append_header(header) click to toggle source

append block header to chain. @param [Bitcoin::BlockHeader] header a block header. @return [Bitcoin::Store::ChainEntry] appended block header entry.

# File lib/bitcoin/store/spv_chain.rb, line 46
def append_header(header)
  logger.info("append header #{header.block_id}")
  raise "this header is invalid. #{header.block_hash}" unless header.valid?
  best_block = latest_block
  current_height = best_block.height
  if best_block.block_hash == header.prev_hash
    entry = Bitcoin::Store::ChainEntry.new(header, current_height + 1)
    db.save_entry(entry)
    entry
  else
    unless find_entry_by_hash(header.block_hash)
      # TODO implements recovery process
      raise "header's previous hash(#{header.prev_hash}) does not match current best block's(#{best_block.block_hash})."
    end
  end
end
find_entry_by_hash(hash) click to toggle source

find block entry with the specified hash

# File lib/bitcoin/store/spv_chain.rb, line 37
def find_entry_by_hash(hash)
  payload = db.get_entry_payload_from_hash(hash)
  return nil unless payload
  ChainEntry.parse_from_payload(payload)
end
find_entry_by_height(height) click to toggle source

find block entry with the specified height.

# File lib/bitcoin/store/spv_chain.rb, line 32
def find_entry_by_height(height)
  find_entry_by_hash(db.get_hash_from_height(height))
end
latest_block() click to toggle source

get latest block in the store. @return

# File lib/bitcoin/store/spv_chain.rb, line 25
def latest_block
  hash = db.best_hash
  return nil unless hash
  find_entry_by_hash(hash)
end
mtp(hash) click to toggle source

get median time past for specified block hash @param [String] hash the block hash. @return [Integer] the median time past value.

# File lib/bitcoin/store/spv_chain.rb, line 73
def mtp(hash)
  time = []
  Bitcoin::MEDIAN_TIME_SPAN.times do
    entry = find_entry_by_hash(hash)
    break unless entry

    time << entry.header.time
    hash = entry.header.prev_hash
  end
  time.sort!
  time[time.size / 2]
end
next_hash(hash) click to toggle source

get next block hash for specified hash @param [String] hash the block hash(little endian) @return [String] the next block hash. If it does not exist yet, return nil.

# File lib/bitcoin/store/spv_chain.rb, line 66
def next_hash(hash)
  db.next_hash(hash)
end

Private Instance Methods

initialize_block() click to toggle source

if database is empty, put genesis block.

# File lib/bitcoin/store/spv_chain.rb, line 89
def initialize_block
  unless latest_block
    block = Bitcoin.chain_params.genesis_block
    genesis = ChainEntry.new(block.header, 0)
    db.save_entry(genesis)
  end
end