2018-10-05 00:20:12 +00:00
|
|
|
import
|
2021-09-16 15:59:46 +00:00
|
|
|
std/tables,
|
2022-02-01 12:04:20 +00:00
|
|
|
eth/[common, rlp, p2p],
|
2021-10-28 03:48:28 +00:00
|
|
|
chronicles, eth/trie/[db, trie_defs],
|
2021-05-13 09:01:58 +00:00
|
|
|
./db/[db_chain, state_db],
|
2021-10-28 03:48:28 +00:00
|
|
|
"."/[constants, chain_config, forks, p2p/gaslimit]
|
2020-01-13 18:35:40 +00:00
|
|
|
|
2022-02-11 16:28:39 +00:00
|
|
|
{.push raises: [Defect].}
|
2022-02-01 12:04:20 +00:00
|
|
|
|
2022-02-11 16:28:39 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
proc initDbAccounts(db: BaseChainDB): BlockHeader
|
|
|
|
{.raises: [Defect, RlpError].} =
|
|
|
|
## Initialise block chain DB accounts derived from the `genesis.alloc` table
|
|
|
|
## of the `db` descriptor argument.
|
|
|
|
##
|
|
|
|
## The function returns the `Genesis` block header.
|
|
|
|
##
|
|
|
|
|
|
|
|
# For `eth/trie/db.newMemoryDB()`, the following initialisation is part of
|
2022-02-01 12:04:20 +00:00
|
|
|
# the constructor function which is missing for the permanent constructor
|
|
|
|
# function `eth/trie/db.trieDB()`.
|
2022-02-11 16:28:39 +00:00
|
|
|
db.db.put(emptyRlpHash.data, emptyRlp)
|
2022-02-01 12:04:20 +00:00
|
|
|
|
2022-02-11 16:28:39 +00:00
|
|
|
var sdb = newAccountStateDB(db.db, emptyRlpHash, db.pruneTrie)
|
|
|
|
let g = db.genesis
|
2018-08-01 12:50:44 +00:00
|
|
|
|
|
|
|
for address, account in g.alloc:
|
2018-08-09 09:25:37 +00:00
|
|
|
sdb.setAccount(address, newAccount(account.nonce, account.balance))
|
2020-04-20 18:12:44 +00:00
|
|
|
sdb.setCode(address, account.code)
|
2022-02-01 12:04:20 +00:00
|
|
|
|
|
|
|
# Kludge:
|
|
|
|
#
|
|
|
|
# With the pruning persistent version, the initial/trivial key-value
|
|
|
|
# pair `(emptyRlpHash.data,emptyRlp)` will have been deleted after
|
|
|
|
# adding a non-trivial key-value pair in one of the above functions.
|
|
|
|
# This happens in the function/template
|
|
|
|
#
|
|
|
|
# eth/trie/db.del() called by
|
|
|
|
# eth/trie/hexary.prune() invoked by
|
|
|
|
# eth/trie/hexary.origWithNewValue() invoked by
|
|
|
|
# eth/trie/hexary.mergeAt() called by
|
|
|
|
# eth/trie/hexary.put()
|
|
|
|
#
|
|
|
|
# if the database contains the trivial key-value pair, only.
|
|
|
|
# Unfortunately, the *trie* is now empty but the previous root hash
|
|
|
|
# is re-used. This leads to an assert exception in any subsequent
|
|
|
|
# invocation of `eth/trie/hexary.put()`.
|
|
|
|
#
|
|
|
|
# See also https://github.com/status-im/nim-eth/issues/9 where other,
|
|
|
|
# probably related debilities are discussed.
|
|
|
|
#
|
|
|
|
# This kludge also fixes the initial crash described in
|
|
|
|
# https://github.com/status-im/nimbus-eth1/issues/932.
|
2022-02-11 16:28:39 +00:00
|
|
|
if not db.isNil and db.pruneTrie and 0 < account.storage.len:
|
|
|
|
db.db.put(emptyRlpHash.data, emptyRlp) # <-- kludge
|
2022-02-01 12:04:20 +00:00
|
|
|
|
2018-08-09 09:25:37 +00:00
|
|
|
for k, v in account.storage:
|
|
|
|
sdb.setStorage(address, k, v)
|
2018-08-01 12:50:44 +00:00
|
|
|
|
|
|
|
result = BlockHeader(
|
|
|
|
nonce: g.nonce,
|
|
|
|
timestamp: g.timestamp,
|
|
|
|
extraData: g.extraData,
|
|
|
|
gasLimit: g.gasLimit,
|
|
|
|
difficulty: g.difficulty,
|
|
|
|
mixDigest: g.mixhash,
|
|
|
|
coinbase: g.coinbase,
|
2021-05-13 09:01:58 +00:00
|
|
|
stateRoot: sdb.rootHash,
|
2018-08-01 12:50:44 +00:00
|
|
|
parentHash: GENESIS_PARENT_HASH,
|
|
|
|
txRoot: BLANK_ROOT_HASH,
|
|
|
|
receiptRoot: BLANK_ROOT_HASH,
|
|
|
|
ommersHash: EMPTY_UNCLE_HASH
|
|
|
|
)
|
|
|
|
|
2021-06-30 13:30:39 +00:00
|
|
|
if g.baseFeePerGas.isSome:
|
|
|
|
result.baseFee = g.baseFeePerGas.get()
|
2022-02-11 16:28:39 +00:00
|
|
|
elif db.config.toFork(0.toBlockNumber) >= FkLondon:
|
2021-06-30 13:30:39 +00:00
|
|
|
result.baseFee = EIP1559_INITIAL_BASE_FEE.u256
|
|
|
|
|
2021-09-16 15:59:46 +00:00
|
|
|
if g.gasLimit.isZero:
|
2018-08-01 12:50:44 +00:00
|
|
|
result.gasLimit = GENESIS_GAS_LIMIT
|
|
|
|
|
2021-09-16 15:59:46 +00:00
|
|
|
if g.difficulty.isZero:
|
2018-08-01 12:50:44 +00:00
|
|
|
result.difficulty = GENESIS_DIFFICULTY
|
|
|
|
|
2022-02-11 16:28:39 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2022-02-14 14:22:39 +00:00
|
|
|
proc toGenesisHeader*(params: NetworkParams, db = newMemoryDb()): BlockHeader
|
2022-02-11 16:28:39 +00:00
|
|
|
{.raises: [Defect, RlpError].} =
|
|
|
|
## Generate the genesis block header from the `params` argument value.
|
|
|
|
newBaseChainDB(
|
2022-02-14 14:22:39 +00:00
|
|
|
db = db,
|
2022-02-11 16:28:39 +00:00
|
|
|
id = params.config.chainID.NetworkId,
|
|
|
|
params = params,
|
|
|
|
pruneTrie = true).initDbAccounts
|
2022-02-01 12:04:20 +00:00
|
|
|
|
2022-02-11 16:28:39 +00:00
|
|
|
proc toGenesisHeader*(db: BaseChainDB): BlockHeader
|
|
|
|
{.raises: [Defect, RlpError].} =
|
|
|
|
## Generate the genesis block header from the `genesis` and `config`
|
|
|
|
## fields of the argument `db` descriptor.
|
|
|
|
NetworkParams(
|
|
|
|
config: db.config,
|
2022-02-14 14:22:39 +00:00
|
|
|
genesis: db.genesis).toGenesisHeader(db.db)
|
2022-02-11 16:28:39 +00:00
|
|
|
|
|
|
|
proc initializeEmptyDb*(db: BaseChainDB)
|
|
|
|
{.raises: [Defect, CatchableError].} =
|
2019-01-08 10:47:40 +00:00
|
|
|
trace "Writing genesis to DB"
|
2022-02-11 16:28:39 +00:00
|
|
|
let b = db.initDbAccounts
|
2021-09-16 15:59:46 +00:00
|
|
|
doAssert(b.blockNumber.isZero, "can't commit genesis block with number > 0")
|
|
|
|
discard db.persistHeaderToDb(b)
|
2022-02-11 16:28:39 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|