Skip to content

Impl state fork handler in state manager call_raw#7061

Merged
sudo-shashank merged 22 commits into
mainfrom
shashank/fix-call-raw
May 26, 2026
Merged

Impl state fork handler in state manager call_raw#7061
sudo-shashank merged 22 commits into
mainfrom
shashank/fix-call-raw

Conversation

@sudo-shashank
Copy link
Copy Markdown
Contributor

@sudo-shashank sudo-shashank commented May 15, 2026

Summary of changes

Changes introduced in this pull request:

  • Impl state fork handler and expensive fork check.

Reference issue to close (if applicable)

Closes #6446
Closes #5965

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

  • Bug Fixes

    • RPC/state calls now detect expensive state-migration windows and either refuse with a clear new error or transparently retry against an earlier state to avoid unpredictable failures.
    • Gas estimation returns clearer failure messages when execution is refused due to migrations.
  • New Features

    • Lotus-compatible automatic retry for state calls across expensive-fork boundaries.
    • Explicit refusal error when a call targets an epoch with an expensive migration.
  • Tests

    • Added snapshot tests covering expensive-fork error scenarios.
  • Chores

    • Migration registry populated with placeholder entries; migration tooling now errors when a requested migration is unimplemented.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Walkthrough

Detects expensive state‑migration epochs, refuses explicit RPC calls that would trigger them (Error::ExpensiveFork), runs required migrations before VM execution in StateManager::call_raw, adds Lotus‑compatible retry logic for StateCall, and adds snapshot tests targeting expensive‑fork epochs.

Changes

Expensive fork handling across state simulation and RPC

Layer / File(s) Summary
State migration registry with expensive fork markers
src/state_migration/mod.rs
Return per-height Option<RunMigration> entries, add early heights as None, and error when attempting to run an unimplemented migration; adjust bundle validation to only require bundles for implemented migrations.
Error variant for expensive fork refusal
src/state_manager/errors.rs
Add Error::ExpensiveFork variant with fixed thiserror message to represent refusal of explicit calls that would trigger expensive migrations.
Network infrastructure for expensive fork detection
src/networks/mod.rs
Add ChainConfig::has_expensive_fork_between(parent, height) which checks for any registered migration epoch in [parent, height); includes a unit test around Height::Shark.
Message simulation refactor with migration and tipset resolution
src/state_manager/message_simulation.rs
Refactor StateManager::call_raw to accept optional state_cid/tipset, resolve an effective tipset (validate provided tipset or walk back from heaviest to avoid expensive-fork boundary), derive state root via run_state_migrations, compute chain randomness from the resolved tipset, update prior-message lookup, and simplify public call/call_on_state helpers.
ETH RPC guards for expensive fork rejection
src/rpc/methods/eth.rs
apply_message checks for expensive forks between parent and target epoch and returns Error::ExpensiveFork early; eth_estimate_gas error formatting updated to use err.message().
StateCall retry loop for expensive forks
src/rpc/methods/state.rs
StateCall::run retries on Error::ExpensiveFork by loading the parent tipset and retrying with a shallow-cloned tipset until a non-ExpensiveFork result; parent load errors wrapped with context.
Test fixtures and integration for expensive fork scenarios
src/tool/subcommands/api_cmd/api_compare_tests.rs
Add eth_expensive_fork_error_tests snapshot tests pinned to the latest expensive-fork epoch for Calibnet and integrate into snapshot_tests; minor store cloning adjustment in create_tests.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant StateManager
  participant ChainConfig
  participant StateMigrations
  participant VM
  Client->>StateManager: Filecoin.StateCall / eth.apply_message (state_cid?, tipset?)
  StateManager->>ChainConfig: has_expensive_fork_between(parent.epoch(), target_epoch)
  alt expensive fork detected
    ChainConfig-->>StateManager: true
    StateManager-->>Client: Error::ExpensiveFork
  else safe
    StateManager->>StateMigrations: run_state_migrations(initial_state_cid)
    StateMigrations-->>StateManager: migrated_state_cid
    StateManager->>VM: execute with migrated_state_cid and chain_rand
    VM-->>Client: execution result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.17% 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 'Impl state fork handler in state manager call_raw' accurately describes the main change—refactoring StateManager::call_raw to handle state forks with fork logic and expensive-fork detection.
Linked Issues check ✅ Passed The PR fully addresses both linked issues: #6446 (applying fork logic in call_raw) and #5965 (expensive fork detection with ErrExpensiveFork) through comprehensive changes across state management and RPC layers.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objectives: state fork handling, expensive fork detection, and supporting infrastructure. No extraneous modifications detected.

✏️ 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 shashank/fix-call-raw
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch shashank/fix-call-raw

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

@sudo-shashank sudo-shashank changed the title Use state fork handler in state manager call_raw Use prepare_parent_state in state manager call_raw May 15, 2026
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/message_simulation.rs`:
- Around line 42-44: The call to exec.prepare_parent_state(genesis_timestamp,
VMTrace::NotTraced, &mut no_cb)? lacks any error context; change it to use
anyhow::Context so failures include call-site info (e.g., use
exec.prepare_parent_state(...).context(format!("failed to prepare parent state
for genesis_timestamp={}", genesis_timestamp))?), ensuring the returned
(state_cid, _, _) bind remains the same and still handles the Result from
prepare_parent_state with context attached.
🪄 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: 418976d3-f7ec-4592-a04e-233e6206d71f

📥 Commits

Reviewing files that changed from the base of the PR and between c89d3e3 and ad5e956.

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

Comment thread src/state_manager/message_simulation.rs Outdated
@sudo-shashank sudo-shashank changed the title Use prepare_parent_state in state manager call_raw Impl state fork handler in state manager call_raw May 18, 2026
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: 3

🤖 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/networks/mod.rs`:
- Around line 542-550: The has_expensive_fork_between function incorrectly
includes the parent epoch in its search window causing a migration at parent to
make the next tipset appear to require migration; update the lower bound check
so it excludes parent by using info.epoch > parent (instead of info.epoch >=
parent) when scanning self.height_infos.values() for info.expensive, i.e. change
the predicate in has_expensive_fork_between to info.expensive && info.epoch >
parent && info.epoch < height so parent-side migrations are not double-counted.

In `@src/state_manager/errors.rs`:
- Around line 15-17: The error message for the ExpensiveFork variant is not
self-contained because it mentions "at epoch" but the variant carries no epoch;
fix by either (A) adding an epoch field to the variant (e.g., change
ExpensiveFork to ExpensiveFork { epoch: u64 } or similar type and update the
#[error(...)] to include the epoch placeholder like #[error("refusing explicit
call due to state fork at epoch {epoch}")] and then update all places that
construct ExpensiveFork to pass the epoch, or (B) remove the dangling suffix by
changing the #[error(...)] text to a self-contained message such as
#[error("refusing explicit call due to state fork")]; touch the ExpensiveFork
variant and its usages accordingly to keep types/constructors consistent.

In `@src/state_manager/message_simulation.rs`:
- Around line 30-56: The code currently performs the expensive-fork check
(chain_config.has_expensive_fork_between) and runs migration prep even when the
caller supplied a state (state_cid is Some), which can reject or re-mutate a
caller-provided post-fork state; in call_on_state, guard the expensive-fork
rejection and run_state_migrations() so they only execute when
state_cid.is_none() (i.e., when we derive state from a tipset), by moving the
chain_config.has_expensive_fork_between checks and the run_state_migrations()
calls inside the state_cid.is_none() branch; apply the same change for the other
occurrence around the code referenced at 58-79 and keep references to
chain_index().load_required_tipset, has_expensive_fork_between,
run_state_migrations, and call_on_state to locate the spots to change.
🪄 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: 8082d114-8347-4a81-b4bb-2fa3b521a995

📥 Commits

Reviewing files that changed from the base of the PR and between b391f54 and c664609.

📒 Files selected for processing (3)
  • src/networks/mod.rs
  • src/state_manager/errors.rs
  • src/state_manager/message_simulation.rs

Comment thread src/networks/mod.rs Outdated
Comment thread src/state_manager/errors.rs
Comment thread src/state_manager/message_simulation.rs
@sudo-shashank sudo-shashank force-pushed the shashank/fix-call-raw branch from c2ff120 to 23e2128 Compare May 19, 2026 07:24
@sudo-shashank sudo-shashank added the RPC requires calibnet RPC checks to run on CI label May 19, 2026
@sudo-shashank sudo-shashank marked this pull request as ready for review May 20, 2026 06:04
@sudo-shashank sudo-shashank requested a review from a team as a code owner May 20, 2026 06:04
@sudo-shashank sudo-shashank requested review from akaladarshi and hanabi1224 and removed request for a team May 20, 2026 06:04
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

🧹 Nitpick comments (1)
src/networks/mod.rs (1)

731-737: ⚡ Quick win

Pin the inclusive lower-bound case in this regression test.

This currently locks in the exclusive upper bound only. Adding an assertion like assert!(cfg.has_expensive_fork_between(shark, shark + 1)); would protect the intended [parent, height) behavior from regressing again.

Based on learnings: ChainConfig::has_expensive_fork_between(parent, height) intentionally uses an inclusive lower bound matching Lotus’s [parent, height) semantics.

🤖 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/networks/mod.rs` around lines 731 - 737, Update the test
has_expensive_fork_between_matches_upgrade_epochs to pin the inclusive
lower-bound case by adding an assertion that the fork exists at the lower bound:
insert assert!(cfg.has_expensive_fork_between(shark, shark + 1)); inside the
test (the test uses ChainConfig::mainnet(), variable shark =
cfg.epoch(Height::Shark)) so update that function to include this new assertion
that calls ChainConfig::has_expensive_fork_between with (shark, shark + 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/tool/subcommands/api_cmd/api_compare_tests.rs`:
- Around line 2450-2456: The code computing expensive_fork_epoch uses
.max().expect(...) which can panic; update this in the helper that returns
anyhow::Result to return an error instead of aborting: replace the
.max().expect(...) pattern on
chain_config.height_infos.values().filter(...).map(...).max() with
.ok_or_else(|| anyhow::anyhow!("calibnet must define at least one expensive
fork"))? so the function returns Err(...) when no epoch is found, propagating
the anyhow::Result; keep references to expensive_fork_epoch, chain_config,
heaviest_tipset, and height_infos so the change is localized.

---

Nitpick comments:
In `@src/networks/mod.rs`:
- Around line 731-737: Update the test
has_expensive_fork_between_matches_upgrade_epochs to pin the inclusive
lower-bound case by adding an assertion that the fork exists at the lower bound:
insert assert!(cfg.has_expensive_fork_between(shark, shark + 1)); inside the
test (the test uses ChainConfig::mainnet(), variable shark =
cfg.epoch(Height::Shark)) so update that function to include this new assertion
that calls ChainConfig::has_expensive_fork_between with (shark, shark + 1).
🪄 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: 4821a8ea-e361-4550-aaaf-255a36880eac

📥 Commits

Reviewing files that changed from the base of the PR and between b391f54 and 6621857.

📒 Files selected for processing (6)
  • src/networks/mod.rs
  • src/rpc/methods/eth.rs
  • src/rpc/methods/state.rs
  • src/state_manager/errors.rs
  • src/state_manager/message_simulation.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs

Comment thread src/tool/subcommands/api_cmd/api_compare_tests.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 67.85714% with 45 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.39%. Comparing base (934b8ad) to head (368f83a).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/state_manager/message_simulation.rs 59.52% 15 Missing and 2 partials ⚠️
src/state_migration/mod.rs 75.00% 14 Missing and 1 partial ⚠️
src/rpc/methods/state.rs 28.57% 4 Missing and 1 partial ⚠️
src/rpc/methods/eth.rs 60.00% 3 Missing and 1 partial ⚠️
src/tool/subcommands/shed_cmd/migration.rs 0.00% 3 Missing ⚠️
src/networks/mod.rs 94.44% 1 Missing ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/state_manager/errors.rs 60.00% <ø> (+20.00%) ⬆️
src/networks/mod.rs 89.26% <94.44%> (+0.21%) ⬆️
src/tool/subcommands/shed_cmd/migration.rs 0.00% <0.00%> (ø)
src/rpc/methods/eth.rs 65.40% <60.00%> (+<0.01%) ⬆️
src/rpc/methods/state.rs 44.43% <28.57%> (-0.07%) ⬇️
src/state_migration/mod.rs 82.40% <75.00%> (+1.08%) ⬆️
src/state_manager/message_simulation.rs 77.84% <59.52%> (-5.50%) ⬇️

... and 13 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 52b5584...368f83a. 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.

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.

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

2456-2456: ⚡ Quick win

Enhance error message with diagnostic context.

The change from .expect() to .ok_or_else() correctly addresses the past review feedback. However, the error message could be more diagnostic by including the heaviest tipset epoch, as suggested in the original review comment.

📋 Suggested improvement for diagnostics
-        .ok_or_else(|| anyhow::anyhow!("calibnet must define at least one expensive fork"))?;
+        .ok_or_else(|| {
+            anyhow::anyhow!(
+                "no expensive fork epoch <= heaviest tipset epoch {} for calibnet snapshot",
+                heaviest_tipset.epoch()
+            )
+        })?;
🤖 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/api_compare_tests.rs` at line 2456, The error
created by .ok_or_else currently uses a generic message "calibnet must define at
least one expensive fork"; update the closure to include diagnostic context by
appending the heaviest tipset epoch (e.g., heaviest_tipset_epoch or
heaviest_tipset.epoch()) so the error shows the epoch value when no expensive
fork is found; locate the call site where .ok_or_else(|| anyhow::anyhow!(...))
is used and interpolate the existing heaviest tipset variable into the anyhow
message to produce a clearer, actionable error.
🤖 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/api_compare_tests.rs`:
- Line 2456: The error created by .ok_or_else currently uses a generic message
"calibnet must define at least one expensive fork"; update the closure to
include diagnostic context by appending the heaviest tipset epoch (e.g.,
heaviest_tipset_epoch or heaviest_tipset.epoch()) so the error shows the epoch
value when no expensive fork is found; locate the call site where .ok_or_else(||
anyhow::anyhow!(...)) is used and interpolate the existing heaviest tipset
variable into the anyhow message to produce a clearer, actionable error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3494d18e-f244-4632-b2a5-c3084f080270

📥 Commits

Reviewing files that changed from the base of the PR and between 6621857 and 548b665.

📒 Files selected for processing (1)
  • src/tool/subcommands/api_cmd/api_compare_tests.rs

Comment thread src/networks/mod.rs Outdated
@sudo-shashank sudo-shashank requested a review from hanabi1224 May 20, 2026 19:41
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.

Caution

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

⚠️ Outside diff range comments (1)
src/rpc/methods/eth.rs (1)

1792-1804: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve ExpensiveFork as a typed RPC error in gas estimation.

Line 1803 wraps non-revert failures into a generic message, which also hides crate::state_manager::Error::ExpensiveFork instead of returning it directly.

Suggested fix
             if let Err(e) = apply_message(ctx, Some(tipset), msg).await {
                 // if the error is an execution reverted, return it directly
                 if e.downcast_ref::<EthErrors>()
                     .is_some_and(|eth_err| matches!(eth_err, EthErrors::ExecutionReverted { .. }))
                 {
                     return Err(e.into());
                 }
+                // Preserve expensive-fork refusal as a typed error.
+                if e.downcast_ref::<crate::state_manager::Error>()
+                    .is_some_and(|sm_err| matches!(sm_err, crate::state_manager::Error::ExpensiveFork))
+                {
+                    return Err(e.into());
+                }

                 err = e.into();
             }
🤖 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/rpc/methods/eth.rs` around lines 1792 - 1804, The current gas estimation
error handling wraps non-revert failures into a generic anyhow error which hides
crate::state_manager::Error::ExpensiveFork; update the branch after
apply_message so that if the error downcasts to
state_manager::Error::ExpensiveFork (or otherwise identifies ExpensiveFork) you
return that error directly (preserving its typed RPC representation) instead of
converting it into the generic "failed to estimate gas" anyhow; keep the
existing special-case for EthErrors::ExecutionReverted but add a second
special-case that checks for ExpensiveFork and returns it unchanged, only
falling back to Err(anyhow::anyhow!("failed to estimate gas: {}",
err.message()).into()) for other errors.
🧹 Nitpick comments (1)
src/networks/mod.rs (1)

705-710: ⚡ Quick win

Add calibnet fix-epoch coverage to expensive-fork tests.

This test only asserts mainnet Shark. Please add assertions around WatermelonFix/WatermelonFix2/DragonFix/TockFix on calibnet to lock in the key behavior this PR is enabling.

🤖 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/networks/mod.rs` around lines 705 - 710, The test
has_expensive_fork_between_matches_upgrade_epochs only checks mainnet Shark; add
equivalent assertions for calibnet by creating cfg = ChainConfig::calibnet() and
for each epoch Height::WatermelonFix, Height::WatermelonFix2, Height::DragonFix,
and Height::TockFix assert that cfg.has_expensive_fork_between(epoch - 1, epoch
+ 1) is true and cfg.has_expensive_fork_between(epoch - 1, epoch) is false
(mirroring the Shark checks) so the test locks in the new calibnet fix-epoch
behavior.
🤖 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.

Outside diff comments:
In `@src/rpc/methods/eth.rs`:
- Around line 1792-1804: The current gas estimation error handling wraps
non-revert failures into a generic anyhow error which hides
crate::state_manager::Error::ExpensiveFork; update the branch after
apply_message so that if the error downcasts to
state_manager::Error::ExpensiveFork (or otherwise identifies ExpensiveFork) you
return that error directly (preserving its typed RPC representation) instead of
converting it into the generic "failed to estimate gas" anyhow; keep the
existing special-case for EthErrors::ExecutionReverted but add a second
special-case that checks for ExpensiveFork and returns it unchanged, only
falling back to Err(anyhow::anyhow!("failed to estimate gas: {}",
err.message()).into()) for other errors.

---

Nitpick comments:
In `@src/networks/mod.rs`:
- Around line 705-710: The test
has_expensive_fork_between_matches_upgrade_epochs only checks mainnet Shark; add
equivalent assertions for calibnet by creating cfg = ChainConfig::calibnet() and
for each epoch Height::WatermelonFix, Height::WatermelonFix2, Height::DragonFix,
and Height::TockFix assert that cfg.has_expensive_fork_between(epoch - 1, epoch
+ 1) is true and cfg.has_expensive_fork_between(epoch - 1, epoch) is false
(mirroring the Shark checks) so the test locks in the new calibnet fix-epoch
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 12798021-fb2c-4181-8ff1-490f592749a6

📥 Commits

Reviewing files that changed from the base of the PR and between 548b665 and 0957fdf.

📒 Files selected for processing (8)
  • src/networks/butterflynet/mod.rs
  • src/networks/calibnet/mod.rs
  • src/networks/devnet/mod.rs
  • src/networks/mainnet/mod.rs
  • src/networks/mod.rs
  • src/rpc/methods/eth.rs
  • src/state_manager/message_simulation.rs
  • src/state_migration/mod.rs

Comment thread src/networks/mod.rs Outdated
Comment thread src/networks/mod.rs Outdated
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 left a comment

Choose a reason for hiding this comment

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

I think we could avoid having 2 sources of expensive fork heights

Comment thread src/rpc/methods/eth.rs
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/tool/subcommands/api_cmd/api_compare_tests.rs`:
- Around line 2451-2455: The code picks the latest migration epoch overall
instead of the latest expensive-fork epoch; update the chain of iterators from
crate::state_migration::get_all_migrations::<crate::db::DbImpl>(&NetworkChain::Calibnet)
so it first filters migrations to only those that represent an expensive fork
(inspect the migration value from the tuple returned by get_all_migrations and
check its expensive/fork-type flag or method, e.g. migration.is_expensive() or
migration.fork_type == Expensive) before calling filter_map(...).max() so that
expensive_fork_epoch reflects the latest expensive migration only.
🪄 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: c6698981-0c39-4593-adcf-50a0a1e2eabd

📥 Commits

Reviewing files that changed from the base of the PR and between 0957fdf and b9634ef.

📒 Files selected for processing (4)
  • src/networks/mod.rs
  • src/rpc/methods/eth.rs
  • src/state_migration/mod.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs

Comment thread src/tool/subcommands/api_cmd/api_compare_tests.rs Outdated
@sudo-shashank sudo-shashank requested a review from hanabi1224 May 25, 2026 16:16
Comment thread src/state_migration/mod.rs Outdated
Comment thread src/state_migration/mod.rs Outdated
Comment thread src/state_migration/mod.rs Outdated
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 left a comment

Choose a reason for hiding this comment

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

I would define a migration function that returns unimplemented state migration at height {height} error for these migrations. None would just bypass the migration and result in state mismatch without clear error message.

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

🧹 Nitpick comments (1)
src/networks/mod.rs (1)

698-703: ⚡ Quick win

Add a calibnet *Fix epoch assertion in the expensive-fork test.

Current test only validates Height::Shark on mainnet. A small calibnet assertion (e.g., WatermelonFix boundary) would lock in the regression that this PR is addressing.

Suggested test extension
 #[test]
 fn has_expensive_fork_between_matches_upgrade_epochs() {
     let cfg = ChainConfig::mainnet();
     let shark = cfg.epoch(Height::Shark);
     assert!(cfg.has_expensive_fork_between(shark - 1, shark + 1));
     assert!(!cfg.has_expensive_fork_between(shark - 1, shark));
+
+    let calib = ChainConfig::calibnet();
+    let wf = calib.epoch(Height::WatermelonFix);
+    assert!(calib.has_expensive_fork_between(wf - 1, wf + 1));
 }

Based on learnings: calibnet *Fix migration heights previously caused expensive-fork detection drift and should be guarded by tests.

🤖 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/networks/mod.rs` around lines 698 - 703, Extend the test function
has_expensive_fork_between_matches_upgrade_epochs to also cover calibnet: create
a calibnet config with ChainConfig::calibnet(), get the WatermelonFix epoch via
cfg.epoch(Height::WatermelonFix), then add assertions mirroring the mainnet ones
using cfg.has_expensive_fork_between(watermelon - 1, watermelon + 1) (should be
true) and cfg.has_expensive_fork_between(watermelon - 1, watermelon) (should be
false) so the calibnet *Fix migration boundary is locked in.
🤖 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_migration/mod.rs`:
- Around line 137-145: The loop over mappings currently skips when
chain_config.height_infos lacks an entry for a migration height; change it to
fail fast: in the for (height, migrate) in &mappings loop, after checking the
migrate pointer (the unimplemented_migration::<DB> as RunMigration<DB> check),
explicitly check if chain_config.height_infos.get(height) is None and
panic/assert with a clear message that the migration height is missing (include
the height), otherwise continue to assert that info.bundle.is_some() for the
Some(info) case; reference the mappings iteration, unimplemented_migration::<DB>
as RunMigration<DB>, and chain_config.height_infos.get(height) when locating the
change.

---

Nitpick comments:
In `@src/networks/mod.rs`:
- Around line 698-703: Extend the test function
has_expensive_fork_between_matches_upgrade_epochs to also cover calibnet: create
a calibnet config with ChainConfig::calibnet(), get the WatermelonFix epoch via
cfg.epoch(Height::WatermelonFix), then add assertions mirroring the mainnet ones
using cfg.has_expensive_fork_between(watermelon - 1, watermelon + 1) (should be
true) and cfg.has_expensive_fork_between(watermelon - 1, watermelon) (should be
false) so the calibnet *Fix migration boundary is locked in.
🪄 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: 904795d1-66e0-4149-85e2-77952b7cd5cc

📥 Commits

Reviewing files that changed from the base of the PR and between 9b947e9 and 30bb907.

📒 Files selected for processing (3)
  • src/networks/mod.rs
  • src/state_migration/mod.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs

Comment thread src/state_migration/mod.rs Outdated
@sudo-shashank sudo-shashank force-pushed the shashank/fix-call-raw branch from 30bb907 to 3a08213 Compare May 26, 2026 04:45
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_migration/mod.rs`:
- Around line 123-125: The BUNDLE_CHECKED flag is being set before validation
finishes, which can suppress future checks on error; move the
BUNDLE_CHECKED.store(true, atomic::Ordering::Relaxed) call to after the
validation loop over mappings completes successfully (i.e., only set
BUNDLE_CHECKED when the for height in mappings loop has finished without
returning/propagating an error), keeping the same atomic ordering and leaving
the validation logic in the same function/block.
🪄 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: 69b6e1e0-6f52-4154-ae4b-7bc9c2e92f31

📥 Commits

Reviewing files that changed from the base of the PR and between 30bb907 and 368f83a.

📒 Files selected for processing (4)
  • src/networks/mod.rs
  • src/state_migration/mod.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs
  • src/tool/subcommands/shed_cmd/migration.rs

Comment thread src/state_migration/mod.rs
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.

🧹 Nitpick comments (1)
src/networks/mod.rs (1)

698-703: ⚡ Quick win

Add explicit calibnet *Fix expensive-fork coverage.

This test only validates Height::Shark on mainnet. Please add at least one calibnet *Fix epoch assertion (e.g., WatermelonFix) to lock the regression surface you just fixed.

Suggested test addition
 #[test]
 fn has_expensive_fork_between_matches_upgrade_epochs() {
     let cfg = ChainConfig::mainnet();
     let shark = cfg.epoch(Height::Shark);
     assert!(cfg.has_expensive_fork_between(shark - 1, shark + 1));
     assert!(!cfg.has_expensive_fork_between(shark - 1, shark));
 }
+
+#[test]
+fn has_expensive_fork_between_matches_calibnet_fix_epochs() {
+    let cfg = ChainConfig::calibnet();
+    let watermelon_fix = cfg.epoch(Height::WatermelonFix);
+    assert!(cfg.has_expensive_fork_between(watermelon_fix - 1, watermelon_fix + 1));
+    assert!(!cfg.has_expensive_fork_between(watermelon_fix - 1, watermelon_fix));
+}
🤖 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/networks/mod.rs` around lines 698 - 703, The test
has_expensive_fork_between_matches_upgrade_epochs only checks mainnet Shark; add
a parallel assertion for calibnet to cover the Fix-era you fixed (e.g., use let
cfg = ChainConfig::calibnet(); let fix_epoch = cfg.epoch(Height::WatermelonFix);
then assert!(cfg.has_expensive_fork_between(fix_epoch - 1, fix_epoch + 1)); and
assert!(!cfg.has_expensive_fork_between(fix_epoch - 1, fix_epoch)); this mirrors
the existing Shark checks and locks the calibnet *Fix regression surface.
🤖 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/networks/mod.rs`:
- Around line 698-703: The test
has_expensive_fork_between_matches_upgrade_epochs only checks mainnet Shark; add
a parallel assertion for calibnet to cover the Fix-era you fixed (e.g., use let
cfg = ChainConfig::calibnet(); let fix_epoch = cfg.epoch(Height::WatermelonFix);
then assert!(cfg.has_expensive_fork_between(fix_epoch - 1, fix_epoch + 1)); and
assert!(!cfg.has_expensive_fork_between(fix_epoch - 1, fix_epoch)); this mirrors
the existing Shark checks and locks the calibnet *Fix regression surface.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 82b0be70-dd10-400c-8535-5f5fb14e9e09

📥 Commits

Reviewing files that changed from the base of the PR and between 30bb907 and 368f83a.

📒 Files selected for processing (4)
  • src/networks/mod.rs
  • src/state_migration/mod.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs
  • src/tool/subcommands/shed_cmd/migration.rs

@sudo-shashank sudo-shashank requested a review from hanabi1224 May 26, 2026 05:37
@sudo-shashank sudo-shashank added this pull request to the merge queue May 26, 2026
Merged via the queue into main with commit df636b3 May 26, 2026
33 checks passed
@sudo-shashank sudo-shashank deleted the shashank/fix-call-raw branch May 26, 2026 06:20
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.

Impl state fork handler in state manager call_raw Investigate expensive fork handling in Forest

2 participants