From 7e3dfaed9f154d318c7a02abe4106470e955257c Mon Sep 17 00:00:00 2001 From: Shashank Date: Thu, 22 Jan 2026 23:00:05 +0530 Subject: [PATCH 1/6] Impl eth_getTransactionByBlockNumberAndIndex V2 --- src/rpc/methods/eth.rs | 67 +++++++++++++++---- src/rpc/mod.rs | 1 + .../subcommands/api_cmd/api_compare_tests.rs | 40 +++++++++++ 3 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 721352189c68..e88ad202bc44 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -2599,6 +2599,8 @@ impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndex { const PARAM_NAMES: [&'static str; 2] = ["blockParam", "txIndex"]; const API_PATHS: BitFlags = ApiPaths::all(); const PERMISSION: Permission = Permission::Read; + const DESCRIPTION: Option<&'static str> = + Some("Retrieves a transaction by its block number and index."); type Params = (BlockNumberOrPredefined, EthUint64); type Ok = Option; @@ -2612,11 +2614,49 @@ impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndex { block_param.into(), ResolveNullTipset::TakeOlder, )?; + eth_tx_by_block_num_and_idx(&ctx, &ts, tx_index) + } +} - let messages = ctx.chain_store().messages_for_tipset(&ts)?; +pub enum EthGetTransactionByBlockNumberAndIndexV2 {} +impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndexV2 { + const NAME: &'static str = "Filecoin.EthGetTransactionByBlockNumberAndIndex"; + const NAME_ALIAS: Option<&'static str> = Some("eth_getTransactionByBlockNumberAndIndex"); + const PARAM_NAMES: [&'static str; 2] = ["blockParam", "txIndex"]; + const API_PATHS: BitFlags = make_bitflags!(ApiPaths::V2); + const PERMISSION: Permission = Permission::Read; + const DESCRIPTION: Option<&'static str> = + Some("Retrieves a transaction by its block number and index."); - let EthUint64(index) = tx_index; - let msg = messages.get(index as usize).with_context(|| { + type Params = (BlockNumberOrPredefined, EthUint64); + type Ok = Option; + + async fn handle( + ctx: Ctx, + (block_param, tx_index): Self::Params, + ) -> Result { + let ts = tipset_by_block_number_or_hash_v2( + &ctx, + block_param.into(), + ResolveNullTipset::TakeOlder, + ) + .await?; + eth_tx_by_block_num_and_idx(&ctx, &ts, tx_index) + } +} + +fn eth_tx_by_block_num_and_idx( + ctx: &Ctx, + ts: &Tipset, + tx_index: EthUint64, +) -> Result, ServerError> +where + B: Blockstore + Send + Sync + 'static, +{ + let messages = ctx.chain_store().messages_for_tipset(&ts)?; + + let EthUint64(index) = tx_index; + let msg = messages.get(index as usize).with_context(|| { format!( "failed to get transaction at index {}: index {} out of range: tipset contains {} messages", index, @@ -2625,19 +2665,18 @@ impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndex { ) })?; - let state = StateTree::new_from_root(ctx.store_owned(), ts.parent_state())?; + let state = StateTree::new_from_root(ctx.store_owned(), ts.parent_state())?; - let tx = new_eth_tx( - &ctx, - &state, - ts.epoch(), - &ts.key().cid()?, - &msg.cid(), - index, - )?; + let tx = new_eth_tx( + &ctx, + &state, + ts.epoch(), + &ts.key().cid()?, + &msg.cid(), + index, + )?; - Ok(Some(tx)) - } + Ok(Some(tx)) } pub enum EthGetTransactionByBlockHashAndIndex {} diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 7244acf2f659..ac33fd46d03f 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -131,6 +131,7 @@ macro_rules! for_each_rpc_method { $callback!($crate::rpc::eth::EthGetTransactionCountV2); $callback!($crate::rpc::eth::EthGetTransactionHashByCid); $callback!($crate::rpc::eth::EthGetTransactionByBlockNumberAndIndex); + $callback!($crate::rpc::eth::EthGetTransactionByBlockNumberAndIndexV2); $callback!($crate::rpc::eth::EthGetTransactionByBlockHashAndIndex); $callback!($crate::rpc::eth::EthMaxPriorityFeePerGas); $callback!($crate::rpc::eth::EthProtocolVersion); diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index 9fdf04507358..bce1f4c47a4e 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -2126,6 +2126,46 @@ fn eth_tests_with_tipset(store: &Arc, shared_tipset: &Tipset .unwrap(), ) .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), + RpcTest::identity( + EthGetTransactionByBlockNumberAndIndex::request(( + BlockNumberOrPredefined::PredefinedBlock(ExtPredefined::Pending), + 0.into(), + )) + .unwrap(), + ) + .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), + RpcTest::identity( + EthGetTransactionByBlockNumberAndIndex::request(( + BlockNumberOrPredefined::PredefinedBlock(ExtPredefined::Latest), + 0.into(), + )) + .unwrap(), + ) + .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), + RpcTest::identity( + EthGetTransactionByBlockNumberAndIndexV2::request(( + BlockNumberOrPredefined::BlockNumber(shared_tipset.epoch().into()), + 0.into(), + )) + .unwrap(), + ) + .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), + RpcTest::identity( + EthGetTransactionByBlockNumberAndIndexV2::request(( + BlockNumberOrPredefined::PredefinedBlock(ExtPredefined::Safe), + 0.into(), + )) + .unwrap(), + ) + .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), + RpcTest::identity( + EthGetTransactionByBlockNumberAndIndexV2::request(( + BlockNumberOrPredefined::PredefinedBlock(ExtPredefined::Finalized), + 0.into(), + )) + .unwrap(), + ) + .policy_on_rejected(PolicyOnRejected::PassWithQuasiIdenticalError), RpcTest::identity( EthGetTransactionByBlockHashAndIndex::request((block_hash.clone(), 0.into())).unwrap(), ) From edc8f259a090d756733f5f01cfac003065fc05e5 Mon Sep 17 00:00:00 2001 From: Shashank Date: Thu, 22 Jan 2026 23:30:10 +0530 Subject: [PATCH 2/6] Add test snapshots --- src/tool/subcommands/api_cmd/test_snapshots.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index 4981fbc872bd..3bc9ec6601a7 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -77,6 +77,11 @@ filecoin_ethgetstorageat_1765803742046844.rpcsnap.json.zst # concrete filecoin_ethgetstorageat_1765803742145789.rpcsnap.json.zst # pending filecoin_ethgettransactionbyblockhashandindex_1740132538373654.rpcsnap.json.zst filecoin_ethgettransactionbyblocknumberandindex_1740132538304408.rpcsnap.json.zst +filecoin_ethgettransactionbyblocknumberandindex_latest_1769103643171646.rpcsnap.json.zst +filecoin_ethgettransactionbyblocknumberandindex_pending_1769103643171774.rpcsnap.json.zst +filecoin_ethgettransactionbyblocknumberandindex_v2_1769103643172125.rpcsnap.json.zst +filecoin_ethgettransactionbyblocknumberandindex_v2_finalized_1769103643184069.rpcsnap.json.zst +filecoin_ethgettransactionbyblocknumberandindex_v2_safe_1769103643174698.rpcsnap.json.zst filecoin_ethgettransactionbyhash_1741272955520821.rpcsnap.json.zst filecoin_ethgettransactionbyhashlimited_1741272955509708.rpcsnap.json.zst filecoin_ethgettransactioncount_1740132538183426.rpcsnap.json.zst From aa557092f84ae008d7f6a7e78b31f7780bd0eed0 Mon Sep 17 00:00:00 2001 From: Shashank Date: Thu, 22 Jan 2026 23:35:46 +0530 Subject: [PATCH 3/6] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 329e68977c0f..4d4a1506335a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,8 @@ - [#6421](https://github.com/ChainSafe/forest/pull/6421) Add an environment variable `FOREST_RPC_BACKFILL_FULL_TIPSET_FROM_NETWORK` to enable backfilling full tipsets from network in a few RPC methods. +- [#6469](https://github.com/ChainSafe/forest/pull/6469) Implemented `Filecoin.EthGetTransactionByBlockNumberAndIndex` for API v2. + ### Changed - [#6368](https://github.com/ChainSafe/forest/pull/6368): Migrated build and development tooling from Makefile to `mise`. Contributors should install `mise` and use `mise run` commands instead of `make` commands. From 7e1355398a50bab3aea12c9be68e2cce77ee5b2b Mon Sep 17 00:00:00 2001 From: Shashank Date: Fri, 23 Jan 2026 00:06:53 +0530 Subject: [PATCH 4/6] lint fix --- src/rpc/methods/eth.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index e88ad202bc44..2ad8d0f05bd0 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -2653,7 +2653,7 @@ fn eth_tx_by_block_num_and_idx( where B: Blockstore + Send + Sync + 'static, { - let messages = ctx.chain_store().messages_for_tipset(&ts)?; + let messages = ctx.chain_store().messages_for_tipset(ts)?; let EthUint64(index) = tx_index; let msg = messages.get(index as usize).with_context(|| { @@ -2667,14 +2667,7 @@ where let state = StateTree::new_from_root(ctx.store_owned(), ts.parent_state())?; - let tx = new_eth_tx( - &ctx, - &state, - ts.epoch(), - &ts.key().cid()?, - &msg.cid(), - index, - )?; + let tx = new_eth_tx(ctx, &state, ts.epoch(), &ts.key().cid()?, &msg.cid(), index)?; Ok(Some(tx)) } From 172cec0d979cb9645c66819a9e81a8d71c34d754 Mon Sep 17 00:00:00 2001 From: Shashank Date: Fri, 23 Jan 2026 00:51:24 +0530 Subject: [PATCH 5/6] filter from offline check --- scripts/tests/api_compare/filter-list-offline | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/tests/api_compare/filter-list-offline b/scripts/tests/api_compare/filter-list-offline index 50f62a6f7fe1..e2f2c4f6341c 100644 --- a/scripts/tests/api_compare/filter-list-offline +++ b/scripts/tests/api_compare/filter-list-offline @@ -26,4 +26,6 @@ # Offline server won't provide correct results for finality-related methods !Filecoin.EthGetBlockByNumber !eth_getBlockByNumber +!Filecoin.EthGetTransactionByBlockNumberAndIndex +!eth_getTransactionByBlockNumberAndIndex !Filecoin.ChainSetHead From d7f2d588f9a85d8e56626490641a43cae6ddd085 Mon Sep 17 00:00:00 2001 From: Shashank Date: Fri, 23 Jan 2026 10:34:04 +0530 Subject: [PATCH 6/6] update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b4545846a6e..ff2e89527b35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ ### Added +- [#6469](https://github.com/ChainSafe/forest/pull/6469) Implemented `Filecoin.EthGetTransactionByBlockNumberAndIndex` for API v2. + ### Changed ### Removed @@ -59,8 +61,6 @@ This is a non-mandatory release for all node operators. It includes the support - [#6444](https://github.com/ChainSafe/forest/pull/6444) Implemented `Filecoin.EthTraceReplayBlockTransactions` for API v2. -- [#6469](https://github.com/ChainSafe/forest/pull/6469) Implemented `Filecoin.EthGetTransactionByBlockNumberAndIndex` for API v2. - ### Changed - [#6368](https://github.com/ChainSafe/forest/pull/6368): Migrated build and development tooling from Makefile to `mise`. Contributors should install `mise` and use `mise run` commands instead of `make` commands.