Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions execution_chain/core/chain/forked_chain/chain_private.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# nimbus-execution-client
# Copyright (c) 2025 Status Research & Development GmbH
# Copyright (c) 2025-2026 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
Expand Down Expand Up @@ -53,6 +53,30 @@ proc writeBaggage*(
generatedBal.get(),
)

proc applyBlockAccessList(vmState: BaseVMState, header: Header, bal: BlockAccessListRef) =
# This function assumes that the bal has been validated and therefore
# each of the change lists should already be sorted in ascending order
# by blockAccessIndex.
# We only need to apply the last state change for each of the change lists
# since these will overwrite earlier changes anyway.
vmState.mutateLedger:
for accChanges in bal[]:
if accChanges.balanceChanges.len() > 0:
db.setBalance(accChanges.address, accChanges.balanceChanges[^1].postBalance)
if accChanges.nonceChanges.len() > 0:
db.setNonce(accChanges.address, accChanges.nonceChanges[^1].newNonce)
if accChanges.codeChanges.len() > 0:
db.setCode(accChanges.address, accChanges.codeChanges[^1].newCode)

for storageChange in accChanges.storageChanges:
if storageChange.changes.len() > 0:
db.setStorage(accChanges.address, storageChange.slot, storageChange.changes[^1].newValue)

db.persist(
clearEmptyAccount = vmState.com.isSpuriousOrLater(header.number),
clearCache = true
)

proc processBlock*(
c: ForkedChainRef,
parentBlk: BlockRef,
Expand Down Expand Up @@ -108,7 +132,11 @@ proc processBlock*(
c.badBlocks.put(blkHash, (blk, vmState.blockAccessList))
return err(error)

if not vmState.com.statelessProviderEnabled:
if finalized and blockAccessList.isSome():
# The bal is validated against the header balHash in validateHeaderAndKinship
# so here we skip processing of the block and simply apply the bal state diff.
vmState.applyBlockAccessList(header, blockAccessList.get())
elif not vmState.com.statelessProviderEnabled:
processBlock()
else:
# Clear the caches before executing the block to ensure we collect the correct
Expand Down
12 changes: 9 additions & 3 deletions execution_chain/core/chain/forked_chain/chain_serialize.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# nimbus-execution-client
# Copyright (c) 2025 Status Research & Development GmbH
# Copyright (c) 2025-2026 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
Expand All @@ -19,7 +19,8 @@ import
../../../db/core_db,
../../../db/fcu_db,
../../../db/storage_types,
../../../utils/utils
../../../utils/utils,
../../../common

logScope:
topics = "forked chain"
Expand Down Expand Up @@ -125,6 +126,11 @@ proc replayBlock(fc: ForkedChainRef;
let
parentFrame = parent.txFrame
txFrame = parentFrame.txFrameBegin()
blockAccessList =
if fc.com.isAmsterdamOrLater(blk.header.timestamp):
?parentFrame.getBlockAccessList(blk.hash)
else:
Opt.none(BlockAccessListRef)

# Set finalized to true in order to skip the stateroot check when replaying the
# block because the blocks should have already been checked previously during
Expand All @@ -133,7 +139,7 @@ proc replayBlock(fc: ForkedChainRef;
parent,
txFrame,
blk.blk,
Opt.none(BlockAccessListRef),
blockAccessList,
blk.hash,
finalized = true
).valueOr:
Expand Down