From 176bd0fa5936f51741d43c95617499290aaae1ef Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 19:07:30 +0530 Subject: [PATCH 1/6] feat: add support for reward actor in state decode params API [skip ci] --- src/lotus_json/actor_states/methods/mod.rs | 1 + .../actor_states/methods/reward_methods.rs | 180 ++++++++++++++++++ src/lotus_json/big_int.rs | 30 +++ src/rpc/registry/actors/mod.rs | 1 + src/rpc/registry/actors/reward.rs | 66 +++++++ src/rpc/registry/methods_reg.rs | 3 +- 6 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 src/lotus_json/actor_states/methods/reward_methods.rs create mode 100644 src/rpc/registry/actors/reward.rs diff --git a/src/lotus_json/actor_states/methods/mod.rs b/src/lotus_json/actor_states/methods/mod.rs index 825949dbe75f..70a70c2ec0d9 100644 --- a/src/lotus_json/actor_states/methods/mod.rs +++ b/src/lotus_json/actor_states/methods/mod.rs @@ -9,3 +9,4 @@ mod init_exec4_params; mod init_exec_params; mod miner_change_worker_params; mod miner_constructor_params; +mod reward_methods; diff --git a/src/lotus_json/actor_states/methods/reward_methods.rs b/src/lotus_json/actor_states/methods/reward_methods.rs new file mode 100644 index 000000000000..e71d3177ba3e --- /dev/null +++ b/src/lotus_json/actor_states/methods/reward_methods.rs @@ -0,0 +1,180 @@ +// Copyright 2019-2025 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::*; +use crate::shim::address::Address; +use crate::shim::econ::TokenAmount; +use num_bigint::BigInt; +use paste::paste; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(transparent)] +pub struct RewardConstructorParamsLotusJson( + #[schemars(with = "LotusJson>")] + #[serde(with = "crate::lotus_json")] + Option, +); + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(rename_all = "PascalCase")] +pub struct AwardBlockRewardParamsLotusJson { + #[schemars(with = "LotusJson
")] + #[serde(with = "crate::lotus_json")] + pub miner: Address, + #[schemars(with = "LotusJson")] + #[serde(with = "crate::lotus_json")] + pub penalty: TokenAmount, + #[schemars(with = "LotusJson")] + #[serde(with = "crate::lotus_json")] + pub gas_reward: TokenAmount, + pub win_count: i64, +} + +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)] +#[serde(transparent)] +pub struct UpdateNetworkKPIParamsLotusJson( + #[schemars(with = "LotusJson>")] + #[serde(with = "crate::lotus_json")] + Option, +); + +// Implementation for ConstructorParams +macro_rules! impl_reward_constructor_params { + ($type_suffix:path: $($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_reward_state::[]::ConstructorParams { + type LotusJson = RewardConstructorParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!(null), + Self { + power: None, + }, + ), + ( + json!("1000"), + Self { + power: Some($type_suffix::bigint_ser::BigIntDe(BigInt::from(1000))), + }, + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + RewardConstructorParamsLotusJson(self.power.map(|p| p.0)) + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self { + power: lotus_json.0.map(|p| $type_suffix::bigint_ser::BigIntDe(p)), + } + } + } + } + )+ + }; +} + +// Implementation for AwardBlockRewardParams +macro_rules! impl_award_block_reward_params { + ($($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_reward_state::[]::AwardBlockRewardParams { + type LotusJson = AwardBlockRewardParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!({ + "Miner": "f01234", + "Penalty": "0", + "GasReward": "1000", + "WinCount": 1 + }), + Self { + miner: Address::new_id(1234).into(), + penalty: TokenAmount::from_atto(0).into(), + gas_reward: TokenAmount::from_atto(1000).into(), + win_count: 1, + }, + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + AwardBlockRewardParamsLotusJson { + miner: self.miner.into(), + penalty: self.penalty.into(), + gas_reward: self.gas_reward.into(), + win_count: self.win_count, + } + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self { + miner: lotus_json.miner.into(), + penalty: TokenAmount::from(lotus_json.penalty).into(), + gas_reward: TokenAmount::from(lotus_json.gas_reward).into(), + win_count: lotus_json.win_count, + } + } + } + } + )+ + }; +} + +// Implementation for UpdateNetworkKPIParams +macro_rules! impl_update_network_kpi_params { + ($type_suffix:path: $($version:literal),+) => { + $( + paste! { + impl HasLotusJson for fil_actor_reward_state::[]::UpdateNetworkKPIParams { + type LotusJson = UpdateNetworkKPIParamsLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![ + ( + json!(null), + Self { + curr_realized_power: None, + }, + ), + ( + json!("2000"), + Self { + curr_realized_power: Some($type_suffix::bigint_ser::BigIntDe(BigInt::from(2000))), + }, + ), + ] + } + + fn into_lotus_json(self) -> Self::LotusJson { + UpdateNetworkKPIParamsLotusJson(self.curr_realized_power.map(|p| p.0)) + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Self { + curr_realized_power: lotus_json.0.map(|p| $type_suffix::bigint_ser::BigIntDe(p)), + } + } + } + } + )+ + }; +} + +impl_reward_constructor_params!(fvm_shared4::bigint: 16, 15, 14, 13, 12); +impl_reward_constructor_params!(fvm_shared3::bigint: 11); +impl_award_block_reward_params!(16, 15, 14, 13, 12, 11, 10, 9, 8); +impl_update_network_kpi_params!(fvm_shared4::bigint: 16, 15, 14, 13, 12); +impl_update_network_kpi_params!(fvm_shared3::bigint: 11); diff --git a/src/lotus_json/big_int.rs b/src/lotus_json/big_int.rs index 06f8618144c8..470ae7c66b26 100644 --- a/src/lotus_json/big_int.rs +++ b/src/lotus_json/big_int.rs @@ -29,3 +29,33 @@ impl HasLotusJson for BigInt { big_int } } + +macro_rules! impl_bigint_de { + ($($bigint_de_type:ty),+) => { + $( + impl HasLotusJson for $bigint_de_type { + type LotusJson = BigIntLotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + vec![(json!("1000"), Self(BigInt::from(1000)))] + } + + fn into_lotus_json(self) -> Self::LotusJson { + BigIntLotusJson(self.0) + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + let BigIntLotusJson(big_int) = lotus_json; + Self(big_int) + } + } + )+ + }; +} + +impl_bigint_de!( + fvm_shared2::bigint::bigint_ser::BigIntDe, + fvm_shared3::bigint::bigint_ser::BigIntDe, + fvm_shared4::bigint::bigint_ser::BigIntDe +); diff --git a/src/rpc/registry/actors/mod.rs b/src/rpc/registry/actors/mod.rs index 4de42208df76..328b6c0b59bd 100644 --- a/src/rpc/registry/actors/mod.rs +++ b/src/rpc/registry/actors/mod.rs @@ -5,4 +5,5 @@ pub(crate) mod account; pub(crate) mod evm; pub(crate) mod init; pub(crate) mod miner; +pub(crate) mod reward; pub(crate) mod system; diff --git a/src/rpc/registry/actors/reward.rs b/src/rpc/registry/actors/reward.rs new file mode 100644 index 000000000000..f7030d149134 --- /dev/null +++ b/src/rpc/registry/actors/reward.rs @@ -0,0 +1,66 @@ +// 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 anyhow::Result; +use cid::Cid; + +macro_rules! register_reward_version_11_to_16 { + ($registry:expr, $code_cid:expr, $state_version:path) => {{ + use $state_version::{ + AwardBlockRewardParams, ConstructorParams, Method, UpdateNetworkKPIParams, + }; + + register_actor_methods!( + $registry, + $code_cid, + [ + (Method::Constructor, ConstructorParams), + (Method::AwardBlockReward, AwardBlockRewardParams), + (Method::UpdateNetworkKPI, UpdateNetworkKPIParams), + ] + ); + + // Register methods without parameters + register_actor_methods!($registry, $code_cid, [(Method::ThisEpochReward, empty)]); + }}; +} + +macro_rules! register_reward_version_8_to_9 { + ($registry:expr, $code_cid:expr, $state_version:path, $fvm_shared_version:path) => {{ + use $state_version::{AwardBlockRewardParams, Method}; + use $fvm_shared_version::{bigint::bigint_ser::BigIntDe}; + + register_actor_methods!( + $registry, + $code_cid, + [ + (Method::Constructor, Option), + (Method::AwardBlockReward, AwardBlockRewardParams), + (Method::UpdateNetworkKPI, Option), + ] + ); + }}; +} + +pub(crate) fn register_actor_methods(registry: &mut MethodRegistry, cid: Cid, version: u64) { + match version { + 8 => { + register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v8, fvm_shared2) + } + 9 => { + register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v9, fvm_shared2) + } + 10 => { + register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v10, fvm_shared3) + } + 11 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v11), + 12 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v12), + 13 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v13), + 14 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v14), + 15 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v15), + 16 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v16), + _ => {} + } +} diff --git a/src/rpc/registry/methods_reg.rs b/src/rpc/registry/methods_reg.rs index b4ecedfe1d02..10376ac08f71 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, evm, init, miner}; + use crate::rpc::registry::actors::{account, evm, init, miner, reward}; for (&cid, &(actor_type, _version)) in ACTOR_REGISTRY.iter() { match actor_type { @@ -83,6 +83,7 @@ impl MethodRegistry { 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), + BuiltinActor::Reward => reward::register_actor_methods(self, cid, _version), _ => {} } } From 4c1c7bb911f44b2d44456db52df6a435964b61bd Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 20:26:16 +0530 Subject: [PATCH 2/6] test: add reward actor method tests in api compare tests --- .../subcommands/api_cmd/api_compare_tests.rs | 37 +++++++++++++++++++ .../subcommands/api_cmd/test_snapshots.txt | 3 ++ 2 files changed, 40 insertions(+) diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index d469fa3afbee..0f67be2eba5e 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -52,6 +52,7 @@ use ipld_core::ipld::Ipld; use itertools::Itertools as _; use jsonrpsee::types::ErrorCode; use libp2p::PeerId; +use num_bigint::BigInt; use num_traits::Signed; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -1849,6 +1850,24 @@ fn state_decode_params_api_tests(tipset: &Tipset) -> anyhow::Result constructor_params: fvm_ipld_encoding::RawBytes::new(vec![0x12, 0x34, 0x56]), // dummy bytecode }; + let reward_constructor_params = fil_actor_reward_state::v16::ConstructorParams { + power: Some(Default::default()), + }; + + let reward_award_block_reward_params = fil_actor_reward_state::v16::AwardBlockRewardParams { + miner: Address::new_id(1000).into(), + penalty: Default::default(), + gas_reward: Default::default(), + win_count: 0, + }; + + let rewar_update_network_params = fil_actor_reward_state::v16::UpdateNetworkKPIParams { + curr_realized_power: Option::from(fvm_shared4::bigint::bigint_ser::BigIntDe(BigInt::from( + 111, + ))), + }; + + use fil_actor_reward_state::v16::Method; let tests = vec![ RpcTest::identity(StateDecodeParams::request(( MINER_ADDRESS, @@ -1898,6 +1917,24 @@ fn state_decode_params_api_tests(tipset: &Tipset) -> anyhow::Result to_vec(&init_exec4_params)?, tipset.key().into(), ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::REWARD_ACTOR, + Method::Constructor as u64, + to_vec(&reward_constructor_params)?, + tipset.key().into(), + ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::REWARD_ACTOR, + Method::AwardBlockReward as u64, + to_vec(&reward_award_block_reward_params)?, + tipset.key().into(), + ))?), + RpcTest::identity(StateDecodeParams::request(( + Address::REWARD_ACTOR, + Method::UpdateNetworkKPI as u64, + to_vec(&rewar_update_network_params)?, + tipset.key().into(), + ))?), ]; Ok(tests) diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index d5216a484c70..b29b75efcb2f 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -134,6 +134,9 @@ filecoin_statedecodeparams_1749826976836194.rpcsnap.json.zst filecoin_statedecodeparams_1749826976835026.rpcsnap.json.zst filecoin_statedecodeparams_1749826976835457.rpcsnap.json.zst filecoin_statedecodeparams_1750858921185411.rpcsnap.json.zst +filecoin_statedecodeparams_1754059748144675.rpcsnap.json.zst +filecoin_statedecodeparams_1754059748147929.rpcsnap.json.zst +filecoin_statedecodeparams_1754059748148210.rpcsnap.json.zst filecoin_statereplay_1743504051038215.rpcsnap.json.zst filecoin_statesearchmsg_1741784596636715.rpcsnap.json.zst filecoin_statesearchmsglimited_1741784596704876.rpcsnap.json.zst From 6caff3ac3ff771e13bf169249d7c0b2e8c8482d1 Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 20:40:38 +0530 Subject: [PATCH 3/6] nit fix --- src/tool/subcommands/api_cmd/api_compare_tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index 0f67be2eba5e..38f126e0f338 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -1861,7 +1861,7 @@ fn state_decode_params_api_tests(tipset: &Tipset) -> anyhow::Result win_count: 0, }; - let rewar_update_network_params = fil_actor_reward_state::v16::UpdateNetworkKPIParams { + let reward_update_network_params = fil_actor_reward_state::v16::UpdateNetworkKPIParams { curr_realized_power: Option::from(fvm_shared4::bigint::bigint_ser::BigIntDe(BigInt::from( 111, ))), @@ -1932,7 +1932,7 @@ fn state_decode_params_api_tests(tipset: &Tipset) -> anyhow::Result RpcTest::identity(StateDecodeParams::request(( Address::REWARD_ACTOR, Method::UpdateNetworkKPI as u64, - to_vec(&rewar_update_network_params)?, + to_vec(&reward_update_network_params)?, tipset.key().into(), ))?), ]; From f8f8d1cb1c7152dc4150a848f821a79f95919a2e Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 20:46:36 +0530 Subject: [PATCH 4/6] add remaining method and rename the macro --- src/rpc/registry/actors/reward.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rpc/registry/actors/reward.rs b/src/rpc/registry/actors/reward.rs index f7030d149134..4288ea63bbad 100644 --- a/src/rpc/registry/actors/reward.rs +++ b/src/rpc/registry/actors/reward.rs @@ -27,7 +27,7 @@ macro_rules! register_reward_version_11_to_16 { }}; } -macro_rules! register_reward_version_8_to_9 { +macro_rules! register_reward_version_8_to_10 { ($registry:expr, $code_cid:expr, $state_version:path, $fvm_shared_version:path) => {{ use $state_version::{AwardBlockRewardParams, Method}; use $fvm_shared_version::{bigint::bigint_ser::BigIntDe}; @@ -41,19 +41,22 @@ macro_rules! register_reward_version_8_to_9 { (Method::UpdateNetworkKPI, Option), ] ); + + // Register methods without parameters + register_actor_methods!($registry, $code_cid, [(Method::ThisEpochReward, empty)]); }}; } pub(crate) fn register_actor_methods(registry: &mut MethodRegistry, cid: Cid, version: u64) { match version { 8 => { - register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v8, fvm_shared2) + register_reward_version_8_to_10!(registry, cid, fil_actor_reward_state::v8, fvm_shared2) } 9 => { - register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v9, fvm_shared2) + register_reward_version_8_to_10!(registry, cid, fil_actor_reward_state::v9, fvm_shared2) } 10 => { - register_reward_version_8_to_9!(registry, cid, fil_actor_reward_state::v10, fvm_shared3) + register_reward_version_8_to_10!(registry, cid, fil_actor_reward_state::v10, fvm_shared3) } 11 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v11), 12 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v12), From f413489eaf0ffd829db6465552cf0fd4e201b454 Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 21:12:31 +0530 Subject: [PATCH 5/6] fix linter issue --- src/rpc/registry/actors/reward.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/rpc/registry/actors/reward.rs b/src/rpc/registry/actors/reward.rs index 4288ea63bbad..f5e6ca51f0ae 100644 --- a/src/rpc/registry/actors/reward.rs +++ b/src/rpc/registry/actors/reward.rs @@ -56,7 +56,12 @@ pub(crate) fn register_actor_methods(registry: &mut MethodRegistry, cid: Cid, ve register_reward_version_8_to_10!(registry, cid, fil_actor_reward_state::v9, fvm_shared2) } 10 => { - register_reward_version_8_to_10!(registry, cid, fil_actor_reward_state::v10, fvm_shared3) + register_reward_version_8_to_10!( + registry, + cid, + fil_actor_reward_state::v10, + fvm_shared3 + ) } 11 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v11), 12 => register_reward_version_11_to_16!(registry, cid, fil_actor_reward_state::v12), From c945d8aab5d8a459ff133949b0f7c9a999a9e0cf Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 1 Aug 2025 22:06:53 +0530 Subject: [PATCH 6/6] format fixes --- src/lotus_json/actor_states/methods/mod.rs | 2 +- src/rpc/registry/actors/mod.rs | 2 +- src/rpc/registry/methods_reg.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lotus_json/actor_states/methods/mod.rs b/src/lotus_json/actor_states/methods/mod.rs index 7b767782727b..836d36075545 100644 --- a/src/lotus_json/actor_states/methods/mod.rs +++ b/src/lotus_json/actor_states/methods/mod.rs @@ -9,5 +9,5 @@ mod init_exec4_params; mod init_exec_params; mod miner_change_worker_params; mod miner_constructor_params; -mod reward_methods; mod power_actor; +mod reward_methods; diff --git a/src/rpc/registry/actors/mod.rs b/src/rpc/registry/actors/mod.rs index cceb6e0a77de..ce52f05d104f 100644 --- a/src/rpc/registry/actors/mod.rs +++ b/src/rpc/registry/actors/mod.rs @@ -5,6 +5,6 @@ pub(crate) mod account; pub(crate) mod evm; pub(crate) mod init; pub(crate) mod miner; -pub(crate) mod reward; pub(crate) mod power; +pub(crate) mod reward; pub(crate) mod system; diff --git a/src/rpc/registry/methods_reg.rs b/src/rpc/registry/methods_reg.rs index 388d21a0bbab..2d84a9c5aa72 100644 --- a/src/rpc/registry/methods_reg.rs +++ b/src/rpc/registry/methods_reg.rs @@ -85,7 +85,7 @@ impl MethodRegistry { BuiltinActor::Init => init::register_actor_methods(self, cid, version), BuiltinActor::System => system::register_actor_methods(self, cid, version), BuiltinActor::Power => power::register_actor_methods(self, cid, version), - BuiltinActor::Reward => reward::register_actor_methods(self, cid, version) + BuiltinActor::Reward => reward::register_actor_methods(self, cid, version), _ => {} } }