mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-28 13:05:18 +00:00
48d497580a
this is a preparation for migration to confutils based config although there is still some getConfiguration usage in tests code it will be removed after new config arrived
251 lines
8.2 KiB
Nim
251 lines
8.2 KiB
Nim
# Nimbus
|
|
# Copyright (c) 2018 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
# http://opensource.org/licenses/MIT)
|
|
# at your option. This file may not be copied, modified, or distributed except
|
|
# according to those terms.
|
|
|
|
import
|
|
../../chain_config,
|
|
../../db/db_chain,
|
|
../../genesis,
|
|
../../utils,
|
|
../../chain_config,
|
|
../clique,
|
|
../validate,
|
|
../validate/epoch_hash_cache,
|
|
chronicles,
|
|
eth/[common, trie/db],
|
|
stew/endians2,
|
|
stint
|
|
|
|
type
|
|
# Chain's forks not always equals to EVM's forks
|
|
ChainFork* = enum
|
|
Frontier,
|
|
Homestead,
|
|
DAOFork,
|
|
Tangerine,
|
|
Spurious,
|
|
Byzantium,
|
|
Constantinople,
|
|
Petersburg,
|
|
Istanbul,
|
|
MuirGlacier,
|
|
Berlin,
|
|
London
|
|
|
|
Chain* = ref object of AbstractChainDB
|
|
db: BaseChainDB
|
|
forkIds: array[ChainFork, ForkID]
|
|
blockZeroHash: KeccakHash
|
|
|
|
extraValidation: bool ##\
|
|
## Trigger extra validation, currently within `persistBlocks()`
|
|
## function only.
|
|
|
|
verifyFrom: BlockNumber ##\
|
|
## First block to when `extraValidation` will be applied (only
|
|
## effective if `extraValidation` is true.)
|
|
|
|
cacheByEpoch: EpochHashCache ##\
|
|
## Objects cache to speed up hash lookup in validation functions.
|
|
|
|
poa: Clique ##\
|
|
## For non-PoA networks (when `db.config.poaEngine` is `false`),
|
|
## this descriptor is ignored.
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Helpers
|
|
# ------------------------------------------------------------------------------
|
|
|
|
func toNextFork(n: BlockNumber): uint64 =
|
|
if n == high(BlockNumber):
|
|
result = 0'u64
|
|
else:
|
|
result = n.truncate(uint64)
|
|
|
|
func getNextFork(c: ChainConfig, fork: ChainFork): uint64 =
|
|
let next: array[ChainFork, uint64] = [
|
|
0'u64,
|
|
toNextFork(c.homesteadBlock),
|
|
toNextFork(c.daoForkBlock),
|
|
toNextFork(c.eip150Block),
|
|
toNextFork(c.eip158Block),
|
|
toNextFork(c.byzantiumBlock),
|
|
toNextFork(c.constantinopleBlock),
|
|
toNextFork(c.petersburgBlock),
|
|
toNextFork(c.istanbulBlock),
|
|
toNextFork(c.muirGlacierBlock),
|
|
toNextFork(c.berlinBlock),
|
|
toNextFork(c.londonBlock)
|
|
]
|
|
|
|
if fork == high(ChainFork):
|
|
result = 0
|
|
return
|
|
|
|
result = next[fork]
|
|
for x in fork..high(ChainFork):
|
|
if result != next[x]:
|
|
result = next[x]
|
|
break
|
|
|
|
func calculateForkId(c: ChainConfig, fork: ChainFork,
|
|
prevCRC: uint32, prevFork: uint64): ForkID =
|
|
result.nextFork = c.getNextFork(fork)
|
|
|
|
if result.nextFork != prevFork:
|
|
result.crc = crc32(prevCRC, toBytesBE(prevFork))
|
|
else:
|
|
result.crc = prevCRC
|
|
|
|
func calculateForkIds(c: ChainConfig,
|
|
genesisCRC: uint32): array[ChainFork, ForkID] =
|
|
var prevCRC = genesisCRC
|
|
var prevFork = c.getNextFork(Frontier)
|
|
|
|
for fork in ChainFork:
|
|
result[fork] = calculateForkId(c, fork, prevCRC, prevFork)
|
|
prevFork = result[fork].nextFork
|
|
prevCRC = result[fork].crc
|
|
|
|
proc setForkId(c: Chain, cn: CustomNetwork)
|
|
{. raises: [Defect,CatchableError].} =
|
|
let g = genesisBlockForNetwork(c.db.networkId, cn)
|
|
c.blockZeroHash = g.toBlock.blockHash
|
|
let genesisCRC = crc32(0, c.blockZeroHash.data)
|
|
c.forkIds = calculateForkIds(c.db.config, genesisCRC)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private constructor helper
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc initChain(c: Chain; db: BaseChainDB; poa: Clique; extraValidation: bool)
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## Constructor for the `Chain` descriptor object. For most applications,
|
|
## the `poa` argument is transparent and should be initilaised on the fly
|
|
## which is available below.
|
|
c.db = db
|
|
|
|
if not db.config.daoForkSupport:
|
|
db.config.daoForkBlock = db.config.homesteadBlock
|
|
c.extraValidation = extraValidation
|
|
c.setForkId(db.customNetwork)
|
|
|
|
# Initalise the PoA state regardless of whether it is needed on the current
|
|
# network. For non-PoA networks (when `db.config.poaEngine` is `false`),
|
|
# this descriptor is ignored.
|
|
c.poa = db.newClique
|
|
|
|
# Always initialise the epoch cache even though it migh no be used
|
|
# unless `extraValidation` is set `true`.
|
|
c.cacheByEpoch.initEpochHashCache
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public constructors
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc newChain*(db: BaseChainDB; poa: Clique; extraValidation: bool): Chain
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## Constructor for the `Chain` descriptor object. For most applications,
|
|
## the `poa` argument is transparent and should be initilaised on the fly
|
|
## which is available below. The argument `extraValidation` enables extra
|
|
## block chain validation if set `true`.
|
|
new result
|
|
result.initChain(db, poa, extraValidation)
|
|
|
|
|
|
proc newChain*(db: BaseChainDB, extraValidation: bool): Chain
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## Constructor for the `Chain` descriptor object with default initialisation
|
|
## for the PoA handling. The argument `extraValidation` enables extra block
|
|
## chain validation if set `true`.
|
|
new result
|
|
result.initChain(db, db.newClique, extraValidation)
|
|
|
|
proc newChain*(db: BaseChainDB): Chain
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## Constructor for the `Chain` descriptor object. All sub-object descriptors
|
|
## are initialised with defaults. So is extra block chain validation
|
|
## * `enabled` for PoA networks (such as Goerli)
|
|
## * `disabled` for nopn-PaA networks
|
|
new result
|
|
result.initChain(db, db.newClique, db.config.poaEngine)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public `AbstractChainDB` getter overload methods
|
|
# ------------------------------------------------------------------------------
|
|
|
|
method genesisHash*(c: Chain): KeccakHash {.gcsafe.} =
|
|
## Getter: `AbstractChainDB` overload method
|
|
c.blockZeroHash
|
|
|
|
method getBestBlockHeader*(c: Chain): BlockHeader
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## Getter: `AbstractChainDB` overload method
|
|
c.db.getCanonicalHead()
|
|
|
|
method getTrieDB*(c: Chain): TrieDatabaseRef {.gcsafe.} =
|
|
## Getter: `AbstractChainDB` overload method
|
|
c.db.db
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public `Chain` getters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc clique*(c: Chain): var Clique {.inline.} =
|
|
## Getter
|
|
c.poa
|
|
|
|
proc cacheByEpoch*(c: Chain): var EpochHashCache {.inline.} =
|
|
## Getter
|
|
c.cacheByEpoch
|
|
|
|
proc db*(c: Chain): auto {.inline.} =
|
|
## Getter
|
|
c.db
|
|
|
|
proc extraValidation*(c: Chain): auto {.inline.} =
|
|
## Getter
|
|
c.extraValidation
|
|
|
|
proc forkIds*(c: Chain): auto {.inline.} =
|
|
## Getter
|
|
c.forkIds
|
|
|
|
proc verifyFrom*(c: Chain): auto {.inline.} =
|
|
## Getter
|
|
c.verifyFrom
|
|
|
|
proc currentBlock*(c: Chain): BlockHeader
|
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
|
## currentBlock retrieves the current head block of the canonical chain.
|
|
## Ideally the block should be retrieved from the blockchain's internal cache.
|
|
## but now it's enough to retrieve it from database
|
|
c.db.getCanonicalHead()
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public `Chain` setters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc `extraValidation=`*(c: Chain; extraValidation: bool) {.inline.} =
|
|
## Setter. If set `true`, the assignment value `extraValidation` enables
|
|
## extra block chain validation.
|
|
c.extraValidation = extraValidation
|
|
|
|
proc `verifyFrom=`*(c: Chain; verifyFrom: uint64) {.inline.} =
|
|
## Setter. The assignment value `verifyFrom` defines the first block where
|
|
## validation should start if the `Clique` field `extraValidation` was set
|
|
## `true`.
|
|
c.verifyFrom = verifyFrom.u256
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|