diff --git a/ipc/provider/src/lib.rs b/ipc/provider/src/lib.rs index f2b54653..dc854c67 100644 --- a/ipc/provider/src/lib.rs +++ b/ipc/provider/src/lib.rs @@ -14,6 +14,7 @@ use fvm_shared::{ use ipc_identity::{ EthKeyAddress, EvmKeyStore, KeyStore, KeyStoreConfig, PersistentKeyStore, Wallet, }; +use ipc_sdk::staking::StakingChangeRequest; use ipc_sdk::{ cross::CrossMsg, subnet::{ConsensusType, ConstructParams}, @@ -534,6 +535,33 @@ impl IpcProvider { conn.manager().chain_head_height().await } + /// Obtain the genesis epoch of the input subnet. + pub async fn genesis_epoch(&self, subnet: &SubnetID) -> anyhow::Result { + let parent = subnet.parent().ok_or_else(|| anyhow!("no parent found"))?; + let conn = match self.connection(&parent) { + None => return Err(anyhow!("parent subnet config not found")), + Some(conn) => conn, + }; + conn.manager().genesis_epoch(subnet).await + } + + /// Get the changes in subnet validators. This is fetched from parent. + pub async fn get_validator_changeset( + &self, + subnet: &SubnetID, + start: ChainEpoch, + end: ChainEpoch, + ) -> anyhow::Result> { + let conn = match self.connection(subnet) { + None => return Err(anyhow!("target subnet not found")), + Some(conn) => conn, + }; + + conn.manager() + .get_validator_changeset(subnet, start, end) + .await + } + pub async fn get_top_down_msgs( &self, subnet: &SubnetID, @@ -572,6 +600,15 @@ impl IpcProvider { conn.manager().get_chain_id().await } + + pub async fn get_chain_head_height(&self, subnet: &SubnetID) -> anyhow::Result { + let conn = match self.connection(subnet) { + None => return Err(anyhow!("target subnet not found")), + Some(conn) => conn, + }; + + conn.manager().chain_head_height().await + } } /// Lotus JSON keytype format diff --git a/ipc/provider/src/manager/evm/manager.rs b/ipc/provider/src/manager/evm/manager.rs index 125b48b1..e95d240f 100644 --- a/ipc/provider/src/manager/evm/manager.rs +++ b/ipc/provider/src/manager/evm/manager.rs @@ -70,6 +70,23 @@ struct IPCContractInfo { #[async_trait] impl TopDownCheckpointQuery for EthSubnetManager { + async fn genesis_epoch(&self, subnet_id: &SubnetID) -> Result { + let address = contract_address_from_subnet(subnet_id)?; + log::info!("querying genesis epoch in evm subnet contract: {address:}"); + + let evm_subnet_id = gateway_getter_facet::SubnetID::try_from(subnet_id)?; + + let contract = gateway_getter_facet::GatewayGetterFacet::new( + self.ipc_contract_info.gateway_addr, + Arc::new(self.ipc_contract_info.provider.clone()), + ); + let (exists, subnet) = contract.get_subnet(evm_subnet_id).call().await?; + if !exists { + return Err(anyhow!("subnet: {} does not exists", subnet_id)); + } + Ok(subnet.genesis_epoch.as_u64() as ChainEpoch) + } + async fn chain_head_height(&self) -> Result { let block = self .ipc_contract_info diff --git a/ipc/provider/src/manager/subnet.rs b/ipc/provider/src/manager/subnet.rs index ee160c83..7957679a 100644 --- a/ipc/provider/src/manager/subnet.rs +++ b/ipc/provider/src/manager/subnet.rs @@ -128,6 +128,8 @@ pub trait SubnetManager: Send + Sync + TopDownCheckpointQuery { /// Trait to interact with a subnet to query the necessary information for top down checkpoint. #[async_trait] pub trait TopDownCheckpointQuery: Send + Sync { + /// Returns the genesis epoch that the subnet is created in parent network + async fn genesis_epoch(&self, subnet_id: &SubnetID) -> Result; /// Returns the chain head height async fn chain_head_height(&self) -> Result; /// Returns the list of top down messages