Class: Ciri::Chain::HeaderChain
- Inherits:
-
Object
- Object
- Ciri::Chain::HeaderChain
- Defined in:
- lib/ciri/chain/header_chain.rb
Constant Summary collapse
- HEAD =
'head'- GENESIS =
'genesis'- HEADER_PREFIX =
'h'- TD_SUFFIX =
't'- NUM_SUFFIX =
'n'
Instance Attribute Summary collapse
-
#store ⇒ Object
readonly
Returns the value of attribute store.
Instance Method Summary collapse
-
#calculate_difficulty(header, parent_header) ⇒ Object
calculate header difficulty you can find explain in Ethereum yellow paper: Block Header Validity section.
- #get_header(hash) ⇒ Object
- #get_header_by_number(number) ⇒ Object
- #get_header_hash_by_number(number) ⇒ Object
- #head ⇒ Object
- #head=(header) ⇒ Object
-
#initialize(store, fork_config: nil) ⇒ HeaderChain
constructor
A new instance of HeaderChain.
- #total_difficulty(header_hash = head.nil? ? nil : head.get_hash) ⇒ Object
- #valid?(header) ⇒ Boolean
-
#write(header) ⇒ Object
write header.
- #write_header_hash_number(header_hash, number) ⇒ Object
Constructor Details
#initialize(store, fork_config: nil) ⇒ HeaderChain
Returns a new instance of HeaderChain.
15 16 17 18 |
# File 'lib/ciri/chain/header_chain.rb', line 15 def initialize(store, fork_config: nil) @store = store @fork_config = fork_config end |
Instance Attribute Details
#store ⇒ Object (readonly)
Returns the value of attribute store.
13 14 15 |
# File 'lib/ciri/chain/header_chain.rb', line 13 def store @store end |
Instance Method Details
#calculate_difficulty(header, parent_header) ⇒ Object
calculate header difficulty you can find explain in Ethereum yellow paper: Block Header Validity section.
70 71 72 73 74 75 |
# File 'lib/ciri/chain/header_chain.rb', line 70 def calculate_difficulty(header, parent_header) return header.difficulty if header.number == 0 fork_schema = @fork_config.choose_fork(header.number) fork_schema.calculate_difficulty(header, parent_header) end |
#get_header(hash) ⇒ Object
29 30 31 32 |
# File 'lib/ciri/chain/header_chain.rb', line 29 def get_header(hash) encoded = store[HEADER_PREFIX + hash] encoded && Header.rlp_decode(encoded) end |
#get_header_by_number(number) ⇒ Object
34 35 36 37 |
# File 'lib/ciri/chain/header_chain.rb', line 34 def get_header_by_number(number) hash = get_header_hash_by_number(number) hash && get_header(hash) end |
#get_header_hash_by_number(number) ⇒ Object
101 102 103 104 |
# File 'lib/ciri/chain/header_chain.rb', line 101 def get_header_hash_by_number(number) enc_number = Utils.big_endian_encode number store[HEADER_PREFIX + enc_number + NUM_SUFFIX] end |
#head ⇒ Object
20 21 22 23 |
# File 'lib/ciri/chain/header_chain.rb', line 20 def head encoded = store[HEAD] encoded && Header.rlp_decode(encoded) end |
#head=(header) ⇒ Object
25 26 27 |
# File 'lib/ciri/chain/header_chain.rb', line 25 def head=(header) store[HEAD] = header.rlp_encode end |
#total_difficulty(header_hash = head.nil? ? nil : head.get_hash) ⇒ Object
106 107 108 109 |
# File 'lib/ciri/chain/header_chain.rb', line 106 def total_difficulty(header_hash = head.nil? ? nil : head.get_hash) return 0 if header_hash.nil? RLP.decode(store[HEADER_PREFIX + header_hash + TD_SUFFIX], Integer) end |
#valid?(header) ⇒ Boolean
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ciri/chain/header_chain.rb', line 39 def valid?(header) # ignore genesis header if there not exist one return true if header.number == 0 && get_header_by_number(0).nil? parent_header = get_header(header.parent_hash) return false unless parent_header # check height return false unless parent_header.number + 1 == header.number # check timestamp return false unless parent_header. < header. # check gas limit range parent_gas_limit = parent_header.gas_limit gas_limit_max = parent_gas_limit + parent_gas_limit / 1024 gas_limit_min = parent_gas_limit - parent_gas_limit / 1024 gas_limit = header.gas_limit return false unless gas_limit >= 5000 && gas_limit > gas_limit_min && gas_limit < gas_limit_max return false unless calculate_difficulty(header, parent_header) == header.difficulty # check pow begin POW.check_pow(header.number, header.mining_hash, header.mix_hash, header.nonce, header.difficulty) rescue POW::InvalidError return false end true end |
#write(header) ⇒ Object
write header
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/ciri/chain/header_chain.rb', line 78 def write(header) hash = header.get_hash # get total difficulty td = if header.number == 0 header.difficulty else parent_header = get_header(header.parent_hash) raise "can't find parent from db" unless parent_header parent_td = total_difficulty(parent_header.get_hash) parent_td + header.difficulty end # write header and td store.batch do |b| b.put(HEADER_PREFIX + hash, header.rlp_encode) b.put(HEADER_PREFIX + hash + TD_SUFFIX, RLP.encode(td, Integer)) end end |
#write_header_hash_number(header_hash, number) ⇒ Object
96 97 98 99 |
# File 'lib/ciri/chain/header_chain.rb', line 96 def write_header_hash_number(header_hash, number) enc_number = Utils.big_endian_encode number store[HEADER_PREFIX + enc_number + NUM_SUFFIX] = header_hash end |