Skip to content

Code and account domain writes should be atomic at the IBS/writer layer #22103

Description

@mh0lt

Code and account domain writes should be atomic at the IBS / writer layer

Summary

CodeDomain and AccountsDomain are written as two independent, sequentially-applied DomainPuts for the same address (e.g. execution/state/rw_v3.go writes the account record, then the code). Because they are not atomic, there is a transient window — between the account write and the code write — where the account record already carries the new codeHash but CodeDomain does not yet hold the code for that address. That window is the root cause of a class of cache-on/parallel hazards, not just the individual symptoms patched in #21386.

Why it bites

The account-codeHash → code resolution (used by the now-removed L2b GetLatest bypass, and still by the read-only GetCodeSize/GetCode fast paths) is content-addressed and shared across every address with the same code. In the window above, resolving an address's code via its (already-advanced) account codeHash returns the new code while CodeDomain still holds the old/empty value.

The durable fix

If the IBS/writer layer never put code independently of its account — wrote (account, code) as one unit, supplying the code's prevVal (which the writer knows) so DomainPut never resolves it from a possibly-advanced account — then:

  • the account-ahead-of-code window does not exist;
  • GetLatest's internal prevVal read cannot time-travel — the lost-write is structurally impossible;
  • the account→codeHash shortcut becomes safe on every path (reads, EXTCODESIZE, and prevVal), so the dedup fast path no longer needs the "read-only only" caveat and the removed L2b bypass could even return.

This generalizes @sudeepdino008's "writers pass explicit prevVal for CodeDomain puts" (option 3) into an invariant: code is a dependent of its account and is never written independently.

Scope

Writer-side change in execution/state (the rw_v3.go apply paths and the parallel-apply path), coupling the account + code DomainPuts and threading the prior code as prevVal. Not a blocker for #21386 (whose contained fixes are correct and sufficient), but the principled root fix.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions