evm pool memory zeroing#12145
Conversation
|
Claude finished @svlachakis's task in 6m 6s —— View job Review: EVM pooled memory zeroing (#12145)
SummaryThis replaces eager buffer zeroing (rent-clean + clear-on-return) with a lazy defined-frontier model: I traced the frontier invariant across all read / write / grow / dispose / trace paths and it holds. No Critical / High / Medium findings. Highlights of the correctness check:
Findings (all Low)
Process noteThe PR description is an unfilled template (no summary, no change type checked, testing/docs sections blank). Please fill it in — the type-of-change checkboxes drive auto-labeling, and given this touches consensus-critical EVM memory zeroing a short rationale + perf note would help reviewers.
Verdict: Algorithm is correct; only Low-severity polish items. Mergeable once findings are acknowledged (or addressed) and the description is completed. |
| [ThreadStatic] private static byte[]?[]? _cleanArrays; | ||
| [ThreadStatic] private static int _cleanArrayCount; |
There was a problem hiding this comment.
Low (naming): After this change these caches hold dirty (un-zeroed) buffers — RentBuffer no longer clears and ReturnDirty no longer wipes. The _cleanArrays / _cleanArrayCount names (and "clean cache" framing) are now misleading and will trip up future readers who rely on the name to reason about zeroing. Consider renaming to _pooledArrays / _pooledArrayCount to match the new dirty-pool semantics.
| @@ -465,7 +481,6 @@ private static void ReturnClean(byte[] array, int dirtyLength) | |||
| byte[]?[] cache = _cleanArrays ??= new byte[CleanCacheSlots][]; | |||
| if (_cleanArrayCount < CleanCacheSlots) | |||
| { | |||
| Array.Clear(array, 0, dirtyLength); | |||
| cache[_cleanArrayCount++] = array; | |||
| } | |||
| } | |||
There was a problem hiding this comment.
Low (info-hygiene): Large buffers (> MaxCachedArrayLength = 64 KiB) routed through ReturnLarge end up in SafeArrayPool<byte>.Shared (= the process-wide ArrayPool<byte>.Shared, also used by Trie TrackingCappedArrayPool, Discv5 packet codec, and the BLS precompile) for the 64 KiB–1 MiB band. They're now returned un-zeroed, so leftover EVM memory contents (potentially sensitive contract data) flow into the shared pool.
This is within the ArrayPool contract (renters must never assume zeroed buffers — and Shared is already process-global, so it was never a real zeroing guarantee), and I confirmed the other Shared consumers all fill before reading, so there's no correctness regression. Flagging only because it removes a defense-in-depth wipe; worth a one-line acknowledgement that the hygiene loss is intentional.
EVM Opcode Benchmark DiffAggregated runs: base=3, pr=3 No significant regressions or improvements detected. |
EXPB Benchmark ComparisonRun: View workflow run superblocksNo metrics were produced for realblocksNo metrics were produced for |
Cover the defined-frontier invariants introduced by dirty pooling: word padding zeroed on load after MSTORE8, MCOPY zeroing an undefined source region above the destination, and grow preserving the defined prefix while zeroing the freshly exposed tail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…m-pool-memory-zeroing # Conflicts: # src/Nethermind/Nethermind.Evm.Test/EvmPooledMemoryTests.cs
Fixes Closes Resolves #
Please choose one of the keywords above to refer to the issue this PR solves followed by the issue number (e.g. Fixes #000). If no issue number, remove the line. Also, remove everything marked optional that is not applicable. Remove this note after reading.
Changes
Types of changes
What types of changes does your code introduce?
Testing
Requires testing
If yes, did you write tests?
Notes on testing
Optional. Remove if not applicable.
Documentation
Requires documentation update
If yes, link the PR to the docs update or the issue with the details labeled
docs. Remove if not applicable.Requires explanation in Release Notes
If yes, fill in the details here. Remove if not applicable.
Remarks
Optional. Remove if not applicable.