diff --git a/src/lotus_json/actor_states/methods/eam_params.rs b/src/lotus_json/actor_states/methods/eam_params.rs new file mode 100644 index 000000000000..be92e48f108c --- /dev/null +++ b/src/lotus_json/actor_states/methods/eam_params.rs @@ -0,0 +1,152 @@ +// Copyright 2019-2025 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::*; +use fvm_ipld_encoding::RawBytes; +use paste::paste; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(rename_all = "PascalCase")] +pub struct EAMCreateParamsLotusJson { + #[schemars(with = "LotusJson")] + #[serde(with = "crate::lotus_json")] + pub initcode: RawBytes, + pub nonce: u64, +} + +macro_rules! impl_eam_create_params { + ($($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_eam_state::[]::CreateParams { + type LotusJson = EAMCreateParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!({ + "Initcode": "ESIzRFU=", + "Nonce": 42 + }), + Self { + initcode: hex::decode("1122334455").unwrap(), + nonce: 42, + }, + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + EAMCreateParamsLotusJson { + initcode: RawBytes::new(self.initcode), + nonce: self.nonce, + } + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self { + initcode: lotus_json.initcode.into(), + nonce: lotus_json.nonce, + } + } + } + } + )+ + }; +} + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(rename_all = "PascalCase")] +pub struct EAMCreate2ParamsLotusJson { + #[schemars(with = "LotusJson>")] + #[serde(with = "crate::lotus_json")] + pub initcode: Vec, + pub salt: [u8; 32], +} + +macro_rules! impl_eam_create2_params { + ($($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_eam_state::[]::Create2Params { + type LotusJson = EAMCreate2ParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!({ + "Initcode": "ESIzRFU=", + "Salt": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + }), + Self { + initcode: hex::decode("1122334455").unwrap(), + salt: [0; 32], + }, + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + EAMCreate2ParamsLotusJson { + initcode: self.initcode, + salt: self.salt, + } + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self { + initcode: lotus_json.initcode, + salt: lotus_json.salt, + } + } + } + } + )+ + }; +} + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(rename_all = "PascalCase")] +pub struct EAMCreateExternalParamsLotusJson( + #[schemars(with = "LotusJson")] + #[serde(with = "crate::lotus_json")] + RawBytes, +); + +macro_rules! impl_eam_create_external_params { + ($($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_eam_state::[]::CreateExternalParams { + type LotusJson = EAMCreateExternalParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!("ESIzRFU="), + Self(hex::decode("1122334455").unwrap()), + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + EAMCreateExternalParamsLotusJson(RawBytes::new(self.0)) + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self(lotus_json.0.into()) + } + } + } + )+ + }; +} + +impl_eam_create_params!(10, 11, 12, 13, 14, 15, 16); +impl_eam_create2_params!(10, 11, 12, 13, 14, 15, 16); +impl_eam_create_external_params!(10, 11, 12, 13, 14, 15, 16); diff --git a/src/lotus_json/actor_states/methods/mod.rs b/src/lotus_json/actor_states/methods/mod.rs index 43f5957b5e8b..9ebd49368541 100644 --- a/src/lotus_json/actor_states/methods/mod.rs +++ b/src/lotus_json/actor_states/methods/mod.rs @@ -6,6 +6,7 @@ mod account_authenticate_params; mod account_constructor_params; mod cron_actor_params; mod datacap_actor_params; +mod eam_params; mod evm_actor_params; mod init_constructor_params; mod init_exec4_params; diff --git a/src/rpc/registry/actors/eam.rs b/src/rpc/registry/actors/eam.rs new file mode 100644 index 000000000000..a02bd8b9e80f --- /dev/null +++ b/src/rpc/registry/actors/eam.rs @@ -0,0 +1,38 @@ +// Copyright 2019-2025 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use crate::rpc::registry::methods_reg::{MethodRegistry, register_actor_methods}; +use crate::shim::message::MethodNum; +use cid::Cid; + +macro_rules! register_eam_reg_version { + ($registry:expr, $code_cid:expr, $state_version:path) => {{ + use $state_version::{Create2Params, CreateExternalParams, CreateParams, Method}; + + // Constructor has no parameters + register_actor_methods!($registry, $code_cid, [(Method::Constructor, empty),]); + + register_actor_methods!( + $registry, + $code_cid, + [ + (Method::Create, CreateParams), + (Method::Create2, Create2Params), + (Method::CreateExternal, CreateExternalParams), + ] + ); + }}; +} + +pub(crate) fn register_actor_methods(registry: &mut MethodRegistry, cid: Cid, version: u64) { + match version { + 10 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v10), + 11 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v11), + 12 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v12), + 13 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v13), + 14 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v14), + 15 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v15), + 16 => register_eam_reg_version!(registry, cid, fil_actor_eam_state::v16), + _ => {} + } +} diff --git a/src/rpc/registry/actors/mod.rs b/src/rpc/registry/actors/mod.rs index ba401be54969..66b4f62b320d 100644 --- a/src/rpc/registry/actors/mod.rs +++ b/src/rpc/registry/actors/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod account; pub(crate) mod cron; pub(crate) mod datacap; +pub(crate) mod eam; pub(crate) mod eth_account; pub(crate) mod evm; pub(crate) mod init; diff --git a/src/rpc/registry/methods_reg.rs b/src/rpc/registry/methods_reg.rs index f75f982e323b..75b8ea34162f 100644 --- a/src/rpc/registry/methods_reg.rs +++ b/src/rpc/registry/methods_reg.rs @@ -74,7 +74,7 @@ impl MethodRegistry { fn register_known_methods(&mut self) { use crate::rpc::registry::actors::{ - account, cron, datacap, eth_account, evm, init, miner, multisig, payment_channel, + account, cron, datacap, eam, eth_account, evm, init, miner, multisig, payment_channel, power, reward, system, verified_reg, }; @@ -101,6 +101,7 @@ impl MethodRegistry { BuiltinActor::PaymentChannel => { payment_channel::register_actor_methods(self, cid, version) } + BuiltinActor::EAM => eam::register_actor_methods(self, cid, version), _ => {} } } diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index 509a325a6ab0..a250382dc28e 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -1903,6 +1903,7 @@ fn state_decode_params_api_tests(tipset: &Tipset) -> anyhow::Result tests.extend(multisig_actor_state_decode_params_tests(tipset)?); tests.extend(verified_reg_actor_state_decode_params_tests(tipset)?); tests.extend(paych_actor_state_decode_params_tests(tipset)?); + tests.extend(eam_actor_state_decode_params_tests(tipset)?); Ok(tests) } @@ -1966,6 +1967,48 @@ fn paych_actor_state_decode_params_tests(tipset: &Tipset) -> anyhow::Result anyhow::Result> { + let create_params = fil_actor_eam_state::v16::CreateParams { + initcode: vec![0x11, 0x22, 0x33, 0x44, 0x55], // dummy data + nonce: 2, + }; + + let create_params2 = fil_actor_eam_state::v16::Create2Params { + initcode: vec![0x11, 0x22, 0x33, 0x44, 0x55], // dummy data + salt: [0; 32], + }; + + let create_external_params = + fil_actor_eam_state::v16::CreateExternalParams(vec![0x11, 0x22, 0x33, 0x44, 0x55]); + + Ok(vec![ + RpcTest::identity(StateDecodeParams::request(( + Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR, + fil_actor_eam_state::v16::Method::Constructor as u64, + vec![], + tipset.key().into(), + ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR, + fil_actor_eam_state::v16::Method::Create as u64, + to_vec(&create_params)?, + tipset.key().into(), + ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR, + fil_actor_eam_state::v16::Method::Create2 as u64, + to_vec(&create_params2)?, + tipset.key().into(), + ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::ETHEREUM_ACCOUNT_MANAGER_ACTOR, + fil_actor_eam_state::v16::Method::CreateExternal as u64, + to_vec(&create_external_params)?, + tipset.key().into(), + ))?), + ]) +} + fn evm_actor_state_decode_params_tests(tipset: &Tipset) -> anyhow::Result> { let evm_constructor_params = fil_actor_evm_state::v16::ConstructorParams { creator: fil_actor_evm_state::evm_shared::v16::address::EthAddress([0; 20]), diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index 5854c5a4df2e..aeb76590b5da 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -255,6 +255,10 @@ filecoin_payment_channel_statedecodeparams_1756194613312797.rpcsnap.json.zst filecoin_payment_channel_statedecodeparams_1756194613312868.rpcsnap.json.zst filecoin_payment_channel_statedecodeparams_1756194613312941.rpcsnap.json.zst filecoin_payment_channel_statedecodeparams_1756194613313007.rpcsnap.json.zst +filecoin_eam_statedecodeparams_1756139121347152.rpcsnap.json.zst +filecoin_eam_statedecodeparams_1756139121347218.rpcsnap.json.zst +filecoin_eam_statedecodeparams_1756139121347288.rpcsnap.json.zst +filecoin_eam_statedecodeparams_1756139121347364.rpcsnap.json.zst filecoin_statereplay_1743504051038215.rpcsnap.json.zst filecoin_statesearchmsg_1741784596636715.rpcsnap.json.zst filecoin_statesearchmsglimited_1741784596704876.rpcsnap.json.zst