Jacek Sieka 43d93bcdab
Don't write slot hashes on import (#2564)
The reverse slot hash mechanism causes quite a bit of database traffic
but is broadly not useful except for iterating the storage of an
account, something that a validator never does (it's used by the
tracers).

This flag adds one more thing that is not stored in the database, to be
explored more comprehensively when designing full, validator and archive
modes with different pruning options in the future.

`ldb` says this is 60gb of data (!):
```
ldb --db=. --ignore_unknown_options --column_family=KvtGen approxsize
--hex --from=0x05
--to=0x05ffffffffffffffffffffffffffffffffffffffffffffff
66488353954
```
2024-08-16 08:22:51 +02:00

141 lines
4.5 KiB
Nim

# Nimbus
# Copyright (c) 2024 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
../../../nimbus/[
utils/utils,
common/common,
constants,
db/ledger,
transaction,
evm/state,
evm/types,
core/dao,
core/validate,
core/chain/chain_desc,
core/executor/calculate_reward,
core/executor/process_transaction,
core/executor/process_block
],
chronicles,
results
{.push raises: [].}
proc processBlock(
vmState: BaseVMState; ## Parent environment of header/body block
blk: EthBlock; ## Header/body block to add to the blockchain
): Result[void, string] =
## Generalised function to processes `(header,body)` pair for any network,
## regardless of PoA or not.
##
## Rather than calculating the PoA state change here, it is done with the
## verification in the `chain/persist_blocks.persistBlocks()` method. So
## the `poa` descriptor is currently unused and only provided for later
## implementations (but can be savely removed, as well.)
## variant of `processBlock()` where the `header` argument is explicitely set.
template header: BlockHeader = blk.header
var dbTx = vmState.com.db.ctx.newTransaction()
defer: dbTx.dispose()
let com = vmState.com
if com.daoForkSupport and
com.daoForkBlock.get == header.number:
vmState.mutateStateDB:
db.applyDAOHardFork()
if header.parentBeaconBlockRoot.isSome:
? vmState.processBeaconBlockRoot(header.parentBeaconBlockRoot.get)
? processTransactions(vmState, header, blk.transactions)
if com.isShanghaiOrLater(header.timestamp):
for withdrawal in blk.withdrawals.get:
vmState.stateDB.addBalance(withdrawal.address, withdrawal.weiAmount)
if header.ommersHash != EMPTY_UNCLE_HASH:
discard com.db.persistUncles(blk.uncles)
# EIP-3675: no reward for miner in POA/POS
if com.consensus == ConsensusType.POW:
vmState.calculateReward(header, blk.uncles)
vmState.mutateStateDB:
let clearEmptyAccount = com.isSpuriousOrLater(header.number)
db.persist(clearEmptyAccount)
dbTx.commit()
ok()
proc getVmState(c: ChainRef, header: BlockHeader):
Result[BaseVMState, void] =
if c.vmState.isNil.not:
return ok(c.vmState)
let vmState = BaseVMState()
if not vmState.init(header, c.com, storeSlotHash = storeSlotHash):
debug "Cannot initialise VmState",
number = header.number
return err()
return ok(vmState)
# A stripped down version of persistBlocks without validation
# intended to accepts invalid block
proc setBlock*(c: ChainRef; blk: EthBlock): Result[void, string] =
template header: BlockHeader = blk.header
let dbTx = c.db.ctx.newTransaction()
defer: dbTx.dispose()
c.com.hardForkTransition(header)
# Needed for figuring out whether KVT cleanup is due (see at the end)
let
vmState = c.getVmState(header).valueOr:
return err("no vmstate")
stateRootChpt = vmState.parent.stateRoot # Check point
? vmState.processBlock(blk)
if not c.db.persistHeader(
header, c.com.consensus == ConsensusType.POS, c.com.startOfHistory):
return err("Could not persist header")
try:
c.db.persistTransactions(header.number, header.txRoot, blk.transactions)
c.db.persistReceipts(header.receiptsRoot, vmState.receipts)
if blk.withdrawals.isSome:
c.db.persistWithdrawals(header.withdrawalsRoot, blk.withdrawals.get)
except CatchableError as exc:
return err(exc.msg)
# update currentBlock *after* we persist it
# so the rpc return consistent result
# between eth_blockNumber and eth_syncing
c.com.syncCurrent = header.number
dbTx.commit()
# The `c.db.persistent()` call is ignored by the legacy DB which
# automatically saves persistently when reaching the zero level transaction.
#
# For the `Aristo` database, this code position is only reached if the
# the parent state of the first block (as registered in `headers[0]`) was
# the canonical state before updating. So this state will be saved with
# `persistent()` together with the respective block number.
c.db.persistent(header.number - 1)
ok()
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------