Skip to content

Conversation

@sudo-shashank
Copy link
Contributor

@sudo-shashank sudo-shashank commented Dec 18, 2025

Summary of changes

Changes introduced in this pull request:

  • Add Filecoin.EthEstimateGas V2 API and test snapshots.
  • Refactored Filecoin.EthCall to remove logic duplication.
  • Fix gas_search function

Reference issue to close (if applicable)

Closes #6291

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

    • Added Filecoin.EthEstimateGas RPC endpoint in API v2 (alias: eth_estimateGas) and updated Filecoin.EthCall to expose a V2 call path.
  • Tests

    • Added tests covering EthEstimateGas v2 behavior and the new v2 call path.
  • Documentation

    • Updated unreleased changelog entries to reflect the new v2 endpoints.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Walkthrough

Adds a V2 RPC method for Filecoin.EthEstimateGas, centralizes EthCall and gas-estimation logic into shared helpers (eth_estimate_gas, eth_gas_search, gas_search, eth_call), updates RPC exports, adds tests for the V2 endpoint, and updates the changelog.

Changes

Cohort / File(s) Summary
Changelog & RPC export
CHANGELOG.md, src/rpc/mod.rs
Adds changelog entry for EthEstimateGas (PR #6364) and registers new EthEstimateGasV2 in the RPC method list.
Core RPC methods
src/rpc/methods/eth.rs
Adds EthEstimateGasV2 and V2 API path support; introduces eth_estimate_gas, eth_gas_search, gas_search and refactors gas-estimation into exponential+binary search with can_succeed checks; centralizes eth-call logic into eth_call used by EthCall/EthCallV2.
Tests
src/tool/subcommands/api_cmd/api_compare_tests.rs
Adjusts EthAddress parsing to use EthAddress::try_from, reuses parsed address, and adds a test block for EthEstimateGasV2 (with ExtBlockNumberOrHash::BlockNumber).

Sequence Diagram(s)

sequenceDiagram
    participant Client as RPC Client
    participant Handler as EthEstimateGasV2 Handler
    participant Estimator as eth_estimate_gas()
    participant Search as eth_gas_search()
    participant Probe as gas_search()/can_succeed()
    participant Chain as Blockchain (estimate/apply/call)

    Client->>Handler: Filecoin.EthEstimateGas (EthCallMessage, blockParam)
    Handler->>Handler: resolve tipset (V2 resolver)
    Handler->>Estimator: invoke eth_estimate_gas(tx, tipset)

    Estimator->>Chain: estimate_message_gas(msg)
    alt estimate_message_gas succeeds
        Chain-->>Estimator: gas_estimate
        Estimator->>Search: eth_gas_search(msg, tipset)
    else estimate_message_gas fails
        Chain-->>Estimator: error
        Estimator->>Chain: apply_message(msg) to capture revert info
        Chain-->>Estimator: execution result / revert
        Estimator-->>Handler: propagate error
    end

    Search->>Probe: perform exponential then binary search
    loop search iterations
        Probe->>Chain: call_with_gas(msg, gas_limit)
        Chain-->>Probe: execution result (exit code, data)
        Probe-->>Probe: adjust bounds
    end

    Probe-->>Search: found gas limit
    Search->>Estimator: apply mpool overestimation factor
    Estimator-->>Handler: return EthUint64 result
    Handler-->>Client: RPC response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • eth_gas_search / gas_search algorithm correctness (exponential + binary search, bounds, overestimation)
    • Error handling when estimate_message_gas falls back to apply_message (revert detection)
    • Tipset/block resolution for V2 (ExtBlockNumberOrHash) and ApiPaths::V2 usage
    • eth_call return decoding and ETH_ACCOUNT_MANAGER edge case handling

Possibly related PRs

Suggested labels

RPC

Suggested reviewers

  • hanabi1224
  • akaladarshi

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% 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
Title check ✅ Passed The title directly summarizes the main objective of the PR: adding support for the Filecoin.EthEstimateGas V2 API, which is clearly reflected in the code changes across multiple files.
Linked Issues check ✅ Passed The PR successfully implements the RPC v2 method Filecoin.EthEstimateGas [#6291] by adding EthEstimateGasV2 enum, implementing the RpcMethod trait with proper V2 API paths, and creating supporting gas estimation logic.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing Filecoin.EthEstimateGas V2. While the PR also refactors EthCall logic, this is explicitly mentioned as part of the PR description ('Refactors Filecoin.EthCall to remove duplicated logic') and reduces duplication in the implementation.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 shashank/eth-estimate-gas-v2

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

@sudo-shashank sudo-shashank marked this pull request as ready for review December 18, 2025 11:27
@sudo-shashank sudo-shashank requested a review from a team as a code owner December 18, 2025 11:27
@sudo-shashank sudo-shashank requested review from akaladarshi and hanabi1224 and removed request for a team December 18, 2025 11:27
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: 2

🧹 Nitpick comments (2)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)

2047-2075: EthEstimateGas / EthEstimateGasV2 API comparison tests are well‑wired

The updated address conversion with EthAddress::try_from(msg.to) plus the paired EthEstimateGas (v1) and EthEstimateGasV2 (v2) RpcTest::identity cases correctly exercise both versions using the appropriate block selector types. Ownership (eth_to_addr.clone() for v1, move into v2) is handled cleanly, and the shared PolicyOnRejected::Pass keeps failure behavior aligned.

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

1831-1885: Shared EthEstimateGas / EthEstimateGasV2 implementation is sound; consider logging level

The new eth_estimate_gas helper cleanly centralizes gas estimation for both EthEstimateGas (legacy paths) and EthEstimateGasV2 (v2-only path) while:

  • Forcing the Message gas limit to the zero sentinel so gas::estimate_message_gas performs a full estimation.
  • Re-running the message via apply_message on estimation failure to surface proper EthErrors::ExecutionReverted details when applicable.
  • Delegating to eth_gas_search to refine the gas limit when estimation succeeds.

Functionally this is a solid design and aligns the error story between v1 and v2. The only minor nit is the use of log::info! inside eth_estimate_gas for every estimation; if this path is hot, you may want to downgrade those logs to debug! to avoid noisy production logs.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbb25b2 and 1680184.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • src/rpc/methods/eth.rs (4 hunks)
  • src/rpc/mod.rs (1 hunks)
  • src/tool/subcommands/api_cmd/api_compare_tests.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T10:05:34.350Z
Learnt from: akaladarshi
Repo: ChainSafe/forest PR: 5923
File: src/rpc/registry/actors/miner.rs:221-223
Timestamp: 2025-09-02T10:05:34.350Z
Learning: For miner actor ChangeOwnerAddress and ChangeOwnerAddressExported methods: versions 8-10 use bare Address as parameter type, while versions 11+ use ChangeOwnerAddressParams. This reflects the evolution of the Filecoin miner actor parameter structures across versions.

Applied to files:

  • src/tool/subcommands/api_cmd/api_compare_tests.rs
🧬 Code graph analysis (2)
src/tool/subcommands/api_cmd/api_compare_tests.rs (1)
src/rpc/methods/eth/types.rs (9)
  • try_from (235-242)
  • try_from (248-250)
  • try_from (256-258)
  • try_from (270-272)
  • try_from (278-280)
  • try_from (353-393)
  • default (483-485)
  • default (629-631)
  • default (657-659)
src/rpc/methods/eth.rs (3)
src/rpc/methods/gas.rs (2)
  • estimate_message_gas (317-343)
  • estimate_call_with_gas (214-266)
src/rpc/error.rs (1)
  • error (103-103)
src/rpc/methods/eth/utils.rs (1)
  • decode_payload (63-76)
⏰ 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: Coverage
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: tests-release
  • GitHub Check: All lint checks
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build Ubuntu
  • GitHub Check: Build MacOS
🔇 Additional comments (2)
src/rpc/mod.rs (1)

107-109: Wiring EthEstimateGasV2 into the RPC registry looks correct

Registering EthEstimateGasV2 in for_each_rpc_method! next to EthEstimateGas is consistent with how EthCall/EthCallV2 are exposed and ensures the new v2 endpoint participates in both routing and OpenRPC generation.

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

2671-2693: EthCall / EthCallV2 refactor via eth_call helper preserves behavior and improves reuse

The changes to EthCall and EthCallV2 to delegate into the shared eth_call helper look good:

  • Both variants still resolve the correct tipset (tipset_by_block_number_or_hash for v1, async tipset_by_block_number_or_hash_v2 for v2), then call eth_call(&ctx, tx, ts).
  • eth_call centralizes:
    • EthCallMessageMessage conversion.
    • Execution via apply_message, so all EthCall paths now share consistent revert handling (EthErrors::ExecutionReverted mapping).
    • Special-case handling for ETHEREUM_ACCOUNT_MANAGER_ACTOR (empty bytes) and CBOR-decoding of non-empty return data via decode_payload.
  • Restricting EthCallV2 to ApiPaths::V2 is aligned with the versioned API design introduced elsewhere.

Net effect: less duplicated logic with no obvious behavioral regression.

Also applies to: 2695-2718

@sudo-shashank sudo-shashank marked this pull request as draft December 18, 2025 11:41
auto-merge was automatically disabled December 18, 2025 11:41

Pull request was converted to draft

@sudo-shashank sudo-shashank marked this pull request as ready for review December 18, 2025 13:17
@sudo-shashank sudo-shashank marked this pull request as draft December 18, 2025 13:17
@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 11.97183% with 125 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.15%. Comparing base (4ea21a4) to head (53dcc7b).

Files with missing lines Patch % Lines
src/rpc/methods/eth.rs 13.60% 104 Missing and 4 partials ⚠️
src/tool/subcommands/api_cmd/api_compare_tests.rs 0.00% 17 Missing ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/rpc/mod.rs 24.47% <ø> (ø)
src/tool/subcommands/api_cmd/api_compare_tests.rs 0.00% <0.00%> (ø)
src/rpc/methods/eth.rs 66.22% <13.60%> (-0.10%) ⬇️

... and 18 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 4ea21a4...53dcc7b. Read the comment docs.

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

@sudo-shashank sudo-shashank marked this pull request as ready for review December 18, 2025 15:13
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: 1

♻️ Duplicate comments (1)
src/rpc/methods/eth.rs (1)

1967-2063: [Critical] Infinite loop and unverified gas limit remain unfixed from previous review.

The previous review identified two critical issues in gas_search that have not been addressed:

  1. Infinite loop when message cannot succeed at block gas limit (lines 2043-2049):

When can_succeed(..., BLOCK_GAS_LIMIT) returns false, the exponential search will loop forever:

  • high saturates to BLOCK_GAS_LIMIT (line 2048)
  • low is set to BLOCK_GAS_LIMIT (line 2047)
  • Loop condition high <= BLOCK_GAS_LIMIT remains true
  • Next iteration re-runs with same values indefinitely

This will hang RPC requests when users submit messages that cannot execute even with maximum gas.

  1. Binary search now calls can_succeed(median) correctly (line 2054) ✓ — this was fixed.

  2. Missing final verification (line 2062):

The function returns high without confirming it actually allows execution to succeed. The binary search may converge to a failing gas limit.

🔎 Apply this fix to prevent infinite loops and verify the result:
 async fn gas_search<DB>(
     data: &Ctx<DB>,
     msg: &Message,
     prior_messages: &[ChainMessage],
     ts: Tipset,
 ) -> anyhow::Result<u64>
 where
     DB: Blockstore + Send + Sync + 'static,
 {
     let mut high = msg.gas_limit;
     let mut low = msg.gas_limit;
 
     async fn can_succeed<DB>(
         data: &Ctx<DB>,
         mut msg: Message,
         prior_messages: &[ChainMessage],
         ts: Tipset,
         limit: u64,
     ) -> anyhow::Result<bool>
     where
         DB: Blockstore + Send + Sync + 'static,
     {
         msg.gas_limit = limit;
         let (_invoc_res, apply_ret, _) = data
             .state_manager
             .call_with_gas(
                 &mut msg.into(),
                 prior_messages,
                 Some(ts),
                 VMTrace::NotTraced,
             )
             .await?;
         Ok(apply_ret.msg_receipt().exit_code().is_success())
     }
 
     while high <= BLOCK_GAS_LIMIT {
         if can_succeed(data, msg.clone(), prior_messages, ts.clone(), high).await? {
             break;
         }
+        // If we're already at the block gas limit and still failing, give up.
+        if high == BLOCK_GAS_LIMIT {
+            anyhow::bail!(
+                "message execution failed even at block gas limit ({})",
+                BLOCK_GAS_LIMIT
+            );
+        }
         low = high;
         high = high.saturating_mul(2).min(BLOCK_GAS_LIMIT);
     }
 
     let mut check_threshold = high / 100;
     while (high - low) > check_threshold {
         let median = (high + low) / 2;
         if can_succeed(data, msg.clone(), prior_messages, ts.clone(), median).await? {
             high = median;
         } else {
             low = median;
         }
         check_threshold = median / 100;
     }
 
+    // Final sanity check: ensure the returned `high` actually succeeds.
+    if !can_succeed(data, msg.clone(), prior_messages, ts, high).await? {
+        anyhow::bail!("failed to find a gas limit that allows execution to succeed");
+    }
+
     Ok(high)
 }
🧹 Nitpick comments (1)
src/rpc/methods/eth.rs (1)

1924-1926: Consider using debug! instead of info! for these logs.

Lines 1924 and 1926 use log::info! for messages that appear to be debugging information ("correct gassed_msg: do eth_gas_search", "trying eth_gas search"). These will create noise in production logs for every gas estimation request.

🔎 Reduce log verbosity:
-            log::info!("correct gassed_msg: do eth_gas_search {gassed_msg:?}");
+            tracing::debug!("running eth_gas_search for message: {gassed_msg:?}");
             let expected_gas = eth_gas_search(ctx, gassed_msg, &tipset.key().into()).await?;
-            log::info!("trying eth_gas search: {expected_gas}");
+            tracing::debug!("eth_gas_search result: {expected_gas}");
             Ok(expected_gas.into())
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 254e3f2 and 41be34e.

📒 Files selected for processing (1)
  • src/rpc/methods/eth.rs (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/rpc/methods/eth.rs (4)
src/rpc/methods/eth/types.rs (3)
  • default (483-485)
  • default (629-631)
  • default (657-659)
src/rpc/methods/gas.rs (1)
  • estimate_message_gas (317-343)
src/rpc/error.rs (1)
  • error (103-103)
src/rpc/methods/eth/utils.rs (1)
  • decode_payload (63-76)
⏰ 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). (3)
  • GitHub Check: Coverage
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: tests-release
🔇 Additional comments (2)
src/rpc/methods/eth.rs (2)

1861-1886: LGTM! V2 endpoint correctly configured.

The EthEstimateGasV2 implementation properly:

  • Uses ApiPaths::V2 flag to expose only on the V2 API path
  • Accepts ExtBlockNumberOrHash for extended block parameters (Safe/Finalized)
  • Delegates tipset resolution to the async tipset_by_block_number_or_hash_v2 helper
  • Shares the core estimation logic with V1 via eth_estimate_gas

This follows the same pattern as EthCallV2 and maintains backward compatibility.


2695-2718: Good refactoring that eliminates duplication.

The new eth_call helper successfully consolidates the logic from EthCall and EthCallV2:

  • Preserves the special-case handling for ETHEREUM_ACCOUNT_MANAGER_ACTOR (line 2706)
  • Properly decodes return data via CBOR when present (line 2714)
  • Handles empty return data correctly (lines 2711-2712)
  • Error handling looks correct with context messages (line 2709)

Both V1 and V2 endpoints now delegate to this shared implementation, improving maintainability.

@sudo-shashank
Copy link
Contributor Author

@akaladarshi @hanabi1224 this PR needs your review

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.

[RPC v2] Filecoin.EthEstimateGas

2 participants