From 52175dea073f327f50015fa12e14e7872be169fa Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Thu, 9 May 2024 15:02:01 +0800 Subject: [PATCH] feat(rpc): implement Filecoin.StateMarketParticipants --- src/rpc/methods/state.rs | 37 +++++++++++++++++++++++++ src/shim/actors/market.rs | 13 +++++++++ src/shim/actors/market/balance_table.rs | 37 +++++++++++++++++++++++++ src/shim/actors/mod.rs | 4 +++ src/shim/mod.rs | 1 + src/state_manager/mod.rs | 25 ++++++++--------- src/tool/subcommands/api_cmd.rs | 1 + 7 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 src/shim/actors/market.rs create mode 100644 src/shim/actors/market/balance_table.rs create mode 100644 src/shim/actors/mod.rs diff --git a/src/rpc/methods/state.rs b/src/rpc/methods/state.rs index b60384b22d9b..a6f6c7348fc1 100644 --- a/src/rpc/methods/state.rs +++ b/src/rpc/methods/state.rs @@ -8,6 +8,7 @@ pub use types::*; use crate::blocks::Tipset; use crate::cid_collections::CidHashSet; use crate::libp2p::NetworkMessage; +use crate::shim::actors::market::BalanceTableExt as _; use crate::shim::message::Message; use crate::shim::piece::PaddedPieceSize; use crate::shim::state_tree::StateTree; @@ -88,6 +89,7 @@ macro_rules! for_each_method { $callback!(crate::rpc::state::StateListMiners); $callback!(crate::rpc::state::StateNetworkVersion); $callback!(crate::rpc::state::StateMarketBalance); + $callback!(crate::rpc::state::StateMarketParticipants); $callback!(crate::rpc::state::StateMarketDeals); $callback!(crate::rpc::state::StateDealProviderCollateralBounds); $callback!(crate::rpc::state::StateMarketStorageDeal); @@ -1423,6 +1425,41 @@ impl RpcMethod<2> for StateMarketStorageDeal { } } +pub enum StateMarketParticipants {} + +impl RpcMethod<1> for StateMarketParticipants { + const NAME: &'static str = "Filecoin.StateMarketParticipants"; + const PARAM_NAMES: [&'static str; 1] = ["tipset_key"]; + const API_VERSION: ApiVersion = ApiVersion::V0; + const PERMISSION: Permission = Permission::Read; + + type Params = (ApiTipsetKey,); + type Ok = HashMap; + + async fn handle( + ctx: Ctx, + (ApiTipsetKey(tsk),): Self::Params, + ) -> Result { + let ts = ctx.chain_store.load_required_tipset_or_heaviest(&tsk)?; + let market_state = ctx.state_manager.market_state(&ts)?; + let escrow_table = market_state.escrow_table(ctx.store())?; + let locked_table = market_state.locked_table(ctx.store())?; + let mut result = HashMap::new(); + escrow_table.for_each(|address, escrow| { + let locked = locked_table.get(&address.into())?; + result.insert( + address.to_string(), + MarketBalance { + escrow: escrow.clone(), + locked: locked.into(), + }, + ); + Ok(()) + })?; + Ok(result) + } +} + pub enum StateDealProviderCollateralBounds {} impl RpcMethod<3> for StateDealProviderCollateralBounds { diff --git a/src/shim/actors/market.rs b/src/shim/actors/market.rs new file mode 100644 index 000000000000..f3ba78b06f46 --- /dev/null +++ b/src/shim/actors/market.rs @@ -0,0 +1,13 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +mod balance_table; + +use crate::shim::address::Address; +use crate::shim::econ::TokenAmount; + +pub trait BalanceTableExt { + fn for_each(&self, f: F) -> anyhow::Result<()> + where + F: FnMut(&Address, &TokenAmount) -> anyhow::Result<()>; +} diff --git a/src/shim/actors/market/balance_table.rs b/src/shim/actors/market/balance_table.rs new file mode 100644 index 000000000000..2d3619edd32e --- /dev/null +++ b/src/shim/actors/market/balance_table.rs @@ -0,0 +1,37 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::*; +use fil_actor_interface::market::BalanceTable; +use fvm_ipld_blockstore::Blockstore; + +impl<'bs, BS: Blockstore> BalanceTableExt for BalanceTable<'bs, BS> { + fn for_each(&self, mut f: F) -> anyhow::Result<()> + where + F: FnMut(&Address, &TokenAmount) -> anyhow::Result<()>, + { + match self { + Self::V8(t) => { + t.0.for_each(|key, escrow| f(&Address::from_bytes(&key.0)?, &escrow.into()))? + } + Self::V9(t) => { + t.0.for_each(|key, escrow| f(&Address::from_bytes(&key.0)?, &escrow.into()))? + } + Self::V10(t) => { + t.0.for_each(|key, escrow| f(&Address::from_bytes(&key.0)?, &escrow.into()))? + } + Self::V11(t) => { + t.0.for_each(|key, escrow| f(&Address::from_bytes(&key.0)?, &escrow.into()))? + } + Self::V12(t) => t.0.for_each(|address, escrow| { + f(&address.into(), &escrow.into()) + .map_err(|e| fil_actors_shared::v12::ActorError::unspecified(e.to_string())) + })?, + Self::V13(t) => t.0.for_each(|address, escrow| { + f(&address.into(), &escrow.into()) + .map_err(|e| fil_actors_shared::v13::ActorError::unspecified(e.to_string())) + })?, + }; + Ok(()) + } +} diff --git a/src/shim/actors/mod.rs b/src/shim/actors/mod.rs new file mode 100644 index 000000000000..69dac30e96e1 --- /dev/null +++ b/src/shim/actors/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +pub mod market; diff --git a/src/shim/mod.rs b/src/shim/mod.rs index ecf8b0dc2355..36ccbd93f0ae 100644 --- a/src/shim/mod.rs +++ b/src/shim/mod.rs @@ -1,6 +1,7 @@ // Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +pub mod actors; pub mod address; pub mod bigint; pub mod clock; diff --git a/src/state_manager/mod.rs b/src/state_manager/mod.rs index 9268617a06a8..49e23cd42f3c 100644 --- a/src/state_manager/mod.rs +++ b/src/state_manager/mod.rs @@ -193,10 +193,10 @@ impl TipsetStateCache { pub struct MarketBalance { #[schemars(with = "LotusJson")] #[serde(with = "crate::lotus_json")] - escrow: TokenAmount, + pub escrow: TokenAmount, #[schemars(with = "LotusJson")] #[serde(with = "crate::lotus_json")] - locked: TokenAmount, + pub locked: TokenAmount, } lotus_json_with_self!(MarketBalance); @@ -1019,19 +1019,16 @@ where .ok_or_else(|| Error::Other(format!("Failed to lookup the id address {addr}"))) } - /// Retrieves market balance in escrow and locked tables. - pub fn market_balance( - &self, - addr: &Address, - ts: &Tipset, - ) -> anyhow::Result { - let actor = self - .get_actor(&Address::MARKET_ACTOR, *ts.parent_state())? - .ok_or_else(|| { - Error::State("Market actor address could not be resolved".to_string()) - })?; - + /// Retrieves market state + pub fn market_state(&self, ts: &Tipset) -> Result { + let actor = self.get_required_actor(&Address::MARKET_ACTOR, *ts.parent_state())?; let market_state = market::State::load(self.blockstore(), actor.code, actor.state)?; + Ok(market_state) + } + + /// Retrieves market balance in escrow and locked tables. + pub fn market_balance(&self, addr: &Address, ts: &Tipset) -> Result { + let market_state = self.market_state(ts)?; let new_addr = self .lookup_id(addr, ts)? diff --git a/src/tool/subcommands/api_cmd.rs b/src/tool/subcommands/api_cmd.rs index 86e88a8e5095..fbbfc0b60686 100644 --- a/src/tool/subcommands/api_cmd.rs +++ b/src/tool/subcommands/api_cmd.rs @@ -729,6 +729,7 @@ fn state_tests_with_tipset( RpcTest::identity(StateVMCirculatingSupplyInternal::request((tipset .key() .into(),))?), + RpcTest::identity(StateMarketParticipants::request((tipset.key().into(),))?), ]; // Get deals