Skip to content

[r3.4] execution/state: revert CodeSizePath in codeChange journal entry#20194

Merged
lystopad merged 1 commit into
release/3.4from
feature/lystopad/r3.4-fix-codesizepath-revert
Mar 27, 2026
Merged

[r3.4] execution/state: revert CodeSizePath in codeChange journal entry#20194
lystopad merged 1 commit into
release/3.4from
feature/lystopad/r3.4-fix-codesizepath-revert

Conversation

@lystopad

Copy link
Copy Markdown
Member

Summary

Backport of main commit 94a02c2bbb to release/3.4, adapted for r3.4's *VersionedWrite pointer map.

The bug

SetCode writes three versioned entries (CodePath, CodeHashPath, CodeSizePath) to versionedWrites, but codeChange.revert() only cleaned up CodePath and CodeHashPath. The stale CodeSizePath caused GetCodeSize to return the pre-revert value after a parent frame reverted a child CREATE/CREATE2, making EXTCODESIZE report wrong results.

Concrete impact: contracts checking extcodesize(addr) > 0 after a failed deployment see a non-zero size instead of 0, taking a different code path and computing different gas. This produces arbitrary gas under-counts that fail block validation with "gas used by execution: X, in header: Y".

Observed in production:

  • Mainnet node (r3.4, build cd4cc8e1) stuck at block 24741565 with -61,560 gas diff
  • Hoodi node previously exhibited similar pattern at block 2486302

The fix

Add CodeSizePath cleanup to both branches of codeChange.revert():

  • wasCommited == true: Delete(CodeSizePath) alongside the existing Delete calls
  • wasCommited == false: restore v.Val = len(ch.prevcode) (r3.4 uses *VersionedWrite pointers, not UpdateVal)

Adaptation from main

Main uses WriteSet.UpdateVal() (added in the IBS 2-cache refactor which is main-only). r3.4's WriteSet stores *VersionedWrite pointers, so direct v.Val = ... assignment modifies the map entry in place — consistent with all other wasCommited == false revert handlers in r3.4's journal.go.

Test plan

  • make erigon builds cleanly
  • make lint clean (0 issues)
  • Mainnet node at block 24741565 unblocked after deploying this fix

SetCode writes three versioned entries (CodePath, CodeHashPath,
CodeSizePath), but codeChange.revert() only cleaned up CodePath and
CodeHashPath. The stale CodeSizePath caused GetCodeSize to return the
pre-revert value after a parent frame reverted a child CREATE/CREATE2,
making EXTCODESIZE report wrong results.

This caused EVM execution to take wrong code paths (e.g. contracts
checking extcodesize(addr) > 0 after a failed deploy), resulting in
arbitrary gas under-counts that fail block validation.

Fix: add CodeSizePath cleanup to both branches of codeChange.revert().
  - wasCommited == true:  Delete(CodeSizePath) alongside the existing Deletes
  - wasCommited == false: restore v.Val = len(ch.prevcode)

Backport of main commit 94a02c2, adapted for r3.4's *VersionedWrite
pointer map (uses v.Val = ... instead of UpdateVal).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lystopad lystopad merged commit ad5dc81 into release/3.4 Mar 27, 2026
22 checks passed
@lystopad lystopad deleted the feature/lystopad/r3.4-fix-codesizepath-revert branch March 27, 2026 14:56
AskAlexSharov pushed a commit that referenced this pull request Apr 6, 2026
…ry (#20194)

## Summary

Backport of main commit `94a02c2bbb` to `release/3.4`, adapted for
r3.4's `*VersionedWrite` pointer map.

### The bug

`SetCode` writes three versioned entries (`CodePath`, `CodeHashPath`,
`CodeSizePath`) to `versionedWrites`, but `codeChange.revert()` only
cleaned up `CodePath` and `CodeHashPath`. The stale `CodeSizePath`
caused `GetCodeSize` to return the pre-revert value after a parent frame
reverted a child `CREATE`/`CREATE2`, making `EXTCODESIZE` report wrong
results.

**Concrete impact**: contracts checking `extcodesize(addr) > 0` after a
failed deployment see a non-zero size instead of 0, taking a different
code path and computing different gas. This produces arbitrary gas
under-counts that fail block validation with `"gas used by execution: X,
in header: Y"`.

**Observed in production**:
- Mainnet node (r3.4, build `cd4cc8e1`) stuck at block 24741565 with
`-61,560` gas diff
- Hoodi node previously exhibited similar pattern at block 2486302

### The fix

Add `CodeSizePath` cleanup to both branches of `codeChange.revert()`:
- `wasCommited == true`: `Delete(CodeSizePath)` alongside the existing
`Delete` calls
- `wasCommited == false`: restore `v.Val = len(ch.prevcode)` (r3.4 uses
`*VersionedWrite` pointers, not `UpdateVal`)

### Adaptation from main

Main uses `WriteSet.UpdateVal()` (added in the IBS 2-cache refactor
which is main-only). r3.4's `WriteSet` stores `*VersionedWrite`
pointers, so direct `v.Val = ...` assignment modifies the map entry in
place — consistent with all other `wasCommited == false` revert handlers
in r3.4's `journal.go`.

## Test plan
- [x] `make erigon` builds cleanly
- [x] `make lint` clean (0 issues)
- [ ] Mainnet node at block 24741565 unblocked after deploying this fix

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
github-merge-queue Bot pushed a commit that referenced this pull request Apr 6, 2026
Cherry-pick from release/3.4 to main.

Original PRs:
- #20335 — paged writer: lost amount of workers
- #20281 — pagedWriter and compressor to use same COMPRESS_WORKERS
variable
- #20262 — stageloop, execmodule: add ERIGON_IN_MEM_HISTORY env flag
- #20114 — crypto: zero-alloc, syncpool-free method to hash []byte type
- #20194 — execution/state: revert CodeSizePath in codeChange journal
entry

20 candidates checked total; 15 were already effectively on main.

---------

Co-authored-by: moskud <sudeepdino008@gmail.com>
Co-authored-by: awskii <awskii@users.noreply.github.com>
Co-authored-by: Giulio rebuffo <giulio.rebuffo@gmail.com>
Co-authored-by: lystopad <oleksandr.lystopad@erigon.tech>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
AskAlexSharov pushed a commit that referenced this pull request Apr 12, 2026
…ry (#20194)

## Summary

Backport of main commit `94a02c2bbb` to `release/3.4`, adapted for
r3.4's `*VersionedWrite` pointer map.

### The bug

`SetCode` writes three versioned entries (`CodePath`, `CodeHashPath`,
`CodeSizePath`) to `versionedWrites`, but `codeChange.revert()` only
cleaned up `CodePath` and `CodeHashPath`. The stale `CodeSizePath`
caused `GetCodeSize` to return the pre-revert value after a parent frame
reverted a child `CREATE`/`CREATE2`, making `EXTCODESIZE` report wrong
results.

**Concrete impact**: contracts checking `extcodesize(addr) > 0` after a
failed deployment see a non-zero size instead of 0, taking a different
code path and computing different gas. This produces arbitrary gas
under-counts that fail block validation with `"gas used by execution: X,
in header: Y"`.

**Observed in production**:
- Mainnet node (r3.4, build `cd4cc8e1`) stuck at block 24741565 with
`-61,560` gas diff
- Hoodi node previously exhibited similar pattern at block 2486302

### The fix

Add `CodeSizePath` cleanup to both branches of `codeChange.revert()`:
- `wasCommited == true`: `Delete(CodeSizePath)` alongside the existing
`Delete` calls
- `wasCommited == false`: restore `v.Val = len(ch.prevcode)` (r3.4 uses
`*VersionedWrite` pointers, not `UpdateVal`)

### Adaptation from main

Main uses `WriteSet.UpdateVal()` (added in the IBS 2-cache refactor
which is main-only). r3.4's `WriteSet` stores `*VersionedWrite`
pointers, so direct `v.Val = ...` assignment modifies the map entry in
place — consistent with all other `wasCommited == false` revert handlers
in r3.4's `journal.go`.

## Test plan
- [x] `make erigon` builds cleanly
- [x] `make lint` clean (0 issues)
- [ ] Mainnet node at block 24741565 unblocked after deploying this fix

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
github-merge-queue Bot pushed a commit that referenced this pull request Apr 13, 2026
Cherry-pick from `release/3.4` to `main`:

- #19677 agg: workers presets. ressplit workers
- #19919 Revert "flush: use etl.IdentityLoadFunc instead custom. part2"
- #19780 etl: zero-copy memDataProvider
- #19941 d_lru: disable for commitment
- #19942 TemporalMemBatch: re-use vals-slice when can
- #19996 etl: pool of bufwriter
- #19995 collate: replace bitmap by array
- #20002 skill creator review results
- #20033 seg: revert global limiter
- #20046 Caplin: prevent calling `glob` per file in
`BuildMissingIndices`
- #20113 seg: more usage of bufio
- #20194 execution/state: revert CodeSizePath in codeChange journal
entry
- #20431 remove `flush complete` log line
- #20440 etl: munmap temp files in Dispose to prevent disk space leak

93 commits skipped due to conflicts (branches diverged significantly).

---------

Co-authored-by: lystopad <oleksandr.lystopad@erigon.tech>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: moskud <sudeepdino008@gmail.com>
Co-authored-by: info@weblogix.biz <admin@10gbps.weblogix.it>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants