Skip to content

Comments

fix(RPC): backport F3 finality resolution to eth V1 methods#6644

Open
hanabi1224 wants to merge 4 commits intomainfrom
hm/f3-await-v1-rpc
Open

fix(RPC): backport F3 finality resolution to eth V1 methods#6644
hanabi1224 wants to merge 4 commits intomainfrom
hm/f3-await-v1-rpc

Conversation

@hanabi1224
Copy link
Contributor

@hanabi1224 hanabi1224 commented Feb 24, 2026

Summary of changes

Changes introduced in this pull request:

Reference issue to close (if applicable)

Closes #6631

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

  • New Features

    • Backported F3 finality resolution to ETH v1 RPC methods for improved finality handling.
  • Documentation

    • Added FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION environment variable documentation to control F3 finality behavior in ETH v1 RPC endpoints.
    • Updated reference documentation with new dictionary entries.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (3)
  • src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap is excluded by !**/*.snap
  • src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap is excluded by !**/*.snap
  • src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap is excluded by !**/*.snap

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

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

This pull request backports F3 finality resolution to ETH v1 RPC methods by refactoring the type system and adding async tipset resolution logic. The changes replace legacy block-parameter types with a unified BlockNumberOrHash interface, expose new chain resolution helpers, and introduce an environment variable for controlling F3 finality behavior in v1 APIs.

Changes

Cohort / File(s) Summary
Documentation & Configuration
CHANGELOG.md, docs/dictionary.txt, docs/docs/users/reference/env_variables.md
Added changelog entry for F3 finality backport, new dictionary tokens (v0, v1, v2) for Tipset, and FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION environment variable documentation.
Chain Resolution Logic
src/rpc/methods/chain.rs
Exposed SAFE_HEIGHT_DISTANCE as public constant, added get_ec_safe_tipset helper, and changed multiple function signatures to return concrete Tipset instead of Option to eliminate None-handling branches.
Eth RPC Type System Refactoring
src/rpc/methods/eth.rs
Replaced ExtBlockNumberOrHash/ExtPredefined with new BlockNumberOrHash/Predefined types; added async Predefined resolution methods (resolve_predefined_tipset, resolve_predefined_tipset_v1/v2); updated all RPC method handlers to use BlockNumberOrHash with new async resolution methods supporting multiple API versions.
Eth RPC Type Definitions
src/rpc/methods/eth/types.rs
Updated BlockNumberOrPredefined enum to store Predefined instead of ExtPredefined; adjusted From mapping logic to target BlockNumberOrHash.
Removed Constants
src/eth/mod.rs
Removed public SAFE_EPOCH_DELAY constant and its documentation; value migrated to chain-specific constants.
Test Updates
src/tool/subcommands/api_cmd/api_compare_tests.rs, src/tool/subcommands/api_cmd/test_snapshot.rs, src/tool/subcommands/api_cmd/test_snapshots.txt
Updated test code to use new BlockNumberOrHash/Predefined types instead of legacy types; changed assertions to use pretty_assertions; regenerated RPC snapshots with updated address variants and finality tags (finalized, latest, safe).

Sequence Diagram

sequenceDiagram
    participant Client as ETH RPC Client
    participant Handler as RPC Method Handler
    participant Resolver as BlockNumberOrHash
    participant PredefinedResolve as Predefined Resolver
    participant ChainStore as Chain Store
    
    Client->>Handler: eth_getBalance(address, blockParam, ...)
    Handler->>Resolver: BlockNumberOrHash::from(blockParam)
    
    alt blockParam is Predefined Tag
        Resolver->>PredefinedResolve: resolve_predefined_tipset_v1(ctx)
        PredefinedResolve->>ChainStore: Get latest/finalized/safe tipset
        alt Tag is finalized
            PredefinedResolve->>ChainStore: Resolve via F3 finality<br/>(if enabled)
        end
        ChainStore-->>PredefinedResolve: Return Tipset
        PredefinedResolve-->>Resolver: Tipset
    else blockParam is Block Number/Hash
        Resolver->>ChainStore: Lookup block by number/hash
        ChainStore-->>Resolver: Tipset
    end
    
    Resolver-->>Handler: Tipset
    Handler->>Handler: Process request with resolved tipset
    Handler-->>Client: RPC Response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • akaladarshi
  • sudo-shashank
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive While most changes align with F3 backporting, the removal of SAFE_EPOCH_DELAY from src/eth/mod.rs and introduction of SAFE_EPOCH_DELAY_FOR_TESTING appears tangential to the core objective. Clarify whether SAFE_EPOCH_DELAY removal and test constant changes are necessary dependencies or should be separated into a distinct PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: backporting F3 finality resolution to eth V1 RPC methods, which aligns with the primary objective.
Linked Issues check ✅ Passed The PR implements support for 'safe' and 'finalized' tags in V1 APIs through BlockNumberOrHash resolution methods, achieving RPC parity with Lotus F3 behavior as required by issue #6631.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hm/f3-await-v1-rpc

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

@hanabi1224 hanabi1224 added the RPC requires calibnet RPC checks to run on CI label Feb 24, 2026
@hanabi1224 hanabi1224 changed the title fix(RPC): backport F3 fanality resolution to eth V1 methods fix(RPC): backport F3 finality resolution to eth V1 methods Feb 24, 2026
@hanabi1224 hanabi1224 marked this pull request as ready for review February 24, 2026 16:01
@hanabi1224 hanabi1224 requested a review from a team as a code owner February 24, 2026 16:01
@hanabi1224 hanabi1224 requested review from akaladarshi and sudo-shashank and removed request for a team February 24, 2026 16:01
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.

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)

2712-2718: ⚠️ Potential issue | 🟠 Major

Bug: V1 handler EthGetTransactionByBlockNumberAndIndex uses tipset_by_block_number_or_hash_v2 instead of _v1.

This method has API_PATHS: BitFlags<ApiPaths> = ApiPaths::all() (non-V2), yet it calls tipset_by_block_number_or_hash_v2. All other V1 handlers in this PR consistently use _v1. The V2 counterpart at line 2740 also correctly uses _v2. This means V1 callers of this endpoint won't respect the FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION env flag.

Proposed fix
         let ts = BlockNumberOrHash::from(block_param)
-            .tipset_by_block_number_or_hash_v2(&ctx, ResolveNullTipset::TakeOlder)
+            .tipset_by_block_number_or_hash_v1(&ctx, ResolveNullTipset::TakeOlder)
             .await?;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 2712 - 2718, The V1 handler
EthGetTransactionByBlockNumberAndIndex currently calls
tipset_by_block_number_or_hash_v2 which bypasses V1 feature gating; change the
call in the async fn handle (the BlockNumberOrHash::from(block_param) chain) to
use tipset_by_block_number_or_hash_v1 with the same ResolveNullTipset::TakeOlder
and ctx so V1 callers respect FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION and
match other V1 handlers.
🧹 Nitpick comments (10)
docs/docs/users/reference/env_variables.md (1)

61-61: Tighten phrasing in the description.

Consider shortening to “Whether to disable …” for concision.

✍️ Suggested tweak
-| `FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION`            | 1 or true                        | empty                                          | 1                                                             | Whether or not to disable F3 finality resolution in Eth v1 RPC methods                                                |
+| `FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION`            | 1 or true                        | empty                                          | 1                                                             | Whether to disable F3 finality resolution in Eth v1 RPC methods                                                       |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/users/reference/env_variables.md` at line 61, Update the
description for the environment variable
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION to a more concise phrasing: replace
"Whether or not to disable F3 finality resolution in Eth v1 RPC methods" with
"Whether to disable F3 finality resolution in Eth v1 RPC methods" in the docs
table row to tighten the wording.
src/rpc/methods/eth/types.rs (1)

270-275: Add a doc comment for the public enum.

BlockNumberOrPredefined is public; please add a short doc comment describing its purpose.

📝 Suggested doc comment
+/// Block selector used by eth RPCs; accepts either a predefined tag or a block number.
 #[derive(PartialEq, Debug, Clone, Serialize, Deserialize, JsonSchema, derive_more::From)]
 #[serde(untagged)]
 pub enum BlockNumberOrPredefined {

As per coding guidelines “Document all public functions and structs with doc comments”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth/types.rs` around lines 270 - 275, The public enum
BlockNumberOrPredefined lacks a doc comment; add a concise Rust doc comment
(///) above the enum BlockNumberOrPredefined explaining that it represents
either an explicit block number (BlockNumber variant holding EthInt64) or a
predefined block specifier (PredefinedBlock variant holding Predefined), and
mention its serialization behavior if relevant (serde untagged) so callers
understand its usage in RPC types.
src/tool/subcommands/api_cmd/test_snapshots.txt (1)

143-148: Verify new snapshot artifacts are available remotely.

Please confirm these new snapshot files have been uploaded to the snapshot bucket; otherwise the fetch step will fail for these test cases.

Based on learnings “In the Forest project, .rpcsnap.json.zst snapshot files listed in src/tool/subcommands/api_cmd/test_snapshots.txt are not stored in the repository itself but are downloaded from a DigitalOcean (DO) bucket when needed. The manifest file serves as an index/catalog of available snapshots.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tool/subcommands/api_cmd/test_snapshots.txt` around lines 143 - 148, The
test snapshot manifest src/tool/subcommands/api_cmd/test_snapshots.txt lists
several .rpcsnap.json.zst artifacts (e.g.,
filecoin_filecoinaddresstoethaddress_1771943760273649.rpcsnap.json.zst,
_1771943760275947..., _1771943760315677..., _1771946498262342...,
_1771946498262483..., _1771946498262885...) but these are not stored in-repo and
must exist in the remote snapshot bucket; verify each of these exact files has
been uploaded to the DigitalOcean snapshot bucket, ensure the bucket
manifest/catalog used by the fetch step includes these entries, confirm object
ACLs/public access or credentials permit the fetch, and if any are missing
upload them (or update the manifest file referenced by the fetch logic) so the
test fetch step succeeds.
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)

1475-1483: Minor inconsistency: use from_predefined instead of the variant directly.

Every other call site in this file uses BlockNumberOrHash::from_predefined(tag). The direct variant form works, but it exposes the internal enum structure unnecessarily.

♻️ Suggested fix
-                        (msg.clone(), BlockNumberOrHash::PredefinedBlock(tag)),
+                        (msg.clone(), BlockNumberOrHash::from_predefined(tag)),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tool/subcommands/api_cmd/api_compare_tests.rs` around lines 1475 - 1483,
Replace the direct enum construction BlockNumberOrHash::PredefinedBlock(tag)
with the helper constructor BlockNumberOrHash::from_predefined(tag) in the loop
that builds tests (inside the for tag in [Predefined::Latest, Predefined::Safe,
Predefined::Finalized] block). Update the EthCallV2::request_with_alias call
used when creating RpcTest::identity so it passes
BlockNumberOrHash::from_predefined(tag) instead of the PredefinedBlock variant
to match other call sites and avoid exposing the enum internals.
src/rpc/methods/chain.rs (2)

1049-1049: Consider simplifying with .map(Some) instead of Some(…).transpose().

Both are semantically identical — Result<Tipset>Result<Option<Tipset>> — but .map(Some) is more idiomatic and easier to read at a glance:

-            TipsetTag::Finalized => Some(Self::get_latest_finalized_tipset(ctx).await).transpose(),
+            TipsetTag::Finalized => Self::get_latest_finalized_tipset(ctx).await.map(Some),

(The Safe arm on line 1050 uses the same existing pattern; both could be changed for consistency, or left as-is — it's a pure readability preference.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/chain.rs` at line 1049, The match arm using
TipsetTag::Finalized currently wraps an awaited Result in Some(...).transpose();
replace that pattern by mapping the Result to an Option via .map(Some) on the
async call (i.e., change the expression involving
get_latest_finalized_tipset(ctx).await to
get_latest_finalized_tipset(ctx).await.map(Some)); do the same for the Safe arm
that uses get_latest_safe_tipset(ctx).await so both arms use the more idiomatic
.map(Some) conversion from Result<Tipset> to Result<Option<Tipset>>.

1071-1077: New public function is missing a doc comment (required by coding guidelines).

A brief description clarifying this is the EC-only (non-F3) safe-tipset path would also aid consumers in eth.rs.

📝 Suggested doc comment
+    /// Returns the EC-based safe tipset, i.e. the tipset at [`SAFE_HEIGHT_DISTANCE`] epochs
+    /// behind the current head, without consulting F3. Use [`get_latest_safe_tipset`] when
+    /// F3 finality should be preferred.
     pub fn get_ec_safe_tipset(ctx: &Ctx<impl Blockstore>) -> anyhow::Result<Tipset> {

As per coding guidelines: "Document all public functions and structs with doc comments".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/chain.rs` around lines 1071 - 1077, Add a Rust doc comment
(///) to the public function get_ec_safe_tipset describing its purpose and
behaviour: state that it returns the EC-only (non-F3) safe tipset by computing
safe_height = head.epoch() - SAFE_HEIGHT_DISTANCE and resolving the tipset at
that height with ResolveNullTipset::TakeOlder; note that this is the EC-only
safe-tipset path (not F3) and mention that consumers like eth.rs rely on this
contract. Ensure the comment sits immediately above the get_ec_safe_tipset
declaration and follows crate doc style and tone.
src/rpc/methods/eth.rs (4)

362-377: resolve_common_predefined_tipset returns Ok(None) for Safe and Finalized, delegating to callers.

The wildcard arm _ => Ok(None) matches Safe and Finalized, which is correct since these are handled by the caller (resolve_predefined_tipset_v1 / _v2). However, if new variants are ever added to Predefined, they'd silently fall through here too.

Consider using an explicit match instead of the wildcard to get a compile-time reminder if new variants are added:

Suggested change
-            _ => Ok(None),
+            Predefined::Safe | Predefined::Finalized => Ok(None),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 362 - 377, The match in
resolve_common_predefined_tipset currently uses a wildcard arm that returns
Ok(None), which will silently accept any future Predefined variants; change the
match to explicitly list all known variants (Earliest, Pending, Latest, Safe,
Finalized) and return Ok(None) for Safe and Finalized so the compiler will error
if a new variant is added, updating the match in the
resolve_common_predefined_tipset function to remove the `_ => Ok(None)` arm and
replace it with explicit arms for Safe and Finalized (and keep the existing
behavior for Earliest, Pending, Latest).

439-452: BlockNumberOrHash::from_str shadows FromStr::from_str.

The method from_str is defined as an inherent method (not implementing the FromStr trait), which silently shadows any potential FromStr trait implementation. This is fine functionally, but if FromStr is ever derived or implemented, the inherent method will always take precedence, which could cause confusion.

Also, the addition of "safe" and "finalized" parsing at lines 444-445 is correct and aligns with the PR objective.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 439 - 452, The current inherent method
BlockNumberOrHash::from_str shadows the standard FromStr trait; replace it by
implementing std::str::FromStr for BlockNumberOrHash (impl FromStr for
BlockNumberOrHash { type Err = Error; fn from_str(&str) -> Result<Self,
Self::Err> { ... } }) reusing the existing logic (keep the "earliest",
"pending", "latest"/"", "safe", "finalized" branches and the hex branch that
calls hex_str_to_epoch and then from_block_number/from_predefined); remove or
rename the original inherent from_str to avoid shadowing (e.g., rename to
parse_str) so there is no ambiguity between the trait impl and an inherent
method.

3857-3865: EthTraceCall serves V1 and V2 but always uses _v2 resolution.

This single handler serves both V1 | V2 paths. Using tipset_by_block_number_or_hash_v2 means V1 callers passing "safe" or "finalized" as block_param will get F3-based resolution regardless of FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION. The default case ("latest") is unaffected since both paths resolve it identically.

If the intent is to respect the env flag for V1, consider either splitting into V1/V2 handlers (like most other methods in this PR) or passing the API version dynamically.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 3857 - 3865, The handler for
EthTraceCall always uses tipset_by_block_number_or_hash_v2, causing V1 callers
using BlockNumberOrHash values like "safe" or "finalized" to get F3 resolution
regardless of FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION; update the handler
to respect API version by branching on the request version (or split into
separate V1/V2 handlers): if the caller is V1 use tipset_by_block_number_or_hash
(or the legacy resolver) when block_param is "safe"|"finalized", otherwise use
tipset_by_block_number_or_hash_v2 for V2; adjust the code around
EthTraceCall::handle, the BlockNumberOrHash parsing, and the call to
tipset_by_block_number_or_hash_v2 (and ResolveNullTipset::TakeOlder) so V1 flows
consult the env flag and legacy resolver while V2 continues to use the _v2
resolver.

3186-3191: FilecoinAddressToEthAddress defaults to Predefined::Finalized and always uses _v2.

This endpoint is served on all_with_v2() but always resolves via tipset_by_block_number_or_hash_v2. V1 callers (who omit block_param) will always get F3-finalized resolution, bypassing the FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION opt-out. Same concern as EthTraceCall – this may be intentional since there's no separate V2 handler, but it's inconsistent with the V1 backport pattern used elsewhere in this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/rpc/methods/eth.rs` around lines 3186 - 3191, The
FilecoinAddressToEthAddress handler currently defaults block_param to
Predefined::Finalized and always calls tipset_by_block_number_or_hash_v2,
causing V1 callers (served via all_with_v2()) to be forced to F3-finalized
resolution and bypass the FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION opt-out;
update the logic in the FilecoinAddressToEthAddress handler to detect V1
requests (as other V1 backports do) and: if V1 and the
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION flag is set, avoid defaulting to
Predefined::Finalized and call the non-_v2 resolver
(tipset_by_block_number_or_hash or the v1 variant) instead; otherwise keep the
existing v2 path (leave the block_param default and call
tipset_by_block_number_or_hash_v2) so v2 behavior remains unchanged. Reference
symbols: FilecoinAddressToEthAddress, block_param, Predefined::Finalized,
tipset_by_block_number_or_hash_v2, all_with_v2(), and
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/rpc/methods/eth.rs`:
- Around line 2712-2718: The V1 handler EthGetTransactionByBlockNumberAndIndex
currently calls tipset_by_block_number_or_hash_v2 which bypasses V1 feature
gating; change the call in the async fn handle (the
BlockNumberOrHash::from(block_param) chain) to use
tipset_by_block_number_or_hash_v1 with the same ResolveNullTipset::TakeOlder and
ctx so V1 callers respect FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION and match
other V1 handlers.

---

Nitpick comments:
In `@docs/docs/users/reference/env_variables.md`:
- Line 61: Update the description for the environment variable
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION to a more concise phrasing: replace
"Whether or not to disable F3 finality resolution in Eth v1 RPC methods" with
"Whether to disable F3 finality resolution in Eth v1 RPC methods" in the docs
table row to tighten the wording.

In `@src/rpc/methods/chain.rs`:
- Line 1049: The match arm using TipsetTag::Finalized currently wraps an awaited
Result in Some(...).transpose(); replace that pattern by mapping the Result to
an Option via .map(Some) on the async call (i.e., change the expression
involving get_latest_finalized_tipset(ctx).await to
get_latest_finalized_tipset(ctx).await.map(Some)); do the same for the Safe arm
that uses get_latest_safe_tipset(ctx).await so both arms use the more idiomatic
.map(Some) conversion from Result<Tipset> to Result<Option<Tipset>>.
- Around line 1071-1077: Add a Rust doc comment (///) to the public function
get_ec_safe_tipset describing its purpose and behaviour: state that it returns
the EC-only (non-F3) safe tipset by computing safe_height = head.epoch() -
SAFE_HEIGHT_DISTANCE and resolving the tipset at that height with
ResolveNullTipset::TakeOlder; note that this is the EC-only safe-tipset path
(not F3) and mention that consumers like eth.rs rely on this contract. Ensure
the comment sits immediately above the get_ec_safe_tipset declaration and
follows crate doc style and tone.

In `@src/rpc/methods/eth.rs`:
- Around line 362-377: The match in resolve_common_predefined_tipset currently
uses a wildcard arm that returns Ok(None), which will silently accept any future
Predefined variants; change the match to explicitly list all known variants
(Earliest, Pending, Latest, Safe, Finalized) and return Ok(None) for Safe and
Finalized so the compiler will error if a new variant is added, updating the
match in the resolve_common_predefined_tipset function to remove the `_ =>
Ok(None)` arm and replace it with explicit arms for Safe and Finalized (and keep
the existing behavior for Earliest, Pending, Latest).
- Around line 439-452: The current inherent method BlockNumberOrHash::from_str
shadows the standard FromStr trait; replace it by implementing std::str::FromStr
for BlockNumberOrHash (impl FromStr for BlockNumberOrHash { type Err = Error; fn
from_str(&str) -> Result<Self, Self::Err> { ... } }) reusing the existing logic
(keep the "earliest", "pending", "latest"/"", "safe", "finalized" branches and
the hex branch that calls hex_str_to_epoch and then
from_block_number/from_predefined); remove or rename the original inherent
from_str to avoid shadowing (e.g., rename to parse_str) so there is no ambiguity
between the trait impl and an inherent method.
- Around line 3857-3865: The handler for EthTraceCall always uses
tipset_by_block_number_or_hash_v2, causing V1 callers using BlockNumberOrHash
values like "safe" or "finalized" to get F3 resolution regardless of
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION; update the handler to respect API
version by branching on the request version (or split into separate V1/V2
handlers): if the caller is V1 use tipset_by_block_number_or_hash (or the legacy
resolver) when block_param is "safe"|"finalized", otherwise use
tipset_by_block_number_or_hash_v2 for V2; adjust the code around
EthTraceCall::handle, the BlockNumberOrHash parsing, and the call to
tipset_by_block_number_or_hash_v2 (and ResolveNullTipset::TakeOlder) so V1 flows
consult the env flag and legacy resolver while V2 continues to use the _v2
resolver.
- Around line 3186-3191: The FilecoinAddressToEthAddress handler currently
defaults block_param to Predefined::Finalized and always calls
tipset_by_block_number_or_hash_v2, causing V1 callers (served via all_with_v2())
to be forced to F3-finalized resolution and bypass the
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION opt-out; update the logic in the
FilecoinAddressToEthAddress handler to detect V1 requests (as other V1 backports
do) and: if V1 and the FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION flag is set,
avoid defaulting to Predefined::Finalized and call the non-_v2 resolver
(tipset_by_block_number_or_hash or the v1 variant) instead; otherwise keep the
existing v2 path (leave the block_param default and call
tipset_by_block_number_or_hash_v2) so v2 behavior remains unchanged. Reference
symbols: FilecoinAddressToEthAddress, block_param, Predefined::Finalized,
tipset_by_block_number_or_hash_v2, all_with_v2(), and
FOREST_ETH_V1_DISABLE_F3_FINALITY_RESOLUTION.

In `@src/rpc/methods/eth/types.rs`:
- Around line 270-275: The public enum BlockNumberOrPredefined lacks a doc
comment; add a concise Rust doc comment (///) above the enum
BlockNumberOrPredefined explaining that it represents either an explicit block
number (BlockNumber variant holding EthInt64) or a predefined block specifier
(PredefinedBlock variant holding Predefined), and mention its serialization
behavior if relevant (serde untagged) so callers understand its usage in RPC
types.

In `@src/tool/subcommands/api_cmd/api_compare_tests.rs`:
- Around line 1475-1483: Replace the direct enum construction
BlockNumberOrHash::PredefinedBlock(tag) with the helper constructor
BlockNumberOrHash::from_predefined(tag) in the loop that builds tests (inside
the for tag in [Predefined::Latest, Predefined::Safe, Predefined::Finalized]
block). Update the EthCallV2::request_with_alias call used when creating
RpcTest::identity so it passes BlockNumberOrHash::from_predefined(tag) instead
of the PredefinedBlock variant to match other call sites and avoid exposing the
enum internals.

In `@src/tool/subcommands/api_cmd/test_snapshots.txt`:
- Around line 143-148: The test snapshot manifest
src/tool/subcommands/api_cmd/test_snapshots.txt lists several .rpcsnap.json.zst
artifacts (e.g.,
filecoin_filecoinaddresstoethaddress_1771943760273649.rpcsnap.json.zst,
_1771943760275947..., _1771943760315677..., _1771946498262342...,
_1771946498262483..., _1771946498262885...) but these are not stored in-repo and
must exist in the remote snapshot bucket; verify each of these exact files has
been uploaded to the DigitalOcean snapshot bucket, ensure the bucket
manifest/catalog used by the fetch step includes these entries, confirm object
ACLs/public access or credentials permit the fetch, and if any are missing
upload them (or update the manifest file referenced by the fetch logic) so the
test fetch step succeeds.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 442e716 and c3496cd.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/dictionary.txt
  • docs/docs/users/reference/env_variables.md
  • src/eth/mod.rs
  • src/rpc/methods/chain.rs
  • src/rpc/methods/eth.rs
  • src/rpc/methods/eth/types.rs
  • src/tool/subcommands/api_cmd/api_compare_tests.rs
  • src/tool/subcommands/api_cmd/test_snapshot.rs
  • src/tool/subcommands/api_cmd/test_snapshots.txt
💤 Files with no reviewable changes (1)
  • src/eth/mod.rs

@codecov
Copy link

codecov bot commented Feb 24, 2026

Codecov Report

❌ Patch coverage is 73.55769% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.54%. Comparing base (442e716) to head (cdc74ba).

Files with missing lines Patch % Lines
src/rpc/methods/eth.rs 76.06% 17 Missing and 28 partials ⚠️
src/rpc/methods/chain.rs 44.44% 9 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/rpc/methods/eth/types.rs 75.56% <100.00%> (ø)
src/tool/subcommands/api_cmd/test_snapshot.rs 85.10% <ø> (ø)
src/rpc/methods/chain.rs 52.36% <44.44%> (-0.52%) ⬇️
src/rpc/methods/eth.rs 69.54% <76.06%> (+0.45%) ⬆️

... and 9 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 442e716...cdc74ba. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Support safe and finalized in V1 APIs

1 participant