diff --git a/src/rpc/registry/actors/mod.rs b/src/rpc/registry/actors/mod.rs index 483ff04baa3a..4de42208df76 100644 --- a/src/rpc/registry/actors/mod.rs +++ b/src/rpc/registry/actors/mod.rs @@ -5,3 +5,4 @@ pub(crate) mod account; pub(crate) mod evm; pub(crate) mod init; pub(crate) mod miner; +pub(crate) mod system; diff --git a/src/rpc/registry/actors/system.rs b/src/rpc/registry/actors/system.rs new file mode 100644 index 000000000000..8781346ae88e --- /dev/null +++ b/src/rpc/registry/actors/system.rs @@ -0,0 +1,32 @@ +// 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_system_version { + ($registry:expr, $code_cid:expr, $state_version:path) => {{ + use $state_version::*; + + register_actor_methods!( + $registry, + $code_cid, + [ + (Method::Constructor, empty), // constructor method doesn't accept any kind of param + ] + ); + }}; +} + +pub(crate) fn register_actor_methods(registry: &mut MethodRegistry, cid: Cid) { + register_system_version!(registry, cid, fil_actor_system_state::v8); + register_system_version!(registry, cid, fil_actor_system_state::v9); + register_system_version!(registry, cid, fil_actor_system_state::v10); + register_system_version!(registry, cid, fil_actor_system_state::v11); + register_system_version!(registry, cid, fil_actor_system_state::v12); + register_system_version!(registry, cid, fil_actor_system_state::v13); + register_system_version!(registry, cid, fil_actor_system_state::v14); + register_system_version!(registry, cid, fil_actor_system_state::v15); + register_system_version!(registry, cid, fil_actor_system_state::v16); +} diff --git a/src/rpc/registry/actors_reg.rs b/src/rpc/registry/actors_reg.rs index 2b7cf13bd297..53f13a0ba11a 100644 --- a/src/rpc/registry/actors_reg.rs +++ b/src/rpc/registry/actors_reg.rs @@ -50,14 +50,6 @@ impl ActorRegistry { pub(crate) static ACTOR_REGISTRY: LazyLock = LazyLock::new(ActorRegistry::new); -pub fn get_actor_type_from_code(code_cid: &Cid) -> Result<(BuiltinActor, u64)> { - ACTOR_REGISTRY - .map - .get(code_cid) - .copied() - .ok_or_else(|| anyhow!("Unknown actor code CID: {}", code_cid)) -} - macro_rules! load_and_serialize_state { ($store:expr, $code_cid:expr, $state_cid:expr, $actor_type:expr, $state_type:ty) => {{ let state = <$state_type>::load($store, *$code_cid, *$state_cid).context(format!( diff --git a/src/rpc/registry/methods_reg.rs b/src/rpc/registry/methods_reg.rs index e839a838abf6..b4ecedfe1d02 100644 --- a/src/rpc/registry/methods_reg.rs +++ b/src/rpc/registry/methods_reg.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0, MIT use crate::lotus_json::HasLotusJson; +use crate::rpc::registry::actors::system; +use crate::rpc::registry::actors_reg::{ACTOR_REGISTRY, ActorRegistry}; use crate::shim::machine::BuiltinActor; use crate::shim::message::MethodNum; use ahash::{HashMap, HashMapExt}; @@ -11,8 +13,6 @@ use serde::de::DeserializeOwned; use serde_json::Value; use std::sync::LazyLock; -use crate::rpc::registry::actors_reg::{ACTOR_REGISTRY, get_actor_type_from_code}; - // Global registry for method parameter deserialization static METHOD_REGISTRY: LazyLock = LazyLock::new(MethodRegistry::with_known_methods); @@ -63,7 +63,7 @@ impl MethodRegistry { return Ok(Some(deserializer(params_bytes)?)); } - let (actor_type, version) = get_actor_type_from_code(code_cid)?; + let (actor_type, version) = ActorRegistry::get_actor_details_from_code(code_cid)?; bail!( "No deserializer registered for actor type {:?} (v{}), method {}", @@ -82,6 +82,7 @@ impl MethodRegistry { BuiltinActor::Miner => miner::register_miner_actor_methods(self, cid), BuiltinActor::EVM => evm::register_evm_actor_methods(self, cid), BuiltinActor::Init => init::register_actor_methods(self, cid), + BuiltinActor::System => system::register_actor_methods(self, cid), _ => {} } } @@ -97,6 +98,25 @@ pub fn deserialize_params( } macro_rules! register_actor_methods { + // Handle empty params case + ($registry:expr, $code_cid:expr, [ + $( ($method:expr, empty) ),* $(,)? + ]) => { + $( + $registry.register_method( + $code_cid, + $method as MethodNum, + |bytes| -> anyhow::Result<()> { + if bytes.is_empty() { + Ok(()) + } else { + Ok(fvm_ipld_encoding::from_slice(bytes)?) + } + }, + ); + )* + }; + ($registry:expr, $code_cid:expr, [ $( ($method:expr, $param_type:ty) ),* $(,)? ]) => { @@ -250,21 +270,6 @@ mod test { } } - #[test] - fn test_unsupported_actor_types() { - // Test actors that are not registered in the method registry - if let Some(system_cid) = get_real_actor_cid(BuiltinActor::System) { - let method_num = 1; - - let result = deserialize_params(&system_cid, method_num, &[]); - assert!(result.is_err()); - - let error_msg = result.unwrap_err().to_string(); - assert!(error_msg.contains("No deserializer registered for actor type")); - assert!(error_msg.contains("System")); - } - } - #[test] fn test_register_actor_methods_macro() { let mut registry = MethodRegistry::new(); @@ -292,4 +297,15 @@ mod test { let result3 = registry.deserialize_params(&test_cid, 3, &encoded); assert!(result3.is_err()); } + + #[test] + fn test_system_actor_deserialize_params_cbor_null() { + let system_cid = get_real_actor_cid(BuiltinActor::System) + .expect("Should have System actor CID in registry"); + + // Test with null data + let result = deserialize_params(&system_cid, 1, &[]); + + assert!(result.is_ok(), "Should handle CBOR null: {result:?}"); + } }