Skip to content

fix: adjust state computation policy for Eth RPC methods#7116

Merged
hanabi1224 merged 5 commits into
mainfrom
hm/state-compute-rpc
May 29, 2026
Merged

fix: adjust state computation policy for Eth RPC methods#7116
hanabi1224 merged 5 commits into
mainfrom
hm/state-compute-rpc

Conversation

@hanabi1224
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 commented May 28, 2026

Summary of changes

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • Breaking Changes

    • Ethereum RPC methods no longer compute state by default when data is missing from the index.
  • New Features

    • Added FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS environment variable to enable state computation for Ethereum RPC methods when needed.
  • Chores

    • Improved configuration and cache warmup handling for state management.

Review Change Stack

@hanabi1224 hanabi1224 added the RPC requires calibnet RPC checks to run on CI label May 28, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Walkthrough

This PR introduces an environment-controlled policy to gate state recomputation when executed-tipset data is missing from storage. A new load_executed_tipset_for_rpc method reads FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS and passes the policy through the loading pipeline. RPC methods (block building, receipts, fee history, events) now use this policy-aware loader instead of always recomputing state. Documentation, changelog, and test config are updated accordingly.

Changes

RPC State Recomputation Policy

Layer / File(s) Summary
StateRecomputePolicy and RPC loader implementation
src/state_manager/state_computation.rs
StateRecomputePolicy enum gates recomputation with Allowed/Disallowed variants. load_executed_tipset_for_rpc reads FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS and threads policy through cached and inner loaders. Recomputation is skipped for missing state/receipts or event fallback when policy disallows it; otherwise proceeds as before.
RPC call sites updated
src/rpc/methods/eth.rs, src/rpc/methods/eth/filter/mod.rs
Block building, receipt fetching, fee history calculation, and event collection now call load_executed_tipset_for_rpc instead of load_executed_tipset, routing all RPC-initiated executed-tipset loads through the recomputation policy gate.
Daemon RPC cache warmup
src/daemon/mod.rs
Cache warmup pre-step attempts to load the executed tipset before warming RPC caches; failures are logged as warnings and do not block cache population.
Documentation and changelog
docs/docs/users/reference/env_variables.md, CHANGELOG.md, scripts/tests/api_compare/docker-compose.yml
New environment variable FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS documented (boolean, default false), breaking change entry added, and offline API test server index backfill epochs increased from 50 to 200.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • ChainSafe/forest#7118: Targets removing test-time unsafe set_var that forces the new env flag and updating snapshots to match the default policy change introduced by this PR.
  • ChainSafe/forest#7117: Directly addresses the newly introduced FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS env variable and state computation gating logic.

Possibly related PRs

  • ChainSafe/forest#7025: Both PRs modify Ethereum RPC event and receipt codepaths; this PR switches message sources to load_executed_tipset_for_rpc while #7025 scopes receipt logs by message and adjusts event filter caps in the same eth.rs and eth/filter/mod.rs areas.

Suggested reviewers

  • akaladarshi
  • LesnyRumcajs
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: adjust state computation policy for Eth RPC methods' directly reflects the main change: introducing a configurable state computation policy for Ethereum RPC methods via the FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS environment variable.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hm/state-compute-rpc
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch hm/state-compute-rpc

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Comment @coderabbitai help to get the list of available commands and usage tips.

@hanabi1224 hanabi1224 force-pushed the hm/state-compute-rpc branch from dda3dac to 42586fe Compare May 28, 2026 09:15
@hanabi1224 hanabi1224 marked this pull request as ready for review May 28, 2026 09:47
@hanabi1224 hanabi1224 requested a review from a team as a code owner May 28, 2026 09:47
@hanabi1224 hanabi1224 requested review from LesnyRumcajs and akaladarshi and removed request for a team May 28, 2026 09:47
Comment thread src/state_manager/state_computation.rs Outdated
Copy link
Copy Markdown
Member

@LesnyRumcajs LesnyRumcajs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a functional breaking change, hence a CHANGELOG entry is required.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/state_manager/state_computation.rs (1)

58-79: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Key the executed-tipset cache by recompute policy or provenance.

load_executed_tipset_for_rpc and load_executed_tipset now have different semantics, but this cache is still keyed only by ts.key(). If any non-RPC path warms the cache through the Allowed branch, a later RPC call with recomputation disabled will reuse that recomputed entry instead of returning the intended index-miss error. That makes the new policy depend on cache history rather than the configured setting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/state_manager/state_computation.rs` around lines 58 - 79, The cache in
load_executed_tipset_with_cache is keyed only by ts.key(), causing recompute
policy to leak across callers (e.g., load_executed_tipset_for_rpc vs
load_executed_tipset); fix by incorporating the recompute provenance into the
cache key or by validating stored provenance before returning: modify the cache
access sites (calls to self.cache.get(...) and
self.cache.get_or_insert_async(...)) to use a composite key that includes
ts.key() plus the Policy/ provenance (or keep a separate cache per provenance),
or have ExecutedTipset carry provenance and check it against the current policy
before returning and evict if mismatched. Ensure changes touch
load_executed_tipset_with_cache, load_executed_tipset_for_rpc, and
load_executed_tipset to preserve semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/state_manager/state_computation.rs`:
- Around line 138-144: Current code unconditionally bails when event AMT is
unreadable unless allow_state_compute is true, causing RPCs that only need
state_root/message/receipt to fail; change the loader used in StateComputation
(the branch using allow_state_compute and the anyhow::bail! with
msg_ts.epoch()/msg_ts.key()) so it does not hard-fail for missing/unreadable
event trees when recomputation is disabled—instead return a lightweight tipset
state result that includes state_root/messages/receipts but leaves events as
None or a lazy-hydration handle; add a separate function (e.g.,
load_tipset_with_events or hydrate_events_for_tipset) that performs the
expensive AMT/event decoding and is only called by callers that need events
(update callers like Block::from_filecoin_tipset_with_full_tx and
eth_fee_history to call this explicit hydrator), and ensure allow_state_compute
still gates full hydration and the original bail remains inside that
full-hydration path.

---

Outside diff comments:
In `@src/state_manager/state_computation.rs`:
- Around line 58-79: The cache in load_executed_tipset_with_cache is keyed only
by ts.key(), causing recompute policy to leak across callers (e.g.,
load_executed_tipset_for_rpc vs load_executed_tipset); fix by incorporating the
recompute provenance into the cache key or by validating stored provenance
before returning: modify the cache access sites (calls to self.cache.get(...)
and self.cache.get_or_insert_async(...)) to use a composite key that includes
ts.key() plus the Policy/ provenance (or keep a separate cache per provenance),
or have ExecutedTipset carry provenance and check it against the current policy
before returning and evict if mismatched. Ensure changes touch
load_executed_tipset_with_cache, load_executed_tipset_for_rpc, and
load_executed_tipset to preserve semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 84b3a48c-1360-4810-aca0-15c2aac7184f

📥 Commits

Reviewing files that changed from the base of the PR and between 1e2b394 and 42586fe.

📒 Files selected for processing (5)
  • docs/docs/users/reference/env_variables.md
  • scripts/tests/api_compare/docker-compose.yml
  • src/rpc/methods/eth.rs
  • src/rpc/methods/eth/filter/mod.rs
  • src/state_manager/state_computation.rs

Comment thread src/state_manager/state_computation.rs
Comment thread src/state_manager/state_computation.rs
Comment thread src/tool/subcommands/api_cmd/test_snapshot.rs Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/tool/subcommands/api_cmd/test_snapshot.rs (1)

68-68: ⚡ Quick win

Document the unsafe block and consider the LazyLock pattern.

The unsafe { std::env::set_var(...) } call lacks a comment explaining why it's acceptable. The existing INIT_RNG_SEED pattern (lines 221–225) demonstrates best practice: use a LazyLock with a comment noting that std::env::set_var is not thread-safe on Linux. Although the learning confirms that nextest runs tests in separate processes (mitigating cross-test races), the safety justification should still be documented for reviewers and maintainers.

Additionally, consider adopting the LazyLock pattern for consistency and to avoid redundant unsafe calls if this function is invoked multiple times.

📝 Suggested improvement with LazyLock pattern

Add a static initializer following the existing pattern:

+    // Ensure FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS is set once per process.
+    // `std::env::set_var` is not thread-safe on Linux, so initialize once
+    // per process — never concurrently from parallel tests.
+    static INIT_ETH_RPC_COMPUTE_STATE: LazyLock<()> = LazyLock::new(|| {
+        if std::env::var("FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS").is_err() {
+            unsafe { std::env::set_var("FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS", "1") };
+        }
+    });
+
 pub async fn run_test_from_snapshot(path: &Path) -> anyhow::Result<()> {
-    unsafe { std::env::set_var("FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS", "1") };
+    LazyLock::force(&INIT_ETH_RPC_COMPUTE_STATE);
     let mut run = false;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tool/subcommands/api_cmd/test_snapshot.rs` at line 68, Document the
unsafe std::env::set_var call and replace the ad-hoc unsafe call with a static
LazyLock initializer similar to INIT_RNG_SEED: add a static (e.g.,
INIT_FOREST_ETH_RPC using std::sync::LazyLock) whose initializer performs the
unsafe { std::env::set_var("FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS","1") }
and include a comment explaining that setting env vars is not thread-safe on
Linux and why a single-process/test-run justification still makes this safe;
then remove the direct unsafe call and ensure callers trigger the static
(consistent pattern with INIT_RNG_SEED).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/tool/subcommands/api_cmd/test_snapshot.rs`:
- Line 68: Document the unsafe std::env::set_var call and replace the ad-hoc
unsafe call with a static LazyLock initializer similar to INIT_RNG_SEED: add a
static (e.g., INIT_FOREST_ETH_RPC using std::sync::LazyLock) whose initializer
performs the unsafe {
std::env::set_var("FOREST_ETH_RPC_COMPUTE_STATE_ON_INDEX_MISS","1") } and
include a comment explaining that setting env vars is not thread-safe on Linux
and why a single-process/test-run justification still makes this safe; then
remove the direct unsafe call and ensure callers trigger the static (consistent
pattern with INIT_RNG_SEED).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fb980bcd-6620-47f4-b847-7ce191a03e1e

📥 Commits

Reviewing files that changed from the base of the PR and between 42586fe and 2750ee5.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/state_manager/state_computation.rs
  • src/tool/subcommands/api_cmd/test_snapshot.rs
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/state_manager/state_computation.rs

@hanabi1224 hanabi1224 requested a review from LesnyRumcajs May 28, 2026 10:40
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

❌ Patch coverage is 63.63636% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.41%. Comparing base (0d71649) to head (db7dbe5).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/state_manager/state_computation.rs 73.52% 7 Missing and 2 partials ⚠️
src/daemon/mod.rs 0.00% 3 Missing ⚠️
src/rpc/methods/eth.rs 50.00% 0 Missing and 3 partials ⚠️
src/rpc/methods/eth/filter/mod.rs 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/rpc/methods/eth/filter/mod.rs 89.13% <0.00%> (ø)
src/daemon/mod.rs 24.88% <0.00%> (-0.12%) ⬇️
src/rpc/methods/eth.rs 65.26% <50.00%> (+0.03%) ⬆️
src/state_manager/state_computation.rs 78.33% <73.52%> (-0.51%) ⬇️

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1e2b394...db7dbe5. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

Comment thread src/tool/subcommands/api_cmd/test_snapshot.rs Outdated
@hanabi1224 hanabi1224 requested a review from LesnyRumcajs May 28, 2026 12:40
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/state_manager/state_computation.rs`:
- Line 50: Update the tracking issue link in the inline comment that currently
points to "https://github.com/ChainSafe/forest/issues/7118" and change it to
"https://github.com/ChainSafe/forest/issues/7117" so the comment references the
correct follow-up issue for removing the test-only override (locate the comment
in state_computation.rs and replace the issue number).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 41f0f5c0-9c20-4237-928f-bc02dc9eeb5a

📥 Commits

Reviewing files that changed from the base of the PR and between c993b00 and db7dbe5.

📒 Files selected for processing (1)
  • src/state_manager/state_computation.rs

Comment thread src/state_manager/state_computation.rs
Comment thread CHANGELOG.md
@hanabi1224 hanabi1224 enabled auto-merge May 29, 2026 01:21
@hanabi1224 hanabi1224 added this pull request to the merge queue May 29, 2026
Merged via the queue into main with commit 7e31e67 May 29, 2026
66 of 67 checks passed
@hanabi1224 hanabi1224 deleted the hm/state-compute-rpc branch May 29, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

RPC requires calibnet RPC checks to run on CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants