Commit graph

3158 commits

Author SHA1 Message Date
CPerezz
c958bbc73b
core/state/partial: adopt new CodeChanges type for bal-devnet-3
Upstream bal-devnet-3 replaced the CodeChange struct with raw []byte
in ConstructionAccountAccesses.CodeChanges (map[uint16][]byte). Update
the test builder accordingly so the package compiles against the
new API.
2026-04-18 16:03:10 +02:00
CPerezz
fc2d55dd58
core/state/partial: only write modified accounts to trie
Match upstream BALStateTransition behavior: only call UpdateAccount for
accounts that were actually modified (balance, nonce, code, or storage
changes). Previously, all accounts in the BAL (including read-only ones)
were written back to the trie, which could cause root mismatches if the
re-encoded RLP differed from the original encoding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:13:05 +02:00
CPerezz
b5d9b12e70
core/state/partial: fix storage value encoding in trie updates
Trim leading zeros from storage values before passing to UpdateStorage,
matching the upstream BALStateTransition behavior. UpdateStorage
RLP-encodes the value internally, so passing untrimmed 32-byte values
(e.g. [0,0,...,5]) produces different trie nodes than trimmed values
([5]), causing systematic state root mismatches on every BAL-processed
block.

BuildStateSet already correctly trimmed values for the pathdb layer;
this fix aligns the trie update path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:13:05 +02:00
CPerezz
a0c3999bb9
core: fix AdvancePartialHead to initialize partial state root
After the second snap sync completes, AdvancePartialHead moves the head
markers forward but never initialized partialState.Root(). This caused
ProcessBlockWithBAL to fall back to the parent's header root, which
doesn't match the computed trie root from BAL processing — resulting in
a state root mismatch on the first block after sync.

Fix: call SetRoot(root) and SetLastProcessedBlock() in AdvancePartialHead
so subsequent BAL processing chains from the correct state root.

Also add diagnostic logging to ProcessBlockWithBAL for easier debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:13:05 +02:00
CPerezz
962e2de6e1
core, eth: restore stateRoot field using atomic.Pointer
Live testing on bal-devnet-2 confirmed that computed roots DO diverge from
header roots. Block 75315 computed root 0xe909c7.. vs header root
0x9acbbe.. — untracked contracts' storage roots in the local trie are from
snap sync time and differ from the actual current roots, even when the
storage root resolver successfully queries peers.

This means subsequent blocks must chain off the computed root (via
partialState.Root()), not the header root (via parent.Root()). Restore
the stateRoot field using atomic.Pointer[common.Hash] instead of the
previous sync.RWMutex for lock-free concurrent access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:13:05 +02:00
CPerezz
d50dee20ab
core, eth: PR review fixes and remove stateRoot field from PartialState
Apply review fixes: BAL iterator start (Fix 2), fatal root mismatch when
all storage resolved (Fix 3), WriteBlockWithoutState error handling (Fix 4),
contract filter construction order (Fix 5), canonical hash backfill (Fix 6),
underflow guard in gap processing (Fix 8), O(n²) prepend fix (Fix 9),
ReadBALHistory corruption detection (Fix 11), incomplete resolution error
(Fix 13), RLP encode panic (Fix 14), gap processing log level (Fix 16),
TriggerPartialResync message (Fix 18), and comment accuracy fixes.

Remove the stateRoot field and sync.RWMutex from PartialState entirely.
Since partial state maintains the full account trie, the computed root
always matches the header root (assuming storage root resolution succeeds).
ProcessBlockWithBAL now derives parent root from parent.Root() directly,
matching how full nodes derive state root from currentBlock headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:12:46 +02:00
CPerezz
cdb4d77819
core, eth: fix end-to-end partial state sync pipeline
Fix several interacting issues that prevented partial state nodes from
syncing and following the chain on bal-devnet-2:

1. Stale pivot deadlock: Replace unconditional pivot suppression with
   rate-limited advances (2-minute cooldown). This prevents the restart
   loop bug while allowing recovery when the initial pivot is too stale
   for peers to serve.

2. Storage root resolution: Add snap-based resolver that queries peers
   for untracked contracts' storage roots during BAL processing. This
   lets the computed state root converge toward the header root.

3. SetCanonical for partial state: When the computed root differs from
   the header root (expected when untracked contracts have unresolved
   storage roots), check HasState(partialState.Root()) instead of only
   HasState(block.Root()). Guard against zero root during snap sync.

4. Canonical hash backfill: AdvancePartialHead now writes canonical
   hashes for all blocks between the pivot and snap head, fixing the
   "final block not in canonical chain" error caused by
   InsertReceiptChain skipping blocks whose bodies already exist.

5. Gap block processing: After snap sync completes, process accumulated
   blocks between the sync head and chain tip using their persisted BALs
   before entering steady-state chain following.

6. Computed root chaining: Use partialState.Root() (actual computed root)
   as parentRoot for subsequent blocks, not the header root. This ensures
   correct trie chaining when computed != header root.

Tested end-to-end on bal-devnet-2: snap sync completes, gap blocks
processed, canonical head advances at chain tip (~1 block/12s).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:05:26 +02:00
CPerezz
c3c4dfd838
core, eth: fix post-sync block processing and BAL type compatibility
Fix the post-sync deadlock where blocks validated via BAL in newPayload
were never written to the database, causing ForkchoiceUpdated to fail
finding them and triggering infinite sync cycles.

Changes:
- Export WriteBlockWithoutState and call it after ProcessBlockWithBAL
  in newPayload, so FCU can find blocks via GetBlockByHash
- Guard SetCanonical against recoverAncestors for partial state nodes
  (they can't re-execute blocks, only apply BAL diffs)
- Auto-disable log indexing when partial state is enabled (no receipts)
- Fix BAL type field accesses to match upstream bal-devnet-2 types
  (StorageChanges, CodeChanges, BalanceChanges, Validate signature)
- Update newPayload signature (BAL now comes from ExecutableData params)
- Add partial sync scripts and documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:04:09 +02:00
CPerezz
4cd7b3ba6c
core, eth: disable pathdb snapshot generation for partial state
Geth has two independent snapshot tiers, each with its own disable
mechanism:

1. In-memory snapshot cache: controlled by SnapshotLimit (derived from
   ethconfig.SnapshotCache). Setting SnapshotCache=0 disables it.

2. On-disk snapshot generator: a background goroutine in pathdb that
   iterates the entire state trie to build flat key-value snapshots.
   Controlled by pathdb.Config.SnapshotNoBuild.

The partial state configuration (cmd/utils/flags.go) already set
SnapshotCache=0 to disable the in-memory cache. However, SnapshotNoBuild
was never set, so pathdb.Enable() — called after snap sync completes —
still launched the background generator goroutine.

This generator immediately hits missing storage tries for untracked
contracts (whose storage was intentionally skipped during partial sync),
logs "Trie missing, snapshotting paused", and blocks forever on its
abort channel — a permanent goroutine leak with no recovery path.

Additionally, BlockChainConfig.SnapshotNoBuild was never propagated to
pathdb.Config.SnapshotNoBuild in the triedbConfig() conversion. The
field only reached the hash-scheme snapshot module (core/blockchain.go
setupSnapshot), which is already skipped for path-scheme databases. This
plumbing gap meant pathdb.Config.SnapshotNoBuild was never set in
production code — only in tests.

Fix both issues:
- Set SnapshotNoBuild=true when partial state is enabled
- Propagate BlockChainConfig.SnapshotNoBuild into pathdb.Config
2026-04-17 12:01:43 +02:00
CPerezz
bcb2a1bcd5
eth/downloader: add pivot freeze, second state sync, and backfiller guards
Freeze the pivot header for partial state nodes to ensure stable state
sync progress:
- Suppress pivot movement in fetchHeaders() (beaconsync.go)
- Suppress pivot movement in processSnapSyncContent() (downloader.go)
- Reuse existing pivot across sync cycle restarts in syncToHead()

After initial snap sync completes, bridge the gap from pivot to HEAD:
- Import post-pivot blocks with receipts (no execution needed since
  untracked contracts have empty storage tries)
- Run second state sync to download HEAD state root
- Add AdvancePartialHead to update currentBlock without re-execution

Guard the backfiller for partial state mode:
- suspend() skips Cancel() during active snap sync to prevent
  constant cancel/restart cycles from beacon head updates
- resume() skips new sync cycles after partial sync completes
2026-04-17 12:01:42 +02:00
CPerezz
a7a7de7365
eth: add chain retention, BAL engine API support, and bug fixes
Add chain retention for partial state mode: only the most recent N blocks
(default 1024) retain bodies and receipts. During sync, older blocks are
skipped entirely. After sync, the freezer enforces a rolling window.

Add engine API support for Block Access Lists (EIP-7928): NewPayloadV5
accepts BAL data alongside execution payloads, enabling partial state
nodes to receive per-block storage access information from the CL.

Fix beacon backfilling failure caused by dynamic chain cutoff not
clearing the cutoff hash (which remained at the genesis hash).

Add partial state awareness to eth_call/eth_estimateGas to return clear
errors when accessing untracked contract storage.
2026-04-17 11:55:16 +02:00
CPerezz
9f52b96b6c
core: implement partial state BAL processing (Phase 3)
Implement Block Access List (BAL) processing for partial statefulness
per EIP-7928. This enables nodes to update state without re-executing
transactions by applying BAL diffs directly to the trie.

Key additions:
- ApplyBALAndComputeRoot: Core BAL processing with correct commit ordering
  (storage trie → account Root → account trie)
- ProcessBlockWithBAL: Blockchain-level entry point for BAL processing
- HandlePartialReorg: Chain reorganization support using BAL history
- Comprehensive test coverage (31 tests):
  * Unit tests for edge cases (storage deletion, EIP-161, buildStateSet)
  * Blockchain integration tests (ProcessBlockWithBAL, HandlePartialReorg)
  * Both HashScheme and PathScheme coverage

Devnet Testing (2-node setup):
- Full node: dev mode with --dev.period 2, creates blocks
- Partial node: --partial-state mode, syncs via P2P
- Test results: Block sync verified, balance queries match between nodes,
  state roots consistent. Database size reduction observed for partial node.
2026-04-17 11:10:27 +02:00
CPerezz
a5a5f40aa7
core/state: add hash-based filter methods and NewPartialStateSync
Extends ContractFilter interface with hash-based methods (ShouldSyncStorageByHash,
ShouldSyncCodeByHash) for efficient filtering during snap sync when only account
hashes are available.

Adds NewPartialStateSync() function that accepts filter callbacks to control which
accounts have their storage/code synced during healing. This prevents the healing
phase from re-syncing storage for accounts that were intentionally skipped during
initial sync.

Part of partial statefulness Phase 2.
2026-04-17 11:09:19 +02:00
CPerezz
cc2b92b6a4
eth: add partial statefulness foundation (Phase 1)
Implements EIP-7928 BAL-based partial statefulness infrastructure:

- Add PartialStateConfig to eth/ethconfig with CLI flags
- Add ContractFilter interface in core/state/partial/
- Add BAL history database accessors in core/rawdb/
- Add PartialState and BALHistory managers

This enables nodes to track only configured contracts' storage
while maintaining full account trie integrity.
2026-04-17 11:09:19 +02:00
Marius van der Wijden
189bbd91b4 core: fix 8037 transaction inclusion 2026-04-09 15:19:26 +02:00
Marius van der Wijden
cd2095fb4a core/vm: fix two bugs
Fixes the collision bugs and create gas ordering
2026-04-09 15:05:13 +02:00
Sina M
407cf11930
core/state: touch BAL on statedb cache (#34684)
The BAL reader tracker captures access list reads at the reader level.
When statedb has an account cached the BAL tracker is not informed of
the access. This is ok during the lifetime of a transaction because you
only need to record the access the first time. It is also ok during the
lifetime of a block because BAL reads are block-level (same as statedb
caches).

Where I think the issue can rise is in the miner. Namely when building a
block, if the miner picks up a tx which fails, it drops it and picks up
another tx to include. There might be some edge case here where the
failed tx which is not included poisons the cache and a future block
which is included omits an account because it wasn't aware of the
access.
2026-04-08 13:20:58 -04:00
Marius van der Wijden
fa79954576 core: fix rebasing issue 2026-04-08 16:19:24 +02:00
Marius van der Wijden
ce91d227c2 core/vm: fix gas usage 2026-04-08 16:18:54 +02:00
Marius van der Wijden
778326725b core: introduce vm.GasBudget 2026-04-08 15:35:49 +02:00
Marius van der Wijden
0578ebbe1a core/vm: easier logic 2026-04-08 15:34:58 +02:00
Marius van der Wijden
3e37ed1b82 core: fix tx-inclusion tests 2026-04-08 12:44:39 +02:00
Sina M
60096253be
core/types: fix merging state mutations (EIP-7928) (#34640) 2026-04-07 08:57:43 -04:00
Jared Wasinger
6a79e3693b core: preface invalid bal errors so they are caught by the exception mapper 2026-04-05 18:14:18 -04:00
jwasinger
985cdac8a7
core: fix 8037 gas accounting (#34631)
To check whether a transaction can be applied, we validate that
`blockGasLimit > txGasLimit + (cumulativeRegularGasUsed +
cumulativeStateGasUsed)`. However, the check should only be applied to
the bottleneck resource, i.e. `blockGasLimit >
max(txRegularGasUsed+cumulativeRegularGasUsed, txStateGasUsed+
cumulativeStateGasUsed)`.

The changes here break multiple tests.  I am trying to determine why.

---------

Co-authored-by: qu0b <stefan@starflinger.eu>
2026-04-05 18:12:48 -04:00
Jared Wasinger
710ffb03ad core: perform BAL validation against gas limit for blocks which come with access lists
Co-authored-by: spencer <spencer.tb@ethereum.org>
2026-04-05 15:33:42 -04:00
Sina M
c3ad7547ce
core/state: various fixes in EIP-7928 (#34641)
Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-04-03 12:41:45 -04:00
Josh Klopfenstein
53719add20 Some fixes for bal-devnet-3 (#34090)
Rename `balHash` to `blockAccessListHash` in json encoding of block header.  Fix miner panic when attempting to create pre-amsterdam blocks.
2026-03-31 17:59:45 -04:00
Jared Wasinger
e4f847871b core/types: don't include BAL in rlp encoding of full block. Set access list hash on block header when calling 'Block.WithAccessList' 2026-03-31 17:59:43 -04:00
Jared Wasinger
2ff40c7484 core/types/bal: ensure that a written storage slot which was previously read doesn't appear in both the read/write set in the BAL
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-03-31 17:56:43 -04:00
Marius van der Wijden
8327e870e6 all: fix rebasing issues 2026-03-31 17:56:43 -04:00
Marius van der Wijden
18848bca26 all: fix rebasing issues 2026-03-31 17:56:41 -04:00
Marius van der Wijden
98f757bcc2 core: fix deadlock in parallel state processor 2026-03-31 17:53:30 -04:00
Jared Wasinger
c7ab99831a core: fix storage deletion 2026-03-31 17:53:30 -04:00
Jared Wasinger
71ad98ba90 cmd,core,eth,miner:
* add method on StateReaderTracker to clear the accumulated reads
* don't factor the BAL size into the payload size during construction in the miner
* simplify miner code for constructing payloads-with-BALs via the use of aformentioned StateReaderTracker clear method
* clean up the configuration of the BAL execution mode based on the preset flag specified
2026-03-31 17:53:28 -04:00
CPerezz
5f47ac4811 core/types: fix CopyHeader missing BlockAccessListHash deep copy
CopyHeader copies all pointer-typed header fields (WithdrawalsHash,
RequestsHash, SlotNumber, etc.) but was missing the deep copy for
BlockAccessListHash added by EIP-7928. This caused the BAL hash
to be silently shared between the original and the copy, leading
to potential data races and incorrect nil-checks on copied headers.
2026-03-31 17:52:49 -04:00
Jared Wasinger
787464adfc address more lint errors 2026-03-31 17:52:47 -04:00
Jared Wasinger
6d1df21ef9 fix some lint errors (TODO: merge this commit into the 7928 changes 2026-03-31 17:49:53 -04:00
Jared Wasinger
265d74b75e all: implement eip 7928 block access lists 2026-03-31 17:49:49 -04:00
MariusVanDerWijden
40f34eeb08 core: implement EIP-8037: state creation gas cost increase 2026-03-31 16:59:35 -04:00
CPerezz
3da517e239
core/state: fix storage counters in binary trie IntermediateRoot (#34110)
Add missing `StorageUpdated` and `StorageDeleted` counter increments
in the binary trie fast path of `IntermediateRoot()`.
2026-03-31 15:47:07 +02:00
Jonny Rhea
dc3794e3dc
core/rawdb: BAL storage layer (#34064)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Add persistent storage for Block Access Lists (BALs) in `core/rawdb/`.
This provides read/write/delete accessors for BALs in the active
key-value store.

---------

Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-03-31 15:05:31 +08:00
Charles Dusek
e585ad3b42
core/rawdb: fix freezer dir.Sync() failure on Windows (#34115) 2026-03-30 15:34:23 +08:00
Daniel Liu
d1369b69f5
core/txpool/legacypool: use types.Sender instead of signer.Sender (#34059)
Some checks failed
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
`pool.signer.Sender(tx)` bypasses the sender cache used by types.Sender,
which can force an extra signature recovery for every promotable tx
(promotion runs frequently). Use `types.Sender(pool.signer, tx)` here to
keep sender derivation cached and consistent.
2026-03-28 11:46:09 +01:00
rjl493456442
c3467dd8b5
core, miner, trie: relocate witness stats (#34106)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
This PR relocates the witness statistics into the witness itself, making
it more self-contained.
2026-03-27 17:06:46 +01:00
Lessa
8a3a309fa9
core/txpool/legacypool: remove redundant nil check in Get (#34092)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Leftover from d40a255 when return type changed from *txpool.Transaction
to *types.Transaction.
2026-03-26 14:02:31 +01:00
bigbear
5d0e18f775
core/tracing: fix NonceChangeAuthorization comment (#34085)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Comment referenced NonceChangeTransaction which doesn't exist, should be
NonceChangeAuthorization.
2026-03-25 09:16:09 +01:00
Felföldi Zsolt
b87340a856
core, core/vm: implement EIP-7708 (#33645)
This PR implements EIP-7708 according to the latest "rough consensus":

https://github.com/ethereum/EIPs/pull/9003
https://github.com/etan-status/EIPs/blob/fl-ethlogs/EIPS/eip-7708.md

---------

Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
Co-authored-by: raxhvl <raxhvl@users.noreply.github.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-03-23 22:29:53 +08:00
Daniel Liu
a61e5ccb1e
core, internal/ethapi: fix incorrect max-initcode RPC error mapping (#34067)
Problem:

The max-initcode sentinel moved from core to vm, but RPC pre-check
mapping still depended on core.ErrMaxInitCodeSizeExceeded. This mismatch
could surface inconsistent error mapping when oversized initcode is
submitted through JSON-RPC.

Solution:

- Remove core.ErrMaxInitCodeSizeExceeded from the core pre-check error
set.
- Map max-initcode validation errors in RPC from
vm.ErrMaxInitCodeSizeExceeded.
- Keep the RPC error code mapping unchanged (-38025).

Impact:

- Restores consistent max-initcode error mapping after the sentinel
move.
- Preserves existing JSON-RPC client expectations for error code -38025.
- No consensus, state, or protocol behavior changes.
2026-03-23 22:10:32 +08:00
Lessa
e23b0cbc22
core/rawdb: fix key length check for num -- hash in db inspect (#34074)
Fix incorrect key length calculation for `numHashPairings` in
`InspectDatabase`, introduced in #34000.

The `headerHashKey` format is `headerPrefix + num + headerHashSuffix`
(10 bytes), but the check incorrectly included `common.HashLength`,
expecting 42 bytes.

This caused all number -- hash entries to be misclassified as
unaccounted data.
2026-03-23 21:54:30 +08:00