You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-on design from #19623 (2-cache IBS refactor). While #19623 focuses on eliminating stateObject and the IBS round-trip within the current architecture, this issue captures the higher-level ownership restructuring and cross-process optimization opportunities that should inform the implementation to avoid costly future refactors.
These observations emerged during PR #19814 (direct finalize path + unit tests), where the brittleness of IBS's multiple implicit roles became apparent.
Problem
IntraBlockState serves multiple implicit roles:
Execution context — per-TX state objects, journal, snapshots
Version tracking — versioned reads/writes for parallel validation
This exists because originStorage gets updated by each FinalizeTx, so by CommitBlock time it equals the dirty value.
1. TransactionState / BlockState Separation
TransactionState (per-TX, request-scoped)
Key design decision: TransactionState should NOT be owned by the worker and reset between TXs. It should be part of the request — a value object with immutable inputs and value-type outputs. This avoids:
Worker lifecycle bleeding into state lifecycle
Hidden state leaks between TXs (today's IBS.Reset() is fragile)
Coupling that prevents caching
The execution model becomes: (TransactionState, inputs) → (TransactionState, outputs)
Contains:
Account state objects (balance, nonce, code, storage)
Journal for revert snapshots
Dirty tracking
No version map, no BAL, no block-level concerns
BlockState (per-block)
Contains:
Version map (parallel execution)
Block-origin storage values
Accumulated block IO (reads/writes per TX)
BAL computation state
Fee-calc coordination (coinbase/burnt deltas)
Combine(txResult) merges TX results into block state
2. TxTask Refactoring
TxTask has grown organically serving multiple scenarios:
execution/exec/txtask.go — TxTask (the multi-purpose envelope)
Notes
The TransactionState/BlockState separation and TxTask refactoring are too broad for initial implementation but must inform Rationalize IntraBlockState to a 2-Cache Model #19623's design to avoid costly future refactors
Cross-process TX caching requires serial exec deprecation first
Context
Follow-on design from #19623 (2-cache IBS refactor). While #19623 focuses on eliminating
stateObjectand the IBS round-trip within the current architecture, this issue captures the higher-level ownership restructuring and cross-process optimization opportunities that should inform the implementation to avoid costly future refactors.These observations emerged during PR #19814 (direct finalize path + unit tests), where the brittleness of IBS's multiple implicit roles became apparent.
Problem
IntraBlockStateserves multiple implicit roles:refreshVersionedAccountfor EIP-7928The
FinalizeTxvsCommitBlockdistinction is extremely subtle:FinalizeTx:useBlockOrigin=false(originStorage — last written value)CommitBlock:useBlockOrigin=true(blockOriginStorage — block-start value)This exists because
originStoragegets updated by eachFinalizeTx, so byCommitBlocktime it equals the dirty value.1. TransactionState / BlockState Separation
TransactionState (per-TX, request-scoped)
Key design decision: TransactionState should NOT be owned by the worker and reset between TXs. It should be part of the request — a value object with immutable inputs and value-type outputs. This avoids:
IBS.Reset()is fragile)The execution model becomes:
(TransactionState, inputs) → (TransactionState, outputs)Contains:
BlockState (per-block)
Contains:
Combine(txResult)merges TX results into block state2. TxTask Refactoring
TxTaskhas grown organically serving multiple scenarios:eth_call,eth_estimateGas)The flags
shouldDelayFeeCalc,HistoryExecution,InBatch,AAValidationBatchSizeare symptoms of one object doing too many jobs.TxTask should be split into:
3. Cross-Process TX Caching
TX execution happens in multiple places in Erigon:
eth_call,eth_estimateGas,trace_*)If TransactionState is a pure function of inputs, the cache key becomes:
This enables:
eth_callresults4. BAL Read Generation Decoupling
Currently tightly coupled to IBS via
refreshVersionedAccount. Must be decoupled so that:finalizeTx) can generate correct BAL reads without IBS reconstruction(TxOut addresses, prestate)Implementation Sequencing
These changes build on #19623's 5-phase plan and extend it:
Key Files
execution/stagedsync/exec3_parallel.go— finalize dispatch, finalizeTx, finalizeWithIBSexecution/stagedsync/exec3_finalize_test.go— comparison unit tests (PR exec3_parallel: eliminate IBS round-trip in finalize path #19814)execution/state/intra_block_state.go— IBS (the monolith)execution/state/versionedio.go— version map, BAL computationexecution/state/state_object.go— account state, updateStorageexecution/exec/txtask.go— TxTask (the multi-purpose envelope)Notes