Skip to content

Conversation

@hanabi1224
Copy link
Contributor

@hanabi1224 hanabi1224 commented Oct 24, 2025

Summary of changes

Populate message receipt cache together with state output cache to avoid unnecessarily re-computing state in some RPC methods like eth_getBlockByHash and eth_getBlockByNumber

@AlexeyKrasnoperov please re-evaluate #5633 and #6149 once this is merged.

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.

Summary by CodeRabbit

Release Notes

  • Refactor
    • Improved state and receipt caching implementation
    • Added enhanced debugging support to internal components

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 24, 2025

Walkthrough

Modified the populate_cache function to introduce local variables for key, state_root, and receipt_root, and added conditional logic to fetch and cache receipts from the blockstore into the receipt_event_cache_handler. Added Debug derive to the StateEvents struct.

Changes

Cohort / File(s) Summary
Cache and Debug Updates
src/state_manager/mod.rs
Refactored populate_cache to use local variables (key, state_root, receipt_root) for improved variable reuse; added conditional receipt fetching from blockstore and insertion into receipt_event_cache_handler when available; added Debug derive to StateEvents struct alongside existing derives

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • elmattic

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "fix(rpc): improve performance of eth_GetBlockByNumber" is clearly related to the pull request's main objective, which is to populate the message receipt cache together with the state output cache to improve RPC performance for methods like eth_GetBlockByNumber. The code changes in state_manager/mod.rs implement receipt caching logic that directly supports this performance improvement goal. The title is specific, mentioning both the performance aspect and the targeted RPC method, making it clear and understandable without vague terminology. The title accurately represents the intended outcome of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hm/improve-perf-for-eth_GetBlockByNumber

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

@hanabi1224 hanabi1224 marked this pull request as ready for review October 24, 2025 13:52
@hanabi1224 hanabi1224 requested a review from a team as a code owner October 24, 2025 13:52
@hanabi1224 hanabi1224 requested review from LesnyRumcajs and sudo-shashank and removed request for a team October 24, 2025 13:52
if let Ok(receipts) = Receipt::get_receipts(self.blockstore(), receipt_root)
&& !receipts.is_empty()
{
self.receipt_event_cache_handler
Copy link
Contributor Author

@hanabi1224 hanabi1224 Oct 24, 2025

Choose a reason for hiding this comment

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

Previously, without receipt_event_cache_handler cache being populated, the below function always calls compute_tipset_state to get message receipts

    #[instrument(skip(self))]
    pub async fn tipset_message_receipts(
        self: &Arc<Self>,
        tipset: &Arc<Tipset>,
    ) -> anyhow::Result<Vec<Receipt>> {
        let key = tipset.key();
        let ts = tipset.clone();
        let this = Arc::clone(self);
        self.receipt_event_cache_handler
            .get_receipt_or_else(
                key,
                Box::new(move || {
                    Box::pin(async move {
                        let StateOutput { receipt_root, .. } = this
                            .compute_tipset_state(ts, NO_CALLBACK, VMTrace::NotTraced)
                            .await?;
                        trace!("Completed tipset state calculation");
                        Receipt::get_receipts(this.blockstore(), receipt_root)
                    })
                }),
            )
            .await
    }

Copy link
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/state_manager/mod.rs (1)

218-233: Good refactor that aligns with PR objectives.

The extraction of local variables improves readability, and the receipt caching logic correctly mirrors the pattern in update_cache_with_state_output (lines 469-474). This should successfully avoid recomputation in RPC methods as intended.

One minor observation: consider adding a trace-level log when Receipt::get_receipts fails, similar to other cache operations, to aid debugging without impacting performance.

For example:

-            if let Ok(receipts) = Receipt::get_receipts(self.blockstore(), receipt_root)
-                && !receipts.is_empty()
-            {
-                self.receipt_event_cache_handler
-                    .insert_receipt(key, receipts);
-            }
+            match Receipt::get_receipts(self.blockstore(), receipt_root) {
+                Ok(receipts) if !receipts.is_empty() => {
+                    self.receipt_event_cache_handler
+                        .insert_receipt(key, receipts);
+                }
+                Err(e) => {
+                    trace!("Failed to load receipts for cache population at epoch {}: {}", parent.epoch(), e);
+                }
+                _ => {} // Empty receipts, skip caching
+            }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a86d740 and ab992bf.

📒 Files selected for processing (1)
  • src/state_manager/mod.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/state_manager/mod.rs (3)
src/blocks/tipset.rs (2)
  • key (336-339)
  • key (530-533)
src/shim/executor.rs (2)
  • key (305-310)
  • get_receipts (206-225)
src/state_manager/cache.rs (3)
  • get_receipts (154-154)
  • get_receipts (210-212)
  • get_receipts (267-269)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: tests-release
  • GitHub Check: tests
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: All lint checks
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build Ubuntu
🔇 Additional comments (1)
src/state_manager/mod.rs (1)

98-98: LGTM! Helpful debugging enhancement.

Adding the Debug derive to the public StateEvents struct improves observability without breaking compatibility.

@LesnyRumcajs
Copy link
Member

@hanabi1224 did you check performance gain on your side?

@hanabi1224
Copy link
Contributor Author

hanabi1224 commented Oct 27, 2025

@hanabi1224 did you check performance gain on your side?

@LesnyRumcajs Just checked calibnet@3141000 with the curl command in #5633
Forest: Total: 0.001504s
Lotus: Total: 0.007101s

@LesnyRumcajs
Copy link
Member

@hanabi1224 did you check performance gain on your side?

@LesnyRumcajs Just checked calibnet@3141000 with the curl command in #5633 Forest: Total: 0.001504s Lotus: Total: 0.007101s

I mean, the performance gain between current main and this PR.

@hanabi1224
Copy link
Contributor Author

I mean, the performance gain between current main and this PR.

@LesnyRumcajs Just checked mainnet@5441650

main: Total: 0.443274s
pr: Total: 0.006406s

Copy link
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.

LGTM! Might be worth a changelog entry.

@LesnyRumcajs LesnyRumcajs added this pull request to the merge queue Oct 27, 2025
hanabi1224 added a commit that referenced this pull request Oct 27, 2025
@hanabi1224
Copy link
Contributor Author

LGTM! Might be worth a changelog entry.

@LesnyRumcajs changelog updated in #6192 given this has been in the merge queue.

@coderabbitai coderabbitai bot mentioned this pull request Oct 27, 2025
4 tasks
Merged via the queue into main with commit 5b60a60 Oct 27, 2025
45 checks passed
@LesnyRumcajs LesnyRumcajs deleted the hm/improve-perf-for-eth_GetBlockByNumber branch October 27, 2025 10:12
github-merge-queue bot pushed a commit that referenced this pull request Oct 28, 2025
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