Skip to content

fix: spawn_blocking for fvm calls#7184

Merged
hanabi1224 merged 2 commits into
mainfrom
hm/spawn-blocking-for-fvm-calls
Jun 19, 2026
Merged

fix: spawn_blocking for fvm calls#7184
hanabi1224 merged 2 commits into
mainfrom
hm/spawn-blocking-for-fvm-calls

Conversation

@hanabi1224

@hanabi1224 hanabi1224 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary of changes

Fvm calls are expensive and could exhaust tokio worker threads. Call them with spawn_blocking instead. Also update fn namings to end with _blocking when they're sync ones and invoking fvm.

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

  • Performance

    • Optimized chain state computation and validation for improved efficiency through better async/blocking task separation.
    • Enhanced gas estimation logic to better handle prior message tracking during calculations.
  • Bug Fixes

    • Improved error handling for task execution failures during chain operations.

@hanabi1224 hanabi1224 added the RPC requires calibnet RPC checks to run on CI label Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Renames all synchronous state-computation functions to _blocking variants (apply_block_messages_blocking, validate_tipsets_blocking, compute_state_blocking, prepare_parent_state_blocking), splits get_lookback_tipset_for_round into a blocking helper and a new async spawn_blocking wrapper, moves call_with_gas VM simulation into spawn_blocking, adds From<JoinError> for Error, and updates all call sites to use owned/Arc arguments.

Changes

Blocking/async execution path refactor

Layer / File(s) Summary
state_computation blocking renames and re-exports
src/state_manager/mod.rs, src/state_manager/state_computation.rs
Renames apply_block_messages, validate_tipsets, compute_state, and prepare_parent_state to their _blocking counterparts throughout state_computation.rs, wires them consistently, and updates mod.rs re-exports to the new names.
JoinError conversion and lookback tipset async wrapper
src/chain/store/errors.rs, src/chain/store/chain_store.rs
Adds From<JoinError> for Error mapping to Error::Other. Renames the synchronous lookback computation to get_lookback_tipset_for_round_blocking (using apply_block_messages_blocking), and introduces a new pub async fn get_lookback_tipset_for_round that offloads to tokio::task::spawn_blocking.
call_with_gas and execution_trace moved to spawn_blocking
src/state_manager/message_simulation.rs, src/state_manager/execution.rs
Refactors call_with_gas to take owned ChainMessage and Arc<Vec<ChainMessage>>, moving VM simulation into spawn_blocking. Renames validate_range/validate_tipsets to _blocking variants. Refactors execution_trace cache fill to an execution_trace_inner async wrapper backed by spawn_blocking.
Lookback tipset call site updates
src/interpreter/externs.rs, src/chain_sync/tipset_syncer.rs, src/fil_cns/validation.rs, src/rpc/methods/miner.rs, src/state_manager/mining.rs
Updates every get_lookback_tipset_for_round call site to pass shallow-cloned owned values and .await the result. Updates ForestExterns to call the _blocking variant directly.
Gas estimation prior_messages Arc call site updates
src/rpc/methods/gas.rs, src/rpc/methods/eth.rs
Changes estimate_call_with_gas return type to Arc<Vec<ChainMessage>>. Updates gas_search and can_succeed in eth.rs to accept and propagate Arc<Vec<ChainMessage>> via shallow_clone() at each call_with_gas invocation.
Daemon and tooling call site updates
src/daemon/mod.rs, src/tool/offline_server/server.rs, src/tool/subcommands/api_cmd/api_compare_tests.rs, src/tool/subcommands/snapshot_cmd.rs, src/tool/subcommands/archive_cmd.rs
Updates daemon to call validate_range_blocking; updates offline server, api comparison tests, snapshot commands, and archive commands to call validate_tipsets_blocking and apply_block_messages_blocking.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Async Caller
  participant AsyncFn as get_lookback_tipset_for_round
  participant BlockingFn as get_lookback_tipset_for_round_blocking
  participant ApplyMsgs as apply_block_messages_blocking

  Caller->>AsyncFn: chain_index, chain_config, tipset, round (owned)
  AsyncFn->>BlockingFn: tokio::spawn_blocking (references to owned inputs)
  BlockingFn->>ApplyMsgs: compute state_root for null-blocks branch
  ApplyMsgs-->>BlockingFn: ExecutedTipset { state_root }
  BlockingFn-->>AsyncFn: (Tipset, Cid)
  AsyncFn-->>Caller: Result<(Tipset, Cid), Error>
Loading
sequenceDiagram
  participant RPCHandler as RPC Handler
  participant CWG as call_with_gas (async)
  participant SpawnBlocking as tokio::spawn_blocking
  participant FVM as stacker::grow / FVM

  RPCHandler->>CWG: message (owned), prior_messages Arc, tipset, vm_flush
  CWG->>SpawnBlocking: move message + prior_messages + sm.shallow_clone()
  SpawnBlocking->>FVM: apply prior_messages, adjust nonce, apply message
  FVM-->>SpawnBlocking: ApplyRet + optional state root
  SpawnBlocking-->>CWG: InvocResult + duration + state root
  CWG-->>RPCHandler: Result<(InvocResult, ApplyRet, Duration, Option<Cid>)>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ChainSafe/forest#6255: Modifies ChainStore::get_lookback_tipset_for_round call contract and related call sites, directly overlapping with this PR's introduction of the blocking helper and async wrapper for the same function.
  • ChainSafe/forest#6864: Refactors state_manager/mod.rs to re-export apply_block_messages/validate_tipsets from state_computation, which this PR directly extends by renaming those exports to their _blocking variants.
  • ChainSafe/forest#6889: Refactors ChainStore::get_lookback_tipset_for_round and its call sites in chain_store.rs, changing ChainIndex ownership conventions that this PR further extends with the new blocking/async split.

Suggested reviewers

  • LesnyRumcajs
  • akaladarshi
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: wrapping FVM calls with spawn_blocking to prevent thread exhaustion, which is the core objective of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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/spawn-blocking-for-fvm-calls
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch hm/spawn-blocking-for-fvm-calls

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

@hanabi1224 hanabi1224 marked this pull request as ready for review June 17, 2026 14:17
@hanabi1224 hanabi1224 requested a review from a team as a code owner June 17, 2026 14:17
@hanabi1224 hanabi1224 requested review from LesnyRumcajs, akaladarshi and sudo-shashank and removed request for a team June 17, 2026 14:17
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 59.18367% with 60 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.36%. Comparing base (ae501fb) to head (dbee77a).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/rpc/methods/eth.rs 0.00% 13 Missing ⚠️
src/chain/store/chain_store.rs 57.69% 10 Missing and 1 partial ⚠️
src/state_manager/message_simulation.rs 77.27% 4 Missing and 6 partials ⚠️
src/state_manager/execution.rs 68.42% 5 Missing and 1 partial ⚠️
src/daemon/mod.rs 0.00% 4 Missing ⚠️
src/rpc/methods/miner.rs 0.00% 4 Missing ⚠️
src/chain/store/errors.rs 0.00% 3 Missing ⚠️
src/state_manager/state_computation.rs 66.66% 2 Missing and 1 partial ⚠️
src/tool/subcommands/snapshot_cmd.rs 0.00% 2 Missing ⚠️
src/interpreter/externs.rs 0.00% 1 Missing ⚠️
... and 3 more
Additional details and impacted files
Files with missing lines Coverage Δ
src/chain_sync/tipset_syncer.rs 63.27% <100.00%> (+0.24%) ⬆️
src/fil_cns/validation.rs 78.89% <100.00%> (+0.13%) ⬆️
src/rpc/methods/gas.rs 86.11% <100.00%> (+0.03%) ⬆️
src/state_manager/mod.rs 65.15% <ø> (ø)
src/interpreter/externs.rs 39.81% <0.00%> (ø)
src/state_manager/mining.rs 71.18% <80.00%> (+0.24%) ⬆️
src/tool/offline_server/server.rs 27.23% <0.00%> (ø)
src/tool/subcommands/archive_cmd.rs 29.66% <0.00%> (ø)
src/tool/subcommands/snapshot_cmd.rs 0.00% <0.00%> (ø)
src/chain/store/errors.rs 12.50% <0.00%> (-1.79%) ⬇️
... and 7 more

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ae501fb...dbee77a. 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 coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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/state_manager/state_computation.rs (1)

191-191: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Stale doc comment reference.

The doc comment references apply_block_messages, but this function was renamed to apply_block_messages_blocking.

📝 Suggested fix
-    /// For details, see the documentation for [`apply_block_messages`].
+    /// For details, see the documentation for [`apply_block_messages_blocking`].
🤖 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` at line 191, The doc comment at the
line with "For details, see the documentation for [`apply_block_messages`]"
references a function that no longer exists with that name. Update the function
name reference in the doc comment from `apply_block_messages` to
`apply_block_messages_blocking` to match the actual current function name.
🧹 Nitpick comments (3)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)

2638-2642: ⚡ Quick win

Offload chain revalidation work from the async executor.

This async function directly runs validate_tipsets_blocking, which can monopolize Tokio workers for large ranges. Prefer a tokio::task::spawn_blocking wrapper for this compute-heavy section.

As per coding guidelines, use tokio::task::spawn_blocking for CPU-intensive work such as VM execution and cryptography.

🤖 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` around lines 2638 - 2642,
The validate_tipsets_blocking call is a CPU-intensive blocking operation that is
currently running directly in an async context, which can monopolize Tokio
worker threads. Wrap the state_manager.validate_tipsets_blocking call with
tokio::task::spawn_blocking to offload this blocking work to a dedicated thread
pool, allowing the async executor to continue processing other tasks. This
ensures the blocking validation work does not starve the Tokio runtime.

Source: Coding guidelines

src/tool/subcommands/archive_cmd.rs (1)

856-865: ⚡ Quick win

Move tipset execution to spawn_blocking in show_tipset_diff.

apply_block_messages_blocking performs synchronous VM computation; calling it inline in this async flow can block Tokio workers during large snapshot diffs. Running it through tokio::task::spawn_blocking would avoid executor contention.

As per coding guidelines, use tokio::task::spawn_blocking for CPU-intensive work such as VM execution and cryptography.

🤖 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/archive_cmd.rs` around lines 856 - 865, The call to
apply_block_messages_blocking is a CPU-intensive synchronous operation being
executed directly in an async context, which can block Tokio runtime workers.
Wrap this call in tokio::task::spawn_blocking by creating a closure that
contains the entire apply_block_messages_blocking invocation with all its
parameters, then await the result to ensure the VM execution runs on a dedicated
blocking thread pool instead of blocking the async executor.

Source: Coding guidelines

src/tool/offline_server/server.rs (1)

194-198: ⚡ Quick win

Run tipset validation in spawn_blocking on this async path.

validate_tipsets_blocking is VM-heavy synchronous work, so invoking it directly here can pin a Tokio worker during startup. Wrapping this section in tokio::task::spawn_blocking would keep async scheduling responsive.

As per coding guidelines, use tokio::task::spawn_blocking for CPU-intensive work such as VM execution and cryptography.

🤖 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/offline_server/server.rs` around lines 194 - 198, The call to
state_manager.validate_tipsets_blocking with the chain and take_while iterator
is CPU-intensive synchronous work that can block the Tokio worker thread during
this async path. Wrap the entire state_manager.validate_tipsets_blocking call
and its argument chain (head_ts.chain(rpc_state.db()).take_while(...)) inside
tokio::task::spawn_blocking to offload this VM-heavy work to a dedicated thread
pool, preventing the async runtime from being pinned and keeping async
scheduling responsive.

Source: Coding guidelines

🤖 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/state_manager/state_computation.rs`:
- Line 191: The doc comment at the line with "For details, see the documentation
for [`apply_block_messages`]" references a function that no longer exists with
that name. Update the function name reference in the doc comment from
`apply_block_messages` to `apply_block_messages_blocking` to match the actual
current function name.

---

Nitpick comments:
In `@src/tool/offline_server/server.rs`:
- Around line 194-198: The call to state_manager.validate_tipsets_blocking with
the chain and take_while iterator is CPU-intensive synchronous work that can
block the Tokio worker thread during this async path. Wrap the entire
state_manager.validate_tipsets_blocking call and its argument chain
(head_ts.chain(rpc_state.db()).take_while(...)) inside
tokio::task::spawn_blocking to offload this VM-heavy work to a dedicated thread
pool, preventing the async runtime from being pinned and keeping async
scheduling responsive.

In `@src/tool/subcommands/api_cmd/api_compare_tests.rs`:
- Around line 2638-2642: The validate_tipsets_blocking call is a CPU-intensive
blocking operation that is currently running directly in an async context, which
can monopolize Tokio worker threads. Wrap the
state_manager.validate_tipsets_blocking call with tokio::task::spawn_blocking to
offload this blocking work to a dedicated thread pool, allowing the async
executor to continue processing other tasks. This ensures the blocking
validation work does not starve the Tokio runtime.

In `@src/tool/subcommands/archive_cmd.rs`:
- Around line 856-865: The call to apply_block_messages_blocking is a
CPU-intensive synchronous operation being executed directly in an async context,
which can block Tokio runtime workers. Wrap this call in
tokio::task::spawn_blocking by creating a closure that contains the entire
apply_block_messages_blocking invocation with all its parameters, then await the
result to ensure the VM execution runs on a dedicated blocking thread pool
instead of blocking the async executor.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 29279800-5370-47df-830d-35b7052387ed

📥 Commits

Reviewing files that changed from the base of the PR and between ae501fb and dbee77a.

📒 Files selected for processing (18)
  • src/chain/store/chain_store.rs
  • src/chain/store/errors.rs
  • src/chain_sync/tipset_syncer.rs
  • src/daemon/mod.rs
  • src/fil_cns/validation.rs
  • src/interpreter/externs.rs
  • src/rpc/methods/eth.rs
  • src/rpc/methods/gas.rs
  • src/rpc/methods/miner.rs
  • src/state_manager/execution.rs
  • src/state_manager/message_simulation.rs
  • src/state_manager/mining.rs
  • src/state_manager/mod.rs
  • src/state_manager/state_computation.rs
  • src/tool/offline_server/server.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs
  • src/tool/subcommands/archive_cmd.rs
  • src/tool/subcommands/snapshot_cmd.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • filecoin-project/lotus (manual)

@hanabi1224 hanabi1224 added this pull request to the merge queue Jun 19, 2026
Merged via the queue into main with commit ead4de9 Jun 19, 2026
55 of 56 checks passed
@hanabi1224 hanabi1224 deleted the hm/spawn-blocking-for-fvm-calls branch June 19, 2026 09:16
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