Class: Tapyrus::Store::SPVChain

Inherits:
Object
  • Object
show all
Defined in:
lib/tapyrus/store/spv_chain.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db = Tapyrus::Store::DB::LevelDB.new, genesis: nil) ⇒ SPVChain

initialize spv chain @param db @param genesis genesis block

Raises:

  • (ArgumentError)


22
23
24
25
26
27
# File 'lib/tapyrus/store/spv_chain.rb', line 22

def initialize(db = Tapyrus::Store::DB::LevelDB.new, genesis: nil)
  raise ArgumentError, 'genesis block should be specified.' unless genesis
  @db = db # TODO multiple db switch
  @logger = Tapyrus::Logger.create(:debug)
  initialize_block(genesis)
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



16
17
18
# File 'lib/tapyrus/store/spv_chain.rb', line 16

def db
  @db
end

#loggerObject (readonly)

Returns the value of attribute logger.



17
18
19
# File 'lib/tapyrus/store/spv_chain.rb', line 17

def logger
  @logger
end

Instance Method Details

#add_agg_pubkey(active_height, agg_pubkey) ⇒ Object

Add aggregated public key.

Parameters:

  • active_height (Integer)
  • agg_pubkey (String)

    aggregated public key with hex format.



95
96
97
# File 'lib/tapyrus/store/spv_chain.rb', line 95

def add_agg_pubkey(active_height, agg_pubkey)
  db.add_agg_pubkey(active_height, agg_pubkey)
end

#agg_pubkeysArray[Array(height, agg_pubkey)]

get aggregated public key keys.

Returns:

  • (Array[Array(height, agg_pubkey)])

    the list of public keys.



101
102
103
# File 'lib/tapyrus/store/spv_chain.rb', line 101

def agg_pubkeys
  db.agg_pubkeys
end

#append_header(header) ⇒ Tapyrus::Store::ChainEntry

append block header to chain.

Parameters:

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/tapyrus/store/spv_chain.rb', line 52

def append_header(header)
  logger.info("append header #{header.block_id}")
  best_block = latest_block
  current_height = best_block.height
  raise "this header is invalid. #{header.block_hash}" unless header.valid?(db.agg_pubkey_with_height(current_height + 1))
  if best_block.block_hash == header.prev_hash
    entry = Tapyrus::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) ⇒ Object

find block entry with the specified hash



43
44
45
46
47
# File 'lib/tapyrus/store/spv_chain.rb', line 43

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) ⇒ Object

find block entry with the specified height.



38
39
40
# File 'lib/tapyrus/store/spv_chain.rb', line 38

def find_entry_by_height(height)
  find_entry_by_hash(db.get_hash_from_height(height))
end

#latest_blockObject

get latest block in the store. @return



31
32
33
34
35
# File 'lib/tapyrus/store/spv_chain.rb', line 31

def latest_block
  hash = db.best_hash
  return nil unless hash
  find_entry_by_hash(hash)
end

#mtp(hash) ⇒ Integer

get median time past for specified block hash

Parameters:

  • hash (String)

    the block hash.

Returns:

  • (Integer)

    the median time past value.



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/tapyrus/store/spv_chain.rb', line 79

def mtp(hash)
  time = []
  Tapyrus::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) ⇒ String

get next block hash for specified hash

Parameters:

  • hash (String)

    the block hash(little endian)

Returns:

  • (String)

    the next block hash. If it does not exist yet, return nil.



72
73
74
# File 'lib/tapyrus/store/spv_chain.rb', line 72

def next_hash(hash)
  db.next_hash(hash)
end