From aa09f1219a62fb5b06190ce0b6ea79076d78c9b0 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Tue, 9 Dec 2025 22:41:58 +0800 Subject: [PATCH 1/6] feat(rpc): add v1 RPC method `Filecoin.FilecoinAddressToEthAddress` --- src/rpc/methods/eth.rs | 37 +++++++++++++++++++++++++++++++++++-- src/rpc/mod.rs | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 650426c05ac4..cfe2bd389d79 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -2747,11 +2747,11 @@ impl RpcMethod<0> for EthSubscribe { pub enum EthAddressToFilecoinAddress {} impl RpcMethod<1> for EthAddressToFilecoinAddress { const NAME: &'static str = "Filecoin.EthAddressToFilecoinAddress"; - const NAME_ALIAS: Option<&'static str> = None; - const N_REQUIRED_PARAMS: usize = 1; const PARAM_NAMES: [&'static str; 1] = ["ethAddress"]; const API_PATHS: BitFlags = ApiPaths::all_with_v2(); const PERMISSION: Permission = Permission::Read; + const DESCRIPTION: Option<&'static str> = + Some("Converts an EthAddress into an f410 Filecoin Address"); type Params = (EthAddress,); type Ok = FilecoinAddress; async fn handle( @@ -2762,6 +2762,39 @@ impl RpcMethod<1> for EthAddressToFilecoinAddress { } } +pub enum FilecoinAddressToEthAddress {} +impl RpcMethod<2> for FilecoinAddressToEthAddress { + const NAME: &'static str = "Filecoin.FilecoinAddressToEthAddress"; + const N_REQUIRED_PARAMS: usize = 1; + const PARAM_NAMES: [&'static str; 2] = ["filecoinAddress", "blockParam"]; + const API_PATHS: BitFlags = ApiPaths::all_with_v2(); + const PERMISSION: Permission = Permission::Read; + const DESCRIPTION: Option<&'static str> = + Some("Converts any Filecoin address to an EthAddress"); + type Params = (FilecoinAddress, Option); + type Ok = EthAddress; + async fn handle( + ctx: Ctx, + (address, block_param): Self::Params, + ) -> Result { + if let Ok(eth_address) = EthAddress::from_filecoin_address(&address) { + Ok(eth_address) + } else { + let block_param = block_param.unwrap_or(BlockNumberOrPredefined::PredefinedBlock( + ExtPredefined::Finalized, + )); + let ts = tipset_by_ext_block_number_or_hash( + ctx.chain_store(), + block_param.into(), + ResolveNullTipset::TakeOlder, + )?; + + let id_address = ctx.state_manager.lookup_required_id(&address, &ts)?; + Ok(EthAddress::from_filecoin_address(&id_address)?) + } + } +} + async fn get_eth_transaction_receipt( ctx: Ctx, tx_hash: EthHash, diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index c02678ae30bf..be1c06dc45ae 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -98,6 +98,7 @@ macro_rules! for_each_rpc_method { // eth vertical $callback!($crate::rpc::eth::EthAccounts); $callback!($crate::rpc::eth::EthAddressToFilecoinAddress); + $callback!($crate::rpc::eth::FilecoinAddressToEthAddress); $callback!($crate::rpc::eth::EthBlockNumber); $callback!($crate::rpc::eth::EthCall); $callback!($crate::rpc::eth::EthChainId); From 25eb2f99393512be44d634e5f246fef0b3cfdf4d Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Tue, 9 Dec 2025 22:54:59 +0800 Subject: [PATCH 2/6] tests --- .../subcommands/api_cmd/api_compare_tests.rs | 16 ++++++++++++---- src/tool/subcommands/api_cmd/test_snapshots.txt | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index 19a073232ccf..acd1d04c10cc 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -1456,10 +1456,18 @@ fn eth_tests() -> Vec { EthUninstallFilter::request_with_alias((FilterID::new().unwrap(),), use_alias).unwrap(), )); tests.push(RpcTest::identity( - EthAddressToFilecoinAddress::request((EthAddress::from_str( - "0xff38c072f286e3b20b3954ca9f99c05fbecc64aa", - ) - .unwrap(),)) + EthAddressToFilecoinAddress::request(("0xff38c072f286e3b20b3954ca9f99c05fbecc64aa" + .parse() + .unwrap(),)) + .unwrap(), + )); + tests.push(RpcTest::identity( + FilecoinAddressToEthAddress::request(( + "t410f744ma4xsq3r3eczzktfj7goal67myzfkusna2hy" + .parse() + .unwrap(), + None, + )) .unwrap(), )); } diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index 1d654beee276..63a783a7eae3 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -92,6 +92,7 @@ filecoin_evm_getstorageat_statedecodeparams_1755619756266970.rpcsnap.json.zst filecoin_evm_invokecontract_statedecodeparams_1755004924714521.rpcsnap.json.zst filecoin_evm_invokecontractdelegate_statedecodeparams_1755004924714578.rpcsnap.json.zst filecoin_evm_resurrect_statedecodeparams_1755004924714636.rpcsnap.json.zst +filecoin_filecoinaddresstoethaddress_1765291874419799.rpcsnap.json.zst filecoin_gasestimategaslimit_1741782110512299.rpcsnap.json.zst filecoin_getactoreventsraw_1741782590255476.rpcsnap.json.zst filecoin_market_addbalance_statedecodeparams_1757426002278914.rpcsnap.json.zst From d1dc6cc4fe2b7879146889b2cd32f064a838f60d Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Tue, 9 Dec 2025 22:56:22 +0800 Subject: [PATCH 3/6] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67790329ead6..e0b54e6116cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ - [#6312](https://github.com/ChainSafe/forest/pull/6312) Implemented `Filecoin.StateGetID` for API v2. +- [#6323](https://github.com/ChainSafe/forest/pull/6323) Implemented `Filecoin.FilecoinAddressToEthAddress` for API v1 and v2. + ### Changed ### Removed From c5e17b0e3249514937b9cfb2aca1453c3b15082f Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 10 Dec 2025 17:16:48 +0800 Subject: [PATCH 4/6] more tests --- .../subcommands/api_cmd/api_compare_tests.rs | 18 ++++++++++++++++++ .../subcommands/api_cmd/test_snapshots.txt | 1 + 2 files changed, 19 insertions(+) diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index acd1d04c10cc..b97646878e2c 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -1944,9 +1944,27 @@ fn eth_tests_with_tipset(store: &Arc, shared_tipset: &Tipset ]; for block in shared_tipset.block_headers() { + tests.extend([RpcTest::identity( + FilecoinAddressToEthAddress::request(( + block.miner_address, + Some(BlockNumberOrPredefined::PredefinedBlock( + ExtPredefined::Latest, + )), + )) + .unwrap(), + )]); let (bls_messages, secp_messages) = crate::chain::store::block_messages(store, block).unwrap(); for msg in sample_messages(bls_messages.iter(), secp_messages.iter()) { + tests.extend([RpcTest::identity( + FilecoinAddressToEthAddress::request(( + msg.from(), + Some(BlockNumberOrPredefined::PredefinedBlock( + ExtPredefined::Latest, + )), + )) + .unwrap(), + )]); if let Ok(eth_to_addr) = msg.to.try_into() { tests.extend([RpcTest::identity( EthEstimateGas::request(( diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index 63a783a7eae3..222f4177df00 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -93,6 +93,7 @@ filecoin_evm_invokecontract_statedecodeparams_1755004924714521.rpcsnap.json.zst filecoin_evm_invokecontractdelegate_statedecodeparams_1755004924714578.rpcsnap.json.zst filecoin_evm_resurrect_statedecodeparams_1755004924714636.rpcsnap.json.zst filecoin_filecoinaddresstoethaddress_1765291874419799.rpcsnap.json.zst +filecoin_filecoinaddresstoethaddress_1765357908887069.rpcsnap.json.zst filecoin_gasestimategaslimit_1741782110512299.rpcsnap.json.zst filecoin_getactoreventsraw_1741782590255476.rpcsnap.json.zst filecoin_market_addbalance_statedecodeparams_1757426002278914.rpcsnap.json.zst From 602376a0ff4eaf6f1dcf2d081f1737e0cc4c8377 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 10 Dec 2025 18:04:42 +0800 Subject: [PATCH 5/6] comments on rpc test snapshots --- build.rs | 5 ++++- src/tool/subcommands/api_cmd/test_snapshot.rs | 2 ++ src/tool/subcommands/api_cmd/test_snapshots.txt | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index 8fcccb6ddda4..8d6dd5d27d97 100644 --- a/build.rs +++ b/build.rs @@ -60,7 +60,10 @@ fn rpc_regression_tests_gen() { let tests: Vec<&str> = include_str!("src/tool/subcommands/api_cmd/test_snapshots.txt") .lines() - .map(str::trim) + .map(|i| { + // Remove comment + i.split("#").next().unwrap().trim() + }) .filter(|l| !l.is_empty() && !l.starts_with('#')) .collect(); let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); diff --git a/src/tool/subcommands/api_cmd/test_snapshot.rs b/src/tool/subcommands/api_cmd/test_snapshot.rs index e118341762bc..b47bb6448613 100644 --- a/src/tool/subcommands/api_cmd/test_snapshot.rs +++ b/src/tool/subcommands/api_cmd/test_snapshot.rs @@ -260,6 +260,8 @@ mod tests { .trim() .split("\n") .map(|i| { + // Remove comment + let i = i.split("#").next().unwrap().trim(); let captures = pattern.captures(i).expect("pattern capture failure"); captures .name("name") diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index 222f4177df00..c1fda1cee376 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -92,8 +92,8 @@ filecoin_evm_getstorageat_statedecodeparams_1755619756266970.rpcsnap.json.zst filecoin_evm_invokecontract_statedecodeparams_1755004924714521.rpcsnap.json.zst filecoin_evm_invokecontractdelegate_statedecodeparams_1755004924714578.rpcsnap.json.zst filecoin_evm_resurrect_statedecodeparams_1755004924714636.rpcsnap.json.zst -filecoin_filecoinaddresstoethaddress_1765291874419799.rpcsnap.json.zst -filecoin_filecoinaddresstoethaddress_1765357908887069.rpcsnap.json.zst +filecoin_filecoinaddresstoethaddress_1765291874419799.rpcsnap.json.zst # F4 address +filecoin_filecoinaddresstoethaddress_1765357908887069.rpcsnap.json.zst # F0 address filecoin_gasestimategaslimit_1741782110512299.rpcsnap.json.zst filecoin_getactoreventsraw_1741782590255476.rpcsnap.json.zst filecoin_market_addbalance_statedecodeparams_1757426002278914.rpcsnap.json.zst From 8867ae125cbc38ce26f052607188f0022df1dd7b Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 10 Dec 2025 18:56:30 +0800 Subject: [PATCH 6/6] more tests --- .../subcommands/api_cmd/api_compare_tests.rs | 66 +++++++++++++++---- .../subcommands/api_cmd/test_snapshots.txt | 3 + 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index b97646878e2c..d2919a373ecd 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -87,6 +87,42 @@ static KNOWN_EMPTY_CALIBNET_ADDRESS: LazyLock
= LazyLock::new(|| { .into() }); +// this is the ID address of the `t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly` address +static KNOWN_CALIBNET_F0_ADDRESS: LazyLock
= LazyLock::new(|| { + crate::shim::address::Network::Testnet + .parse_address("t0168923") + .unwrap() + .into() +}); + +static KNOWN_CALIBNET_F1_ADDRESS: LazyLock
= LazyLock::new(|| { + crate::shim::address::Network::Testnet + .parse_address("t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly") + .unwrap() + .into() +}); + +static KNOWN_CALIBNET_F2_ADDRESS: LazyLock
= LazyLock::new(|| { + crate::shim::address::Network::Testnet + .parse_address("t2nfplhzpyeck5dcc4fokj5ar6nbs3mhbdmq6xu3q") + .unwrap() + .into() +}); + +static KNOWN_CALIBNET_F3_ADDRESS: LazyLock
= LazyLock::new(|| { + crate::shim::address::Network::Testnet + .parse_address("t3wmbvnabsj6x2uki33phgtqqemmunnttowpx3chklrchy76pv52g5ajnaqdypxoomq5ubfk65twl5ofvkhshq") + .unwrap() + .into() +}); + +static KNOWN_CALIBNET_F4_ADDRESS: LazyLock
= LazyLock::new(|| { + crate::shim::address::Network::Testnet + .parse_address("t410fx2cumi6pgaz64varl77xbuub54bgs3k5xsvn3ki") + .unwrap() + .into() +}); + const TICKET_QUALITY_GREEDY: f64 = 0.9; const TICKET_QUALITY_OPTIMAL: f64 = 0.8; const ZERO_ADDRESS: &str = "0x0000000000000000000000000000000000000000"; @@ -1255,11 +1291,11 @@ fn state_tests_with_tipset( fn wallet_tests(worker_address: Option
) -> Vec { let prefunded_wallets = [ // the following addresses should have 666 attoFIL each - Address::from_str("t0168923").unwrap(), // this is the ID address of the `t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly` address - Address::from_str("t1w2zb5a723izlm4q3khclsjcnapfzxcfhvqyfoly").unwrap(), - Address::from_str("t2nfplhzpyeck5dcc4fokj5ar6nbs3mhbdmq6xu3q").unwrap(), - Address::from_str("t3wmbvnabsj6x2uki33phgtqqemmunnttowpx3chklrchy76pv52g5ajnaqdypxoomq5ubfk65twl5ofvkhshq").unwrap(), - Address::from_str("t410fx2cumi6pgaz64varl77xbuub54bgs3k5xsvn3ki").unwrap(), + *KNOWN_CALIBNET_F0_ADDRESS, + *KNOWN_CALIBNET_F1_ADDRESS, + *KNOWN_CALIBNET_F2_ADDRESS, + *KNOWN_CALIBNET_F3_ADDRESS, + *KNOWN_CALIBNET_F4_ADDRESS, // This address should have 0 FIL *KNOWN_EMPTY_CALIBNET_ADDRESS, ]; @@ -1462,13 +1498,19 @@ fn eth_tests() -> Vec { .unwrap(), )); tests.push(RpcTest::identity( - FilecoinAddressToEthAddress::request(( - "t410f744ma4xsq3r3eczzktfj7goal67myzfkusna2hy" - .parse() - .unwrap(), - None, - )) - .unwrap(), + FilecoinAddressToEthAddress::request((*KNOWN_CALIBNET_F0_ADDRESS, None)).unwrap(), + )); + tests.push(RpcTest::identity( + FilecoinAddressToEthAddress::request((*KNOWN_CALIBNET_F1_ADDRESS, None)).unwrap(), + )); + tests.push(RpcTest::identity( + FilecoinAddressToEthAddress::request((*KNOWN_CALIBNET_F2_ADDRESS, None)).unwrap(), + )); + tests.push(RpcTest::identity( + FilecoinAddressToEthAddress::request((*KNOWN_CALIBNET_F3_ADDRESS, None)).unwrap(), + )); + tests.push(RpcTest::identity( + FilecoinAddressToEthAddress::request((*KNOWN_CALIBNET_F4_ADDRESS, None)).unwrap(), )); } tests diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index c1fda1cee376..29952cd584a2 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -94,6 +94,9 @@ filecoin_evm_invokecontractdelegate_statedecodeparams_1755004924714578.rpcsnap.j filecoin_evm_resurrect_statedecodeparams_1755004924714636.rpcsnap.json.zst filecoin_filecoinaddresstoethaddress_1765291874419799.rpcsnap.json.zst # F4 address filecoin_filecoinaddresstoethaddress_1765357908887069.rpcsnap.json.zst # F0 address +filecoin_filecoinaddresstoethaddress_1765363872743134.rpcsnap.json.zst # F1 address +filecoin_filecoinaddresstoethaddress_1765363872743268.rpcsnap.json.zst # F3 address +filecoin_filecoinaddresstoethaddress_1765363872743313.rpcsnap.json.zst # F2 address filecoin_gasestimategaslimit_1741782110512299.rpcsnap.json.zst filecoin_getactoreventsraw_1741782590255476.rpcsnap.json.zst filecoin_market_addbalance_statedecodeparams_1757426002278914.rpcsnap.json.zst