Skip to content

Conversation

@elmattic
Copy link
Contributor

@elmattic elmattic commented Jul 15, 2025

Summary of changes

Changes introduced in this pull request:

  • Add api test-stateful subcommand to forest-tool

Usage example:

Lotus:

$ ./forest-tool api test-stateful <lotus-multi-addr> --to t410f2jhqlciub25ad3immo5kug2fluj625xiex6lbyi --from t410f5uudc3yoiodsva73rxyx5sxeiaadpaplsu6mofy --payload 40c10f19000000000000000000000000ed28316f0e43872a83fb8df17ecae440003781eb00000000000000000000000000000000000000000000000006f05b59d3b20000 --topic 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
running 7 tests
test eth_newFilter install/uninstall ... ok
test eth_newFilter under limit ... ok
test eth_newFilter just under limit ... ok
test eth_newFilter over limit ... ok
test eth_newBlockFilter works ... ok
test eth_newPendingTransactionFilter works ... ok
test eth_getFilterLogs works ... ok
test result: ok. 7 passed; 0 failed; 0 ignored; 0 filtered out

Forest:

$ ./forest-tool api test-stateful <forest-multi-addr> --to t410f2jhqlciub25ad3immo5kug2fluj625xiex6lbyi --from t410f5uudc3yoiodsva73rxyx5sxeiaadpaplsu6mofy --payload 40c10f19000000000000000000000000ed28316f0e43872a83fb8df17ecae440003781eb00000000000000000000000000000000000000000000000006f05b59d3b20000 --topic 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
running 7 tests
test eth_newFilter install/uninstall ... ok
test eth_newFilter under limit ... ok
test eth_newFilter just under limit ... ok
test eth_newFilter over limit ... FAILED
test eth_newBlockFilter works ... FAILED
test eth_newPendingTransactionFilter works ... FAILED
test eth_getFilterLogs works ... FAILED
test result: FAILED. 3 passed; 4 failed; 0 ignored; 0 filtered out

Reference issue to close (if applicable)

Closes #5793, #5975

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 a CLI command and test harness to run stateful JSON‑RPC scenarios (filters, subscriptions, pending tx) against a node.
  • Documentation

    • New guide with prerequisites, usage, example output, and instructions for adding stateful RPC tests.
  • Refactor

    • Filter query results unified to return hashes for consistency.
  • Bug Fixes

    • JSON‑RPC notifications now embed proper JSON values instead of stringified payloads.
  • Chores

    • CI job, runnable Calibnet test script, ERC‑20 contract/assets, and a WebSocket dependency added to support stateful tests.
  • Improvements

    • Enabled transaction debug output and added a hex-format helper for numeric values.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 15, 2025

Walkthrough

Adds a stateful RPC test harness and CLI subcommand to run Ethereum filter-related integration tests against a live node, plus docs, ERC‑20 test assets, CI job and runner script, a WebSocket dependency, and small RPC/type/serialization and visibility adjustments.

Changes

Cohort / File(s) Change Summary
Docs: Stateful RPC tests
documentation/src/developer_documentation/rpc_stateful_tests.md
New guide describing prerequisites, usage, example output, and how to add stateful RPC tests.
CLI: API stateful test command
src/tool/subcommands/api_cmd.rs, src/tool/subcommands/api_cmd/stateful_tests.rs
Added ApiCommands::TestStateful variant and wiring: parse args, build TestTransaction, create and run scenario suite via create_tests/run_tests.
Test harness & scenarios
src/tool/subcommands/api_cmd/stateful_tests.rs
New test harness: TestTransaction, RpcTestScenario, scenario builders, WS/mempool helpers, create_tests, run_tests, per-scenario filtering/ignore handling, and predefined filter-focused scenarios.
Contracts assets for testing
src/tool/subcommands/api_cmd/contracts/erc20/roberto.sol, src/tool/subcommands/api_cmd/contracts/erc20/roberto.hex
Added an ERC‑20 contract source and compiled hex payload used to generate logs for tests.
CI workflow & runner script
.github/workflows/forest.yml, scripts/tests/calibnet_api_test_stateful_check.sh
Added calibnet-api-test-stateful CI job and executable script to run forest-tool api test-stateful against Calibnet with preset addresses/payload/topic.
RPC filter types and helpers
src/rpc/methods/eth/types.rs, src/rpc/methods/eth.rs
Consolidated EthFilterResult::Blocks/Txs into Hashes(Vec<EthHash>); updated consumers; added EthUint64::to_hex_string().
RPC channel notification serialization
src/rpc/channel.rs
Notification result now serialized as JSON value (to_value()) instead of a JSON string (to_string()).
ETH module & transaction visibility
src/eth/mod.rs, src/eth/transaction.rs
Made transaction module public, derived Debug for EthTx, and made EthTx::rlp_signed_message public.
Dependencies
Cargo.toml
Added tokio-tungstenite = "0.27.0" for WebSocket support.
Config / dictionary
.config/forest.dic
Added dictionary entries calldata and f4.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  rect rgba(240,248,255,0.9)
  participant CLI as User (forest-tool)
  participant TH as Test Harness
  participant RPC as rpc::Client (HTTP + WS)
  participant N as Forest Node
  end

  CLI->>TH: invoke test-stateful (to, from, payload, topic, filter)
  TH->>RPC: build client (HTTP + WS)
  TH->>TH: create_tests(TestTransaction)
  loop per scenario
    alt subscription-based
      TH->>RPC: subscribe via WS (heads/pending)
      RPC-->>TH: subscription notifications
    end
    TH->>RPC: eth_newFilter / eth_newBlockFilter / eth_newPendingTransactionFilter
    TH->>N: trigger event (invoke contract / send tx)
    N-->>RPC: emit logs / heads / pending
    TH->>RPC: eth_getFilterChanges / eth_getFilterLogs
    RPC-->>TH: return Hashes / Logs
    TH-->>CLI: scenario pass/fail
  end
  TH-->>CLI: aggregated summary
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Add tests covering eth_newFilter / eth_uninstallFilter and edge cases (#5793)
Add tests for eth_newBlockFilter + eth_getFilterChanges (#5793)
Add tests for eth_newPendingTransactionFilter + eth_getFilterChanges, including sending txs (#5793)
Add tests for eth_getFilterLogs using contract-generated logs (#5793)
Test limits, many concurrent filters, and expiration/timeout behavior (#5793) Suite includes a limit-related scenario but lacks explicit high-concurrency stress run and clear expiry verification logic.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Notification serialization changed to JSON value (src/rpc/channel.rs) Notification payload shape change is unrelated to adding tests and modifies RPC message format.
Consolidated filter result variants to Hashes (src/rpc/methods/eth/types.rs) Type-level refactor of filter result representation not required by test additions and may impact other consumers.
Increased visibility for eth transaction internals (src/eth/mod.rs, src/eth/transaction.rs) Publicizing module/methods expands API surface unrelated to the stated testing objectives.

Possibly related PRs

Suggested reviewers

  • akaladarshi
  • LesnyRumcajs
  • hanabi1224

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elmattic/api-run-subcommand

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

♻️ Duplicate comments (2)
src/tool/subcommands/api_cmd.rs (2)

231-246: Optional: parse strongly-typed args at the clap boundary to centralize validation

Let clap parse Address/EthHash/hex bytes for you to reduce error-prone String plumbing and push validation to the boundary. This keeps run() lean and avoids duplicated parsing logic.

Minimal change (no external deps), using a small parser for hex:

-        /// Test Transaction `to` address
-        #[arg(long)]
-        to: String,
-        /// Test Transaction `from` address
-        #[arg(long)]
-        from: String,
-        /// Test Transaction hex `payload`
-        #[arg(long)]
-        payload: String,
-        /// Log `topic` to search for
-        #[arg(long)]
-        topic: String,
+        /// Test Transaction `to` address
+        #[arg(long, value_parser = clap::builder::ValueParser::new(Address::from_str))]
+        to: Address,
+        /// Test Transaction `from` address
+        #[arg(long, value_parser = clap::builder::ValueParser::new(Address::from_str))]
+        from: Address,
+        /// Test Transaction hex `payload` (accepts optional 0x prefix)
+        #[arg(long, value_parser = parse_hex_bytes)]
+        payload: Vec<u8>,
+        /// Log `topic` to search for (0x‑prefixed 32‑byte hash)
+        #[arg(long, value_parser = clap::builder::ValueParser::new(EthHash::from_str))]
+        topic: EthHash,

Add this helper in the same file (top-level):

fn parse_hex_bytes(s: &str) -> Result<Vec<u8>, String> {
    let clean = s.strip_prefix("0x").unwrap_or(s);
    hex::decode(clean).map_err(|e| format!("invalid hex: {s} ({e})"))
}

With this, the run() arm can drop all manual parsing lines and directly construct TestTransaction.


395-417: Accept “0x”-prefixed payloads and add parsing context to improve UX

hex::decode(payload) will reject the commonly used 0x-prefixed form; address/topic errors also lack context. Strip an optional 0x and wrap parses with with_context. Also trim filter to avoid surprises from trailing spaces.

             } => {
-                let client = Arc::new(rpc::Client::default_or_from_env(None)?);
+                let client = Arc::new(
+                    rpc::Client::default_or_from_env(None)
+                        .with_context(|| "could not initialize RPC client; check FULLNODE_API_INFO or that a node is running on 127.0.0.1:2345")?
+                );
 
-                let to = Address::from_str(&to)?;
-                let from = Address::from_str(&from)?;
-                let payload = hex::decode(payload)?;
-                let topic = EthHash::from_str(&topic)?;
+                let to = Address::from_str(&to)
+                    .with_context(|| format!("invalid --to address: {to}"))?;
+                let from = Address::from_str(&from)
+                    .with_context(|| format!("invalid --from address: {from}"))?;
+                let payload = {
+                    let clean = payload.strip_prefix("0x").unwrap_or(&payload);
+                    hex::decode(clean)
+                        .with_context(|| format!("invalid --payload hex: {payload}"))?
+                };
+                let topic = EthHash::from_str(&topic)
+                    .with_context(|| format!("invalid --topic (expect 0x-prefixed 32-byte hash): {topic}"))?;
                 let tx = TestTransaction {
                     to,
                     from,
                     payload,
                     topic,
                 };
 
-                let tests = stateful_tests::create_tests(tx).await;
-                stateful_tests::run_tests(tests, client, filter).await?;
+                let tests = stateful_tests::create_tests(tx).await;
+                let filter = filter.trim().to_string();
+                stateful_tests::run_tests(tests, client, filter).await?;
             }
🧹 Nitpick comments (1)
src/tool/subcommands/api_cmd.rs (1)

208-246: Tighten CLI help: document address/hex formats, FULLNODE_API_INFO, and filter semantics

Current help omits crucial format guidance and environment usage. Clarify that:

  • to/from must be Filecoin addresses (f/t or delegated f4).
  • payload is hex and may include an optional 0x prefix.
  • topic is a 32‑byte Keccak hash (0x… with 64 hex nibbles).
  • connection is taken from FULLNODE_API_INFO (or defaults to 127.0.0.1:2345).
  • filter is case‑sensitive and matches by method-name prefix.

Apply this doc-only diff:

-    /// Run multiple stateful JSON-RPC API tests against a Filecoin node.
+    /// Run a suite of stateful JSON-RPC API tests against a Filecoin node.
     ///
-    /// Some tests require sending a transaction to trigger events; the provided
-    /// `from`, `to`, `payload`, and `topic` inputs are used for those cases.
+    /// Connection:
+    /// - Uses `FULLNODE_API_INFO` if set (e.g. `/ip4/127.0.0.1/tcp/2345/http` or a multiaddr with token).
+    ///   Falls back to `http://127.0.0.1:2345/`.
+    ///
+    /// Inputs:
+    /// - `--from`, `--to`: Filecoin addresses (`f…`/`t…`, including delegated `f4`).
+    /// - `--payload`: hex data; both `deadbeef` and `0xdeadbeef` are accepted.
+    /// - `--topic`: 32-byte event topic (Keccak-256), 0x-prefixed 64-nybble hex.
     ///
-    /// Useful for verifying methods like `eth_newFilter`, `eth_getFilterLogs`, and others
-    /// that rely on internal state.
+    /// Useful for verifying methods like `eth_newFilter`, `eth_getFilterLogs`, and others that rely on internal state.
     ///
-    /// Use `--filter` to run only tests that interact with a specific RPC method.
+    /// Use `--filter` to run only tests that interact with a specific RPC method.
+    /// The match is case-sensitive and by method-name prefix (e.g. `--filter eth_new`).
     ///
-    /// Example output:
-    /// ```text
+    /// Example (Lotus; all pass):
+    /// ```console
     /// running 7 tests
     /// test eth_newFilter install/uninstall ... ok
     /// test eth_newFilter under limit ... ok
     /// test eth_newFilter just under limit ... ok
     /// test eth_newFilter over limit ... ok
     /// test eth_newBlockFilter works ... ok
     /// test eth_newPendingTransactionFilter works ... ok
     /// test eth_getFilterLogs works ... ok
     /// test result: ok. 7 passed; 0 failed; 0 ignored; 0 filtered out
     /// ```
+    /// Example (Forest; some tests currently ignored/pending fixes):
+    /// ```console
+    /// running 7 tests
+    /// test eth_newFilter install/uninstall ... ok
+    /// test eth_newFilter under limit ... ok
+    /// test eth_newFilter just under limit ... ok
+    /// test eth_newFilter over limit ... ignored
+    /// test eth_newBlockFilter works ... ok
+    /// test eth_newPendingTransactionFilter works ... ignored
+    /// test eth_getFilterLogs works ... ignored
+    /// test result: ok. 4 passed; 0 failed; 3 ignored; 0 filtered out
+    /// ```
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7de68a9 and 11dfa3f.

📒 Files selected for processing (2)
  • scripts/tests/calibnet_api_test_stateful_check.sh (1 hunks)
  • src/tool/subcommands/api_cmd.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/tests/calibnet_api_test_stateful_check.sh
🧰 Additional context used
🧬 Code graph analysis (1)
src/tool/subcommands/api_cmd.rs (4)
src/rpc/client.rs (2)
  • client (114-114)
  • default_or_from_env (46-77)
src/rpc/methods/eth.rs (13)
  • new (512-524)
  • new (677-682)
  • from_str (262-264)
  • from_str (370-381)
  • from_str (430-449)
  • from (136-138)
  • from (142-144)
  • from (268-271)
  • from (275-277)
  • filter (3101-3101)
  • filter (3151-3151)
  • filter (3176-3176)
  • filter (3208-3208)
src/shim/address.rs (2)
  • from_str (178-183)
  • from_str (299-302)
src/tool/subcommands/api_cmd/stateful_tests.rs (2)
  • create_tests (606-655)
  • run_tests (91-168)
⏰ 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). (9)
  • 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 MacOS
  • GitHub Check: Build Ubuntu
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (3)
src/tool/subcommands/api_cmd.rs (3)

7-7: Adding stateful_tests module — LGTM

Module layout looks consistent with the rest of the file’s submodules.


21-21: Importing TestTransaction — LGTM

Direct import keeps the call site in run() clean.


30-30: FromStr import — LGTM

Needed for Address/EthHash parsing below.

@LesnyRumcajs
Copy link
Member

no green checkmark!

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

♻️ Duplicate comments (2)
src/tool/subcommands/api_cmd.rs (2)

236-252: Prefer strong typing at the clap boundary for --to, --from, --topic

Let clap parse Address and EthHash via FromStr to fail fast with better help and remove ad-hoc parsing later. Keep payload as a string (we still need custom 0x handling). This mirrors prior feedback.

Apply this refactor (fields only):

-        /// Test Transaction `to` address
-        #[arg(long)]
-        to: String,
-        /// Test Transaction `from` address
-        #[arg(long)]
-        from: String,
+        /// Test Transaction `to` address (delegated f4)
+        #[arg(long)]
+        to: Address,
+        /// Test Transaction `from` address (delegated f4)
+        #[arg(long)]
+        from: Address,
@@
-        /// Log `topic` to search for
-        #[arg(long)]
-        topic: String,
+        /// Log `topic` (32‑byte Keccak hash) to search for
+        #[arg(long)]
+        topic: EthHash,

If you adopt this, the manual Address::from_str/EthHash::from_str calls in the match arm can be dropped (see follow-up diff in Lines 401‑423). Also, you can remove the unused use std::str::FromStr; import (Line 30).


401-423: Add user-friendly parse context, accept 0x‑prefixed payloads, and improve FULLNODE_API_INFO error

  • Wrap default_or_from_env with context to guide users when the env var is missing/invalid.
  • Accept “0x…” payloads by stripping the prefix before hex::decode.
  • Add with_context on parse errors for clearer CLI UX.
  • Pass client directly (already done; no clone needed).

Minimal, backward-compatible patch:

             } => {
-                let client = Arc::new(rpc::Client::default_or_from_env(None)?);
+                let client = Arc::new(
+                    rpc::Client::default_or_from_env(None)
+                        .with_context(|| "failed to initialize RPC client (set FULLNODE_API_INFO or ensure a node is listening on http://127.0.0.1:2345/)")?
+                );
 
-                let to = Address::from_str(&to)?;
-                let from = Address::from_str(&from)?;
-                let payload = hex::decode(payload)?;
-                let topic = EthHash::from_str(&topic)?;
+                let to = Address::from_str(&to)
+                    .with_context(|| format!("invalid --to address: {to}"))?;
+                let from = Address::from_str(&from)
+                    .with_context(|| format!("invalid --from address: {from}"))?;
+                let payload = {
+                    let clean = payload.strip_prefix("0x").unwrap_or(&payload);
+                    hex::decode(clean)
+                        .with_context(|| format!("invalid --payload hex: {payload}"))?
+                };
+                let topic = EthHash::from_str(&topic)
+                    .with_context(|| format!("invalid --topic (expect 0x‑prefixed 32‑byte hash): {topic}"))?;
 
                 let tx = TestTransaction {
                     to,
                     from,
                     payload,
                     topic,
                 };
 
                 let tests = stateful_tests::create_tests(tx).await;
                 stateful_tests::run_tests(tests, client, filter).await?;
             }

If you adopt typed clap fields (Lines 236‑252), simplify this arm further:

-                let to = Address::from_str(&to)
-                    .with_context(|| format!("invalid --to address: {to}"))?;
-                let from = Address::from_str(&from)
-                    .with_context(|| format!("invalid --from address: {from}"))?;
-                let payload = {
+                let payload = {
                     let clean = payload.strip_prefix("0x").unwrap_or(&payload);
                     hex::decode(clean)
                         .with_context(|| format!("invalid --payload hex: {payload}"))?
                 };
-                let topic = EthHash::from_str(&topic)
-                    .with_context(|| format!("invalid --topic (expect 0x‑prefixed 32‑byte hash): {topic}"))?;
 
                 let tx = TestTransaction {
-                    to,
-                    from,
+                    to,   // already Address
+                    from, // already Address
                     payload,
-                    topic,
+                    topic, // already EthHash
                 };
🧹 Nitpick comments (3)
src/tool/subcommands/api_cmd.rs (3)

208-235: Tighten docs: clarify connection fallback, input formats, and filter semantics

  • Mention the default fallback when FULLNODE_API_INFO is not set (http://127.0.0.1:2345/).
  • Call out that hex inputs commonly include a “0x” prefix and whether it’s accepted.
  • Clarify that --filter does a prefix match (starts_with), not substring.
  • The “all ok (7 passed)” example doesn’t reflect current ignores/expected failures; either add a disclaimer or show a realistic mixed/ignored output.

Apply this doc-only diff:

-    /// Connection: uses `FULLNODE_API_INFO` from the environment.
+    /// Connection: uses `FULLNODE_API_INFO` from the environment; falls back to http://127.0.0.1:2345/.
@@
-    /// - `--payload`: calldata in hex
-    /// - `--topic`: `32‑byte` event topic in hex
-    /// - `--filter`: run only tests that interact with a specific RPC method
+    /// - `--payload`: calldata in hex (accept “0x” prefix or raw hex)
+    /// - `--topic`: 32‑byte event topic in hex (e.g., 0x…)
+    /// - `--filter`: run only tests whose method name starts with this string (case sensitive)
@@
-    /// Example output:
+    /// Example output (results may include ignored or expected failures, depending on node):
@@
-    /// test eth_newFilter over limit ... ok
+    /// test eth_newFilter over limit ... ignored
@@
-    /// test eth_newPendingTransactionFilter works ... ok
-    /// test eth_getFilterLogs works ... ok
-    /// test result: ok. 7 passed; 0 failed; 0 ignored; 0 filtered out
+    /// test eth_newPendingTransactionFilter works ... ignored
+    /// test eth_getFilterLogs works ... ignored
+    /// test result: ok. 4 passed; 0 failed; 3 ignored; 0 filtered out

30-30: use std::str::FromStr; likely unnecessary if clap parses typed args

If you move to typed clap fields for to, from, and topic, this import can be removed.

-use std::str::FromStr;

208-252: Optional: make payload optional to ease running filter-only tests

Right now users must provide --payload even when running, e.g., --filter EthNewBlockFilter, which doesn’t require tx data. Consider Option<String> and validate only when a test needs it. Happy to draft if desired.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b63f1bd and 87e33de.

📒 Files selected for processing (2)
  • .config/forest.dic (2 hunks)
  • src/tool/subcommands/api_cmd.rs (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/tool/subcommands/api_cmd.rs (4)
src/rpc/client.rs (2)
  • client (114-114)
  • default_or_from_env (46-77)
src/rpc/methods/eth.rs (13)
  • new (512-524)
  • new (677-682)
  • from_str (262-264)
  • from_str (370-381)
  • from_str (430-449)
  • from (136-138)
  • from (142-144)
  • from (268-271)
  • from (275-277)
  • filter (3101-3101)
  • filter (3151-3151)
  • filter (3176-3176)
  • filter (3208-3208)
src/shim/address.rs (2)
  • from_str (178-183)
  • from_str (299-302)
src/tool/subcommands/api_cmd/stateful_tests.rs (2)
  • create_tests (606-655)
  • run_tests (91-168)
⏰ 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). (9)
  • GitHub Check: Build forest binaries on Linux AMD64
  • GitHub Check: tests
  • GitHub Check: tests-release
  • GitHub Check: All lint checks
  • GitHub Check: cargo-publish-dry-run
  • GitHub Check: Build MacOS
  • GitHub Check: Build Ubuntu
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
.config/forest.dic (2)

19-19: Add “calldata” to dictionary — LGTM

Correct Ethereum term; avoids false-positive spellcheck hits in docs and code comments.


55-55: Add “f4” to dictionary — LGTM

Matches delegated Filecoin address prefix used in the new CLI docs.

src/tool/subcommands/api_cmd.rs (2)

7-7: New stateful_tests module inclusion — LGTM

Modularizing the stateful suite keeps api_cmd tidy.


21-21: Import of TestTransaction — LGTM

Narrow import is clear and localizes the test harness dependency.

@LesnyRumcajs
Copy link
Member

LesnyRumcajs commented Aug 26, 2025

the stateful check is failing! no review! Let's ensure it's not flaky.

@elmattic elmattic marked this pull request as draft August 26, 2025 09:25
@elmattic elmattic marked this pull request as ready for review August 26, 2025 12: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

♻️ Duplicate comments (2)
scripts/tests/harness.sh (2)

127-135: Backfill path should wait for full healthcheck readiness to avoid flaky stateful tests

Per team learnings, when backfilling you should wait for “healthcheck ready” (not just API up/sync) before running tests that depend on completed DB backfill.

Add this guard near the end of forest_init after sync (outside the changed hunk, shown here as a plain snippet):

# After forest_wait_for_sync
if [[ "${1:-}" == "--backfill-db" ]]; then
  forest_wait_for_healthcheck_ready
fi

143-147: Fail fast on missing token, trim newline, and avoid overriding FULLNODE_API_INFO unless necessary

Right now, if the token file is missing/empty, you’ll silently export an auth-less FULLNODE_API_INFO and the client will not fall back to the default token loader, causing 401s. Also, most token files end with a newline, which will break auth unless trimmed.

Apply this diff to make the block robust and cwd-agnostic while keeping the env override opt-in:

-  DATA_DIR=$( $FOREST_CLI_PATH config dump | grep "data_dir" | cut -d' ' -f3- | tr -d '"' )
-  ADMIN_TOKEN=$(cat "${DATA_DIR}/token")
-  FULLNODE_API_INFO="${ADMIN_TOKEN}:/ip4/127.0.0.1/tcp/2345/http"
-
-  export FULLNODE_API_INFO
+  # Prefer default token path resolution in forest-tool; only export FULLNODE_API_INFO if not already provided.
+  if [[ -z "${FULLNODE_API_INFO:-}" ]]; then
+    DATA_DIR=$($FOREST_CLI_PATH config dump | grep "data_dir" | cut -d' ' -f3- | tr -d '"')
+    TOKEN_FILE="${DATA_DIR}/token"
+    if [[ ! -s "$TOKEN_FILE" ]]; then
+      echo "ERROR: RPC token file missing or empty at: $TOKEN_FILE" >&2
+      return 1
+    fi
+    # Trim trailing newline to avoid an invalid password
+    ADMIN_TOKEN="$(tr -d '\n' < "$TOKEN_FILE")"
+    export FULLNODE_API_INFO="${ADMIN_TOKEN}:/ip4/127.0.0.1/tcp/2345/http"
+  fi
🧹 Nitpick comments (1)
src/tool/subcommands/api_cmd.rs (1)

207-251: Tighten docs: connection fallback and filter semantics

  • Clarify that connection falls back to 127.0.0.1:2345 + default token file when FULLNODE_API_INFO is not set (matches rpc::Client::default_or_from_env).
  • Be explicit that filter uses a case-sensitive prefix match (matches run_tests).

Apply this doc tweak:

-    /// Connection: uses `FULLNODE_API_INFO` from the environment.
+    /// Connection: uses `FULLNODE_API_INFO` from the environment, or falls back to
+    /// `http://127.0.0.1:2345` with the default token file if unset.
@@
-    /// - `--topic`: `32‑byte` event topic in hex
-    /// - `--filter`: run only tests that interact with a specific RPC method
+    /// - `--topic`: `32‑byte` event topic in hex (expects 0x‑prefixed)
+    /// - `--filter`: run only tests whose method name starts with this string (prefix, case sensitive)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5bca9bb and 1e3e088.

📒 Files selected for processing (3)
  • scripts/tests/calibnet_api_test_stateful_check.sh (1 hunks)
  • scripts/tests/harness.sh (1 hunks)
  • src/tool/subcommands/api_cmd.rs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/tests/calibnet_api_test_stateful_check.sh
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-07T09:37:03.079Z
Learnt from: hanabi1224
PR: ChainSafe/forest#5886
File: scripts/tests/calibnet_eth_mapping_check.sh:49-49
Timestamp: 2025-08-07T09:37:03.079Z
Learning: In Forest project scripts, `forest_wait_api` (called within `forest_init`) ensures basic RPC service readiness, while `forest_wait_for_healthcheck_ready` performs additional comprehensive checks including DB backfill completion. When using `--backfill-db` flag, basic RPC operations can proceed after `forest_init`, but operations requiring complete DB backfill should wait for `forest_wait_for_healthcheck_ready`.

Applied to files:

  • scripts/tests/harness.sh
🧬 Code graph analysis (1)
src/tool/subcommands/api_cmd.rs (2)
src/rpc/client.rs (2)
  • client (114-114)
  • default_or_from_env (46-77)
src/tool/subcommands/api_cmd/stateful_tests.rs (2)
  • create_tests (606-655)
  • run_tests (91-168)
⏰ 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: tests
  • GitHub Check: tests-release
  • GitHub Check: Build forest binaries on Linux AMD64
🔇 Additional comments (2)
src/tool/subcommands/api_cmd.rs (2)

7-7: Module wiring LGTM

The new stateful_tests module and TestTransaction import are cleanly integrated.

Also applies to: 21-21


400-423: Add context to RPC client construction error

The suggested minimal change enriches the error message when constructing the RPC client, guiding users to check their environment variables and node connection.

• File – src/tool/subcommands/api_cmd.rs
• Section – the Self::TestStateful arm around line 410

Apply this diff:

-                let client = Arc::new(rpc::Client::default_or_from_env(None)?);
+                let client = Arc::new(
+                    rpc::Client::default_or_from_env(None)
+                        .context("failed to construct RPC client: ensure FULLNODE_API_INFO is valid, the default token file is accessible, and a node is running at 127.0.0.1:2345")?
+                );

Optional follow-up: if the stateful tests require only Delegated addresses, validate the transaction’s from and to protocols via Address::protocol() and return an early error. Since Protocol is re-exported from the external fvm_shared4 crate, please verify it includes a Delegated variant before implementing this check.

@elmattic elmattic requested a review from hanabi1224 August 26, 2025 13:20
@elmattic elmattic added this pull request to the merge queue Aug 26, 2025
Merged via the queue into main with commit e916897 Aug 26, 2025
60 checks passed
@elmattic elmattic deleted the elmattic/api-run-subcommand branch August 26, 2025 14:34
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.

Add test coverage for filter-related Ethereum API methods

5 participants