From b7751666ca0f1ef87526aeb6902ebe14b0ca4e8a Mon Sep 17 00:00:00 2001 From: sudeepdino008 Date: Mon, 10 Aug 2026 16:04:33 +0200 Subject: [PATCH] execution/stagedsync: drop the block write buffer from calcFees/finalize readers (#23140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calcFees and finalize (finalizeTx and the block-end finalizeSystemTx) read through NewVersionedStateReader(be.versionMap, ...), so the version map supplies all accumulated in-block state. The state reader passed alongside is only the pre-block base. It therefore does not need the BlockStateCache write buffer. Pass nil block cache to these readers. Values are unchanged: a version-map miss means no tx wrote the key, so the read falls to the pre-block base, which the plain reader serves. The finalize-comment claiming the buffer is load-bearing was stale — the version map has supplied in-block state since the parallel commitment work landed. The block-complete engine.Finalize IBS (withdrawals/EIP-7002/7251) still uses the write buffer; a later part of #23140 moves it to the version map. --- execution/stagedsync/exec3_parallel.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/execution/stagedsync/exec3_parallel.go b/execution/stagedsync/exec3_parallel.go index 78a73aea00c..0c5f678a713 100644 --- a/execution/stagedsync/exec3_parallel.go +++ b/execution/stagedsync/exec3_parallel.go @@ -2735,10 +2735,13 @@ func (be *blockExecutor) nextResult(ctx context.Context, pe *parallelExecutor, r return nil, fmt.Errorf("apply loop: unexpected task type for tx %d: result.Task=%T", tx, txResult.Task) } if stateReader == nil { + // calcFees reads through NewVersionedStateReader(be.versionMap, ...), + // so the version map supplies all in-block state. This reader is only + // the pre-block base, so it does not need the block write buffer. if txTask.IsHistoric() { - stateReader = state.NewHistoryReaderV3WithBlockCache(applyTx, pe.rs.Domains(), be.blockStateCache, txTask.Version().TxNum) + stateReader = state.NewHistoryReaderV3WithBlockCache(applyTx, pe.rs.Domains(), nil, txTask.Version().TxNum) } else { - stateReader = state.NewCurrentCachedReaderV3(pe.rs.Domains().AsGetter(applyTx), be.blockStateCache) + stateReader = state.NewCurrentCachedReaderV3(pe.rs.Domains().AsGetter(applyTx), nil) } } tipWrites, err := txResult.calcFees(taskVer, be.versionMap, stateReader, txTask.Rules()) @@ -2850,15 +2853,15 @@ func (be *blockExecutor) nextResult(ctx context.Context, pe *parallelExecutor, r } if stateReader == nil { + // finalize (finalizeTx and the block-end finalizeSystemTx) reads + // through NewVersionedStateReader(be.versionMap, ...), so all + // accumulated in-block state comes from the version map. This + // reader is only the pre-block base and does not need the block + // write buffer. if txTask.IsHistoric() { - stateReader = state.NewHistoryReaderV3WithBlockCache(applyTx, pe.rs.Domains(), be.blockStateCache, txTask.Version().TxNum) + stateReader = state.NewHistoryReaderV3WithBlockCache(applyTx, pe.rs.Domains(), nil, txTask.Version().TxNum) } else { - // Use CachedReaderV3 with readCurrent=true so the - // finalize (including system TXs) reads from the - // BlockStateCache write buffer. This ensures the - // system TX sees all accumulated state from prior - // TXs in the block, not stale sd.mem values. - stateReader = state.NewCurrentCachedReaderV3(pe.rs.Domains().AsGetterNoMetrics(applyTx), be.blockStateCache) + stateReader = state.NewCurrentCachedReaderV3(pe.rs.Domains().AsGetterNoMetrics(applyTx), nil) } }