Skip to content

Conversation

@akaladarshi
Copy link
Collaborator

@akaladarshi akaladarshi commented Oct 7, 2025

Summary of changes

Changes introduced in this pull request:

  • Adds implementation for the ChainGetFinalizedTipset API
  • Adds snapshot tests for the ChainGetFinalizedTipset API:
    • The test only verifies basic check since it is dependent on F3 and the latest tipset.

Reference issue to close (if applicable)

Closes #6113

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

  • New Features
    • Finalized tipset retrieval now prefers the latest network certificate when available, with automatic fallback to consensus finality for reliability.
  • Bug Fixes
    • Replaced a stubbed finalized-tipset response with real resolution logic and improved error handling and logging to avoid incorrect or empty results.
  • Tests
    • Added an API test for finalized tipset retrieval and expanded snapshot data to cover the new behavior.

@akaladarshi akaladarshi requested a review from a team as a code owner October 7, 2025 09:30
@akaladarshi akaladarshi requested review from elmattic and removed request for a team October 7, 2025 09:30
@akaladarshi akaladarshi added the RPC requires calibnet RPC checks to run on CI label Oct 7, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Walkthrough

Replaces the stubbed ChainGetFinalizedTipset handler with real finality resolution: computes EC finality epoch from the heaviest tipset, attempts F3 finality via a new helper, and falls back to EC finality on errors. Expands RPC handler contexts to require Send + Sync + 'static, exposes get_rpc_http_client publicly, and adds an API compare test plus snapshot.

Changes

Cohort / File(s) Summary
RPC: Chain finality resolution
src/rpc/methods/chain.rs
Replaces stub with real logic: compute EC finality epoch from heaviest tipset; try F3 finality via new get_f3_finality_tipset helper; if F3 missing/invalid/logged error, fall back to loading EC finality tipset from chain index. Updates handle signature to accept Ctx<impl Blockstore + Send + Sync + 'static> and adds debug/warn logging.
RPC: F3 client and handler context
src/rpc/methods/f3.rs
Widens F3GetLatestCertificate::handle context to Send + Sync + 'static. Makes get_rpc_http_client public (pub fn get_rpc_http_client() -> anyhow::Result<...>).
Tests: API compare
src/tool/subcommands/api_cmd/api_compare_tests.rs
Adds ChainGetFinalizedTipset request to chain_tests_with_tipset via RpcTest::basic(ChainGetFinalizedTipset::request(())?).
Test data: snapshots
src/tool/subcommands/api_cmd/test_snapshots.txt
Adds new snapshot entry: filecoin_chaingetfinalizedtipset_1759828121342574.rpcsnap.json.zst.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant RPC as ChainGetFinalizedTipset
  participant Ctx as Node/Ctx
  participant CI as ChainIndex
  participant F3 as F3 service

  Client->>RPC: ChainGetFinalizedTipset()
  RPC->>Ctx: fetch heaviest tipset
  RPC->>CI: compute EC finality epoch
  RPC->>F3: request latest certificate + head
  alt F3 certificate present and head >= EC epoch
    RPC->>CI: load tipset at F3 head
    CI-->>RPC: F3 finalized tipset
    RPC-->>Client: return F3 finalized tipset
  else F3 missing/invalid/error
    Note over RPC: warn and fallback to EC finality
    RPC->>CI: load tipset at EC finality epoch
    CI-->>RPC: EC finalized tipset
    RPC-->>Client: return EC finalized tipset
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sudo-shashank
  • AlexeyKrasnoperov

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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately summarizes the primary change by indicating the addition of the ChainGetFinalizedTipset API, matching both the implementation details in the code and the intent of the pull request. It is clear, concise, and follows conventional commit style without extraneous information.
Linked Issues Check ✅ Passed The pull request implements the ChainGetFinalizedTipset handler with multi-path finality logic, integrates necessary Blockstore context support, and adds corresponding tests and snapshots, fully satisfying the coding requirements of issue #6113 to support the new v1 API endpoint.
Out of Scope Changes Check ✅ Passed All code modifications, including expanded context bounds in f3 handlers and making the HTTP client helper public, directly support the new ChainGetFinalizedTipset implementation or its testing infrastructure, and there are no unrelated or extraneous changes.
✨ 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 akaladarshi/add-chain-get-finalized-tipset-api

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

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/rpc/methods/chain.rs (1)

151-165: Include error context in the fallback warning.

When we drop into the EC path we lose the original failure reason, which makes field debugging harder. Please log the error (e.g. with tracing::warn!(error = %err, ...)) before falling back.

-        match get_f3_finality_tipset(&ctx, ec_finality_epoch).await {
+        match get_f3_finality_tipset(&ctx, ec_finality_epoch).await {
             Ok(f3_tipset) => {
                 tracing::debug!("Using F3 finalized tipset at epoch {}", f3_tipset.epoch());
                 Ok((*f3_tipset).clone())
             }
-            Err(_) => {
-                // fallback to ec finality
-                tracing::warn!("F3 finalization unavailable, falling back to EC finality");
+            Err(error) => {
+                // fallback to ec finality
+                tracing::warn!(
+                    error = %error,
+                    "F3 finalization unavailable, falling back to EC finality"
+                );
                 let ec_tipset = ctx.chain_index().tipset_by_height(
                     ec_finality_epoch,
                     head,
                     ResolveNullTipset::TakeOlder,
                 )?;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c046fb0 and b215a7d.

📒 Files selected for processing (4)
  • src/rpc/methods/chain.rs (1 hunks)
  • src/rpc/methods/f3.rs (2 hunks)
  • src/tool/subcommands/api_cmd/api_compare_tests.rs (1 hunks)
  • src/tool/subcommands/api_cmd/test_snapshots.txt (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/tool/subcommands/api_cmd/api_compare_tests.rs (2)
src/rpc/reflect/mod.rs (1)
  • request (250-260)
src/rpc/client.rs (1)
  • request (272-285)
src/rpc/methods/chain.rs (1)
src/blocks/tipset.rs (2)
  • epoch (306-308)
  • epoch (543-545)
src/rpc/methods/f3.rs (1)
src/rpc/methods/state.rs (16)
  • handle (109-114)
  • handle (132-138)
  • handle (151-157)
  • handle (172-178)
  • handle (196-205)
  • handle (223-231)
  • handle (248-255)
  • handle (272-282)
  • handle (298-305)
  • handle (335-465)
  • handle (484-492)
  • handle (508-538)
  • handle (555-561)
  • handle (577-597)
  • handle (615-624)
  • handle (641-663)
⏰ 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). (7)
  • GitHub Check: Build Ubuntu
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build MacOS
  • GitHub Check: All lint checks
  • GitHub Check: tests
  • GitHub Check: tests-release
  • GitHub Check: Build forest binaries on Linux AMD64

(): Self::Params,
) -> Result<Self::Ok, ServerError> {
let head = ctx.chain_store().heaviest_tipset();
let ec_finality_epoch = head.epoch() - ctx.chain_config().policy.chain_finality;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let ec_finality_epoch = head.epoch() - ctx.chain_config().policy.chain_finality;
let ec_finality_epoch = (head.epoch() - ctx.chain_config().policy.chain_finality).max(0);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

match get_f3_finality_tipset(&ctx, ec_finality_epoch).await {
Ok(f3_tipset) => {
tracing::debug!("Using F3 finalized tipset at epoch {}", f3_tipset.epoch());
Ok((*f3_tipset).clone())
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we avoid cloning here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think so f3_tipset wrapped in Arc so we will have to clone only.

.await
.map_err(|e| anyhow::anyhow!("Failed to get F3 certificate: {}", e))?;

let f3_finalized_head = f3_finalized_cert.chain_head();
Copy link
Contributor

Choose a reason for hiding this comment

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

f3_finalized_cert.chain_head() could be newer than chain head during catchup. Lotus does not seem to handle that case, should we handle it? e.g. marking finalized tipset in F3.Finalize RPC method instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

We could track this in a separate issue, for now the logic matches Lotus

@akaladarshi akaladarshi force-pushed the akaladarshi/add-chain-get-finalized-tipset-api branch from b215a7d to de68dc2 Compare October 8, 2025 13:25
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/rpc/methods/chain.rs (1)

143-167: LGTM! Well-structured finality resolution with F3 primary and EC fallback.

The implementation correctly:

  • Computes EC finality epoch with .max(0) to prevent negative values
  • Attempts F3 finality first via the new helper
  • Falls back to EC finality on errors with appropriate logging

Optional: Log the discarded error for easier debugging.

Currently, the error from get_f3_finality_tipset (line 156) is silently discarded. Consider logging it at debug level to aid troubleshooting:

         match get_f3_finality_tipset(&ctx, ec_finality_epoch).await {
             Ok(f3_tipset) => {
                 tracing::debug!("Using F3 finalized tipset at epoch {}", f3_tipset.epoch());
                 Ok((*f3_tipset).clone())
             }
-            Err(_) => {
+            Err(e) => {
                 // fallback to ec finality
-                tracing::warn!("F3 finalization unavailable, falling back to EC finality");
+                tracing::warn!("F3 finalization unavailable, falling back to EC finality: {}", e);
                 let ec_tipset = ctx.chain_index().tipset_by_height(
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b215a7d and de68dc2.

📒 Files selected for processing (4)
  • src/rpc/methods/chain.rs (1 hunks)
  • src/rpc/methods/f3.rs (2 hunks)
  • src/tool/subcommands/api_cmd/api_compare_tests.rs (1 hunks)
  • src/tool/subcommands/api_cmd/test_snapshots.txt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/tool/subcommands/api_cmd/api_compare_tests.rs
  • src/tool/subcommands/api_cmd/test_snapshots.txt
🧰 Additional context used
🧬 Code graph analysis (2)
src/rpc/methods/chain.rs (2)
src/rpc/methods/state.rs (16)
  • handle (109-114)
  • handle (132-138)
  • handle (151-157)
  • handle (172-178)
  • handle (196-205)
  • handle (223-231)
  • handle (248-255)
  • handle (272-282)
  • handle (298-305)
  • handle (335-465)
  • handle (484-492)
  • handle (508-538)
  • handle (555-561)
  • handle (577-597)
  • handle (615-624)
  • handle (641-663)
src/blocks/tipset.rs (2)
  • epoch (306-308)
  • epoch (543-545)
src/rpc/methods/f3.rs (1)
src/rpc/methods/state.rs (16)
  • handle (109-114)
  • handle (132-138)
  • handle (151-157)
  • handle (172-178)
  • handle (196-205)
  • handle (223-231)
  • handle (248-255)
  • handle (272-282)
  • handle (298-305)
  • handle (335-465)
  • handle (484-492)
  • handle (508-538)
  • handle (555-561)
  • handle (577-597)
  • handle (615-624)
  • handle (641-663)
⏰ 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). (7)
  • GitHub Check: tests
  • GitHub Check: tests-release
  • GitHub Check: All lint checks
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build MacOS
  • GitHub Check: Build Ubuntu
🔇 Additional comments (3)
src/rpc/methods/f3.rs (2)

701-704: LGTM! Signature update enables cross-thread async usage.

Adding Send + Sync + 'static bounds aligns with other async RPC handlers (e.g., StateCall, StateReplay in state.rs) and is necessary for calling this method from ChainGetFinalizedTipset in chain.rs.


954-954: LGTM! Visibility change supports cross-module usage.

Exposing get_rpc_http_client publicly enables the new ChainGetFinalizedTipset implementation in chain.rs to interact with the F3 sidecar.

src/rpc/methods/chain.rs (1)

170-197: LGTM! Robust F3 finality helper with proper validation.

The helper correctly:

  • Fetches the latest F3 certificate via F3GetLatestCertificate::handle
  • Validates that F3 finality is not behind EC finality (lines 180-186)
  • Loads the corresponding tipset from the chain index
  • Provides descriptive error messages for debugging

@akaladarshi akaladarshi enabled auto-merge October 9, 2025 06:43
@akaladarshi akaladarshi added this pull request to the merge queue Oct 9, 2025
Merged via the queue into main with commit 4661ae8 Oct 9, 2025
40 checks passed
@akaladarshi akaladarshi deleted the akaladarshi/add-chain-get-finalized-tipset-api branch October 9, 2025 07:58
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.

Implement ChainGetFinalizedTipset API

4 participants