Skip to content

fix: incorporate EC finality calculator into tipset lookup-by-height cache#7112

Merged
hanabi1224 merged 9 commits into
mainfrom
hm/warmup-tipset-height-lookup
May 27, 2026
Merged

fix: incorporate EC finality calculator into tipset lookup-by-height cache#7112
hanabi1224 merged 9 commits into
mainfrom
hm/warmup-tipset-height-lookup

Conversation

@hanabi1224
Copy link
Copy Markdown
Contributor

@hanabi1224 hanabi1224 commented May 27, 2026

Summary of changes

Previously, we don't cache the lookup for epoch (head-900, head] (Only when F3 is down), with EC finality calculator, the finaltiy is ~100 (actually 20 @6052192) instead of 900 on mainnet

Changes introduced in this pull request:

Benchmark of querying tipset @ (head epoch - 500).

# command
oha -n 1000 -c 1 -m POST http://localhost:2345/rpc/v1 -H 'Content-Type: application/json' -D eth_getBlockByNumber_call.json

# payload
{
        "method": "eth_getBlockByNumber",
        "params": ["0x5c571f", false],
        "id": 1,
        "jsonrpc": "2.0"
}

# main
  Success rate: 100.00%30s    40s    50s    60s    70s     ││0.0124  0.0166  0.0207  0.0248  0.0290  0.0331  0.0372    │
  Total:────────19659.0131 ms──────────────────────────────┘└──────────────────────────────────────────────────────────┘
  Slowest:      150.5417 ms
  Fastest:      12.4223 ms
  Average:      19.6465 ms
  Requests/sec: 50.8673

  Total data:   2.82 MiB
  Size/request: 2.88 KiB
  Size/sec:     146.74 KiB

Response time histogram:
   12.422 ms [1]   |
   26.234 ms [812] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
   40.046 ms [184] |■■■■■■■
   53.858 ms [1]   |
   67.670 ms [0]   |
   81.482 ms [1]   |
   95.294 ms [0]   |
  109.106 ms [0]   |
  122.918 ms [0]   |
  136.730 ms [0]   |
  150.542 ms [1]   |

Response time distribution:
  10.00% in 16.0410 ms
  25.00% in 16.3323 ms
  50.00% in 16.6541 ms
  75.00% in 20.0071 ms
  90.00% in 28.3209 ms
  95.00% in 34.7470 ms
  99.00% in 36.3333 ms
  99.90% in 150.5417 ms
  99.99% in 150.5417 ms
  
# PR  
  Success rate: 100.00%
  Total:        658.4161 ms
  Slowest:      20.1629 ms
  Fastest:      0.2080 ms
  Average:      0.6541 ms
  Requests/sec: 1518.7965

  Total data:   2.82 MiB
  Size/request: 2.88 KiB
  Size/sec:     4.28 MiB

Response time histogram:
   0.208 ms [1]   |
   2.204 ms [966] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
   4.199 ms [28]  |
   6.194 ms [4]   |
   8.190 ms [0]   |
  10.185 ms [0]   |
  12.181 ms [0]   |
  14.176 ms [0]   |
  16.172 ms [0]   |
  18.167 ms [0]   |
  20.163 ms [1]   |

Response time distribution:
  10.00% in 0.2769 ms
  25.00% in 0.3087 ms
  50.00% in 0.4054 ms
  75.00% in 0.6308 ms
  90.00% in 1.3820 ms
  95.00% in 1.9961 ms
  99.00% in 3.0389 ms
  99.90% in 20.1629 ms
  99.99% in 20.1629 ms

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

  • Refactor

    • Finality logic now derives a dynamic EC-based finalized epoch and uses a unified predicate that stays consistent as the chain head advances.
    • The EC-derived finalized epoch is exposed so other components can reference the computed finality point.
  • Performance

    • Added async tipset lookups and an extra cache warmup step to prefetch finalized tipsets, improving RPC responsiveness and cache hit rates; lookup failures are logged.

Review Change Stack

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

coderabbitai Bot commented May 27, 2026

Important

Review skipped

This PR was authored by the user configured for CodeRabbit reviews. CodeRabbit does not review PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 37de5d2a-b55d-4f92-8657-313e88b57b90

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Refactors EC finality epoch computation into a public RPC helper; caches the EC-derived finalized epoch in ChainStore and uses it (maxed with F3 epoch) for finality checks; adds async tipset lookup and warms daemon RPC caches using the cached EC epoch.

Changes

EC finality epoch caching and integration

Layer / File(s) Summary
RPC EC finality calculation refactoring
src/rpc/methods/chain.rs
ChainGetTipSetFinalityStatus gains get_ec_finality_epoch and internal helpers (depth→epoch mapping, cached threshold-depth); chain-sampling and finalized-tipset resolution are refactored to compute an EC finality epoch and resolve the tipset via ChainIndex.
ChainStore EC finalized-epoch cache and integration
src/chain/store/chain_store.rs
Adds ec_calculator_finalized_epoch: Arc<AtomicI64>, initializes it with get_ec_finality_epoch in ChainStore::new, integrates it into with_is_tipset_finalized using max(F3_finalized_epoch, ec_calculator_finalized_epoch), propagates it via ShallowClone, recomputes it in set_heaviest_tipset, and exposes pub fn ec_calculator_finalized_epoch(&self) -> ChainEpoch.
ChainIndex async lookup & daemon warmup
src/chain/store/index.rs, src/daemon/mod.rs
Adds ChainIndex::tipset_by_height_async (spawn_blocking wrapper) and updates tipset_by_height fast-paths; daemon cache prefill now loads the tipset at the cached EC finalized epoch via the async lookup and logs a warning if lookup fails.

Sequence Diagram(s)

sequenceDiagram
  participant Daemon
  participant ChainStore
  participant ChainGetTipSetFinalityStatus
  participant ChainIndex
  Daemon->>ChainStore: on new validated tipset -> read ec_calculator_finalized_epoch
  ChainStore->>ChainGetTipSetFinalityStatus: (during init/set_heaviest) get_ec_finality_epoch(chain_index, chain_config, head)
  ChainGetTipSetFinalityStatus->>ChainIndex: tipset_by_height(ec_finality_epoch, head, ResolveNullTipset::TakeOlder)
  ChainIndex-->>ChainGetTipSetFinalityStatus: finalized tipset
  ChainGetTipSetFinalityStatus-->>ChainStore: ec_finality_epoch
  Daemon->>ChainIndex: tipset_by_height_async(ec_finality_epoch, head, ResolveNullTipset::TakeOlder)
  ChainIndex-->>Daemon: finalized tipset or error
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

  • ChainSafe/forest#6880: Modifies ChainIndex::tipset_by_height behavior; related to the index fast-path changes and async wrapper added here.
  • ChainSafe/forest#6811: Refactors ChainGetTipSetFinalityStatus and its helpers; closely related to the new helper extraction.
  • ChainSafe/forest#6897: Also refactors EC-based finality resolution and overlaps with ChainGetTipSetFinalityStatus changes.

Suggested reviewers

  • sudo-shashank
  • 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 main change: incorporating EC finality calculator into tipset lookup-by-height caching, which is the core objective of the 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.


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

@hanabi1224 hanabi1224 marked this pull request as ready for review May 27, 2026 08:58
@hanabi1224 hanabi1224 requested a review from a team as a code owner May 27, 2026 08:58
@hanabi1224 hanabi1224 requested review from LesnyRumcajs and sudo-shashank and removed request for a team May 27, 2026 08:58
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/rpc/methods/chain.rs (1)

1171-1191: 💤 Low value

Consider using ChainEpoch as the return type for consistency.

The method returns i64, but conceptually represents a ChainEpoch. While they're the same underlying type, using ChainEpoch would be more self-documenting and consistent with how the result is used in ChainStore (stored in Arc<RwLock<ChainEpoch>>).

Suggested change
     pub fn get_ec_finality_epoch(
         chain_index: &ChainIndex,
         chain_config: &ChainConfig,
         head: &Tipset,
-    ) -> i64 {
+    ) -> ChainEpoch {
         let depth =
             Self::get_ec_finality_threshold_depth_with_cache(chain_index, chain_config, head);
         Self::get_ec_finality_epoch_by_depth(chain_config, head, depth)
     }

     fn get_ec_finality_epoch_by_depth(
         chain_config: &ChainConfig,
         head: &Tipset,
         depth: i64,
-    ) -> i64 {
+    ) -> ChainEpoch {
🤖 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/chain.rs` around lines 1171 - 1191, Change the return type of
get_ec_finality_epoch and get_ec_finality_epoch_by_depth from i64 to ChainEpoch
to reflect the semantic type; update their signatures (pub fn
get_ec_finality_epoch(... ) -> ChainEpoch and fn
get_ec_finality_epoch_by_depth(... ) -> ChainEpoch) and convert the
arithmetic/clamping logic to produce a ChainEpoch (e.g., perform epoch
subtraction and clamp to zero using ChainEpoch-compatible operations or
conversions), and update any callers or stored places (e.g., where the result is
placed into Arc<RwLock<ChainEpoch>>) to accept ChainEpoch instead of i64; touch
the symbols get_ec_finality_epoch, get_ec_finality_epoch_by_depth, ChainIndex,
ChainConfig, Tipset and chain_config.policy.chain_finality as needed to keep
types consistent.
🤖 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/rpc/methods/chain.rs`:
- Around line 1171-1191: Change the return type of get_ec_finality_epoch and
get_ec_finality_epoch_by_depth from i64 to ChainEpoch to reflect the semantic
type; update their signatures (pub fn get_ec_finality_epoch(... ) -> ChainEpoch
and fn get_ec_finality_epoch_by_depth(... ) -> ChainEpoch) and convert the
arithmetic/clamping logic to produce a ChainEpoch (e.g., perform epoch
subtraction and clamp to zero using ChainEpoch-compatible operations or
conversions), and update any callers or stored places (e.g., where the result is
placed into Arc<RwLock<ChainEpoch>>) to accept ChainEpoch instead of i64; touch
the symbols get_ec_finality_epoch, get_ec_finality_epoch_by_depth, ChainIndex,
ChainConfig, Tipset and chain_config.policy.chain_finality as needed to keep
types consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 73c9f109-5c91-49a7-a50f-ed4e300a65a7

📥 Commits

Reviewing files that changed from the base of the PR and between ee2a7e6 and 2da49d6.

📒 Files selected for processing (2)
  • src/chain/store/chain_store.rs
  • src/rpc/methods/chain.rs

@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

❌ Patch coverage is 71.07438% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.40%. Comparing base (ee2a7e6) to head (7bd0392).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/daemon/mod.rs 0.00% 18 Missing ⚠️
src/chain/store/index.rs 25.00% 11 Missing and 1 partial ⚠️
src/chain/store/chain_store.rs 84.00% 4 Missing ⚠️
src/rpc/methods/chain.rs 98.38% 1 Missing ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/rpc/methods/chain.rs 57.22% <98.38%> (+1.56%) ⬆️
src/chain/store/chain_store.rs 69.01% <84.00%> (+0.14%) ⬆️
src/chain/store/index.rs 85.38% <25.00%> (-3.45%) ⬇️
src/daemon/mod.rs 25.00% <0.00%> (-0.69%) ⬇️

... and 8 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 ee2a7e6...7bd0392. 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.

@hanabi1224 hanabi1224 force-pushed the hm/warmup-tipset-height-lookup branch from 4060d7c to 8eef8d9 Compare May 27, 2026 09:55
Comment thread src/chain/store/chain_store.rs Outdated
Comment thread src/rpc/methods/chain.rs Outdated
@hanabi1224 hanabi1224 enabled auto-merge May 27, 2026 11:46
@hanabi1224 hanabi1224 added this pull request to the merge queue May 27, 2026
Merged via the queue into main with commit 8086404 May 27, 2026
33 checks passed
@hanabi1224 hanabi1224 deleted the hm/warmup-tipset-height-lookup branch May 27, 2026 12:07
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