Skip to content

fix(core): refactor account update to prevent race condition - #763

Merged
MicaiahReid merged 5 commits into
mainfrom
fix/race
Aug 24, 2026
Merged

fix(core): refactor account update to prevent race condition#763
MicaiahReid merged 5 commits into
mainfrom
fix/race

Conversation

@MicaiahReid

Copy link
Copy Markdown
Collaborator
  • Introduced AccountUpdatePolicy enum to manage authoritative vs. cache hydration updates.
  • Replaced direct calls to write_account_update with apply_account_update across multiple modules.
  • Updated logic in SurfnetSvm to handle account updates based on the new policy, ensuring local state is preserved when appropriate.
  • Enhanced tests to validate behavior of local vs. remote account updates, ensuring local writes are not overwritten by stale remote data.
  • Removed deprecated write_multiple_account_updates method and consolidated account update logic for clarity and maintainability.

Thank you @Arrowana for identifying this bug! Replaces #738

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR separates authoritative local account mutations from conditional remote or database hydration, resolving fetched accounts under the SVM write lock so concurrent local writes win.

  • Adds explicit account provenance and update policies.
  • Rechecks single and batch remote results atomically before hydration.
  • Keeps coupled mint and programdata dependencies aligned with the retained primary account.
  • Refreshes returned coupled results from current local state.
  • Migrates RPC, runloop, snapshot, and cheatcode paths to the consolidated update API.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the current code skips the entire fetched composite when its primary is already live and refreshes returned coupled dependencies from retained local state.

Important Files Changed

Filename Overview
crates/core/src/surfnet/locker.rs Resolves fetched single and batch accounts under one writer lock, preserves concurrent local writes, and reconstructs returned coupled dependencies from local state.
crates/core/src/surfnet/svm.rs Introduces authoritative and conditional-hydration policies with component-level guards that prevent stale coupled dependencies from being applied.
crates/core/src/surfnet/mod.rs Replaces the prior update flag and specialized result variants with explicit source provenance and a unified coupled-account representation.
crates/core/src/surfnet/surfnet_lite_svm.rs Tags account results according to whether they came from LiteSVM or persistent storage while retaining local-first lookup behavior.
crates/core/src/surfnet/remote.rs Marks upstream account results as remote and emits unified coupled mint or programdata results for conditional hydration.
crates/core/src/rpc/accounts_data.rs Removes redundant post-read writes because account resolution now performs safe hydration before returning.
crates/core/src/runloops/mod.rs Removes the second startup-hydration write now that remote fallback atomically resolves and applies fetched accounts.

Reviews (8): Last reviewed commit: "Merge branch 'main' into fix/race" | Re-trigger Greptile

Comment thread crates/core/src/surfnet/svm.rs
@MicaiahReid
MicaiahReid requested a review from lgalabru August 13, 2026 20:40
@cds-amal

Copy link
Copy Markdown
Contributor

Nice fix! The policy enum reads like the row selector of a decision table: given a policy and the account's local state, each cell is the action taken. Writing that table out might be worth a few minutes; it would make a compact rustdoc for AccountUpdatePolicy, and it is a good stress test of the model.

Two things to consider while filling it in:

  1. how coupled accounts (a token account's mint, a program's programdata
    account) are represented, since they arrive inside the same
    GetAccountResult as their primary but resolve against their own
    local state;
  2. whether "present only in the DB" distinguishes a row written this
    session from one inherited from a previous run.

My attempts at those cells kept needing footnotes 😞 , which usually means I'm missing an input; curious what you get.

Comment thread crates/core/src/surfnet/svm.rs Outdated
Comment thread crates/core/src/surfnet/locker.rs Outdated
- Introduced AccountUpdatePolicy enum to manage authoritative vs. cache hydration updates.
- Replaced direct calls to write_account_update with apply_account_update across multiple modules.
- Updated logic in SurfnetSvm to handle account updates based on the new policy, ensuring local state is preserved when appropriate.
- Enhanced tests to validate behavior of local vs. remote account updates, ensuring local writes are not overwritten by stale remote data.
- Removed deprecated write_multiple_account_updates method and consolidated account update logic for clarity and maintainability.
lgalabru
lgalabru previously approved these changes Aug 24, 2026
@MicaiahReid
MicaiahReid merged commit 6306f8e into main Aug 24, 2026
11 of 12 checks passed
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.

4 participants