-
Notifications
You must be signed in to change notification settings - Fork 188
refactor state manager mod into multiple sub mods #6864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,180 @@ | ||||||
| // Copyright 2019-2026 ChainSafe Systems | ||||||
| // SPDX-License-Identifier: Apache-2.0, MIT | ||||||
|
|
||||||
| use super::*; | ||||||
| use crate::shim::actors::miner::{MinerInfo, MinerPower, Partition}; | ||||||
| use crate::shim::actors::verifreg::ext::VerifiedRegistryStateExt as _; | ||||||
| use crate::shim::actors::verifreg::{Allocation, AllocationID, Claim}; | ||||||
| use ahash::HashMap; | ||||||
| use fil_actor_verifreg_state::v12::DataCap; | ||||||
| use fil_actor_verifreg_state::v13::ClaimID; | ||||||
| use fil_actors_shared::fvm_ipld_bitfield::BitField; | ||||||
|
|
||||||
| impl<DB> StateManager<DB> | ||||||
| where | ||||||
| DB: Blockstore + Send + Sync + 'static, | ||||||
| { | ||||||
| /// Retrieves market state | ||||||
| pub fn market_state(&self, ts: &Tipset) -> Result<market::State, Error> { | ||||||
| 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<MarketBalance, Error> { | ||||||
| let market_state = self.market_state(ts)?; | ||||||
| let new_addr = self.lookup_required_id(addr, ts)?; | ||||||
| let out = MarketBalance { | ||||||
| escrow: { | ||||||
| market_state | ||||||
| .escrow_table(self.blockstore())? | ||||||
| .get(&new_addr)? | ||||||
| }, | ||||||
| locked: { | ||||||
| market_state | ||||||
| .locked_table(self.blockstore())? | ||||||
| .get(&new_addr)? | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| Ok(out) | ||||||
| } | ||||||
|
|
||||||
| /// Retrieves miner info. | ||||||
| pub fn miner_info(&self, addr: &Address, ts: &Tipset) -> Result<MinerInfo, Error> { | ||||||
| let actor = self | ||||||
| .get_actor(addr, *ts.parent_state())? | ||||||
| .ok_or_else(|| Error::state("Miner actor not found"))?; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| let state = miner::State::load(self.blockstore(), actor.code, actor.state)?; | ||||||
|
|
||||||
| Ok(state.info(self.blockstore())?) | ||||||
| } | ||||||
|
|
||||||
| /// Retrieves miner faults. | ||||||
| pub fn miner_faults(&self, addr: &Address, ts: &Tipset) -> Result<BitField, Error> { | ||||||
| self.all_partition_sectors(addr, ts, |partition| partition.faulty_sectors().clone()) | ||||||
| } | ||||||
|
|
||||||
| /// Retrieves miner recoveries. | ||||||
| pub fn miner_recoveries(&self, addr: &Address, ts: &Tipset) -> Result<BitField, Error> { | ||||||
| self.all_partition_sectors(addr, ts, |partition| partition.recovering_sectors().clone()) | ||||||
| } | ||||||
|
|
||||||
| fn all_partition_sectors( | ||||||
| &self, | ||||||
| addr: &Address, | ||||||
| ts: &Tipset, | ||||||
| get_sector: impl Fn(Partition<'_>) -> BitField, | ||||||
| ) -> Result<BitField, Error> { | ||||||
| let actor = self | ||||||
| .get_actor(addr, *ts.parent_state())? | ||||||
| .ok_or_else(|| Error::state("Miner actor not found"))?; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| let state = miner::State::load(self.blockstore(), actor.code, actor.state)?; | ||||||
|
|
||||||
| let mut partitions = Vec::new(); | ||||||
|
|
||||||
| state.for_each_deadline( | ||||||
| &self.chain_config().policy, | ||||||
| self.blockstore(), | ||||||
| |_, deadline| { | ||||||
| deadline.for_each(self.blockstore(), |_, partition| { | ||||||
| partitions.push(get_sector(partition)); | ||||||
| Ok(()) | ||||||
| }) | ||||||
| }, | ||||||
| )?; | ||||||
|
|
||||||
| Ok(BitField::union(partitions.iter())) | ||||||
| } | ||||||
|
|
||||||
| /// Retrieves miner power. | ||||||
| pub fn miner_power(&self, addr: &Address, ts: &Tipset) -> Result<MinerPower, Error> { | ||||||
| if let Some((miner_power, total_power)) = self.get_power(ts.parent_state(), Some(addr))? { | ||||||
| return Ok(MinerPower { | ||||||
| miner_power, | ||||||
| total_power, | ||||||
| has_min_power: true, | ||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| Ok(MinerPower { | ||||||
| has_min_power: false, | ||||||
| miner_power: Default::default(), | ||||||
| total_power: Default::default(), | ||||||
| }) | ||||||
| } | ||||||
|
|
||||||
| pub fn get_verified_registry_actor_state( | ||||||
| &self, | ||||||
| ts: &Tipset, | ||||||
| ) -> anyhow::Result<verifreg::State> { | ||||||
| let act = self | ||||||
| .get_actor(&Address::VERIFIED_REGISTRY_ACTOR, *ts.parent_state()) | ||||||
| .map_err(Error::state)? | ||||||
| .ok_or_else(|| Error::state("actor not found"))?; | ||||||
| verifreg::State::load(self.blockstore(), act.code, act.state) | ||||||
| } | ||||||
|
|
||||||
| pub fn get_claim( | ||||||
| &self, | ||||||
| addr: &Address, | ||||||
| ts: &Tipset, | ||||||
| claim_id: ClaimID, | ||||||
| ) -> anyhow::Result<Option<Claim>> { | ||||||
| let id_address = self.lookup_required_id(addr, ts)?; | ||||||
| let state = self.get_verified_registry_actor_state(ts)?; | ||||||
| state.get_claim(self.blockstore(), id_address, claim_id) | ||||||
| } | ||||||
|
|
||||||
| pub fn get_all_claims(&self, ts: &Tipset) -> anyhow::Result<HashMap<ClaimID, Claim>> { | ||||||
| let state = self.get_verified_registry_actor_state(ts)?; | ||||||
| state.get_all_claims(self.blockstore()) | ||||||
| } | ||||||
|
|
||||||
| pub fn get_allocation( | ||||||
| &self, | ||||||
| addr: &Address, | ||||||
| ts: &Tipset, | ||||||
| allocation_id: AllocationID, | ||||||
| ) -> anyhow::Result<Option<Allocation>> { | ||||||
| let id_address = self.lookup_required_id(addr, ts)?; | ||||||
| let state = self.get_verified_registry_actor_state(ts)?; | ||||||
| state.get_allocation(self.blockstore(), id_address.id()?, allocation_id) | ||||||
| } | ||||||
|
|
||||||
| pub fn get_all_allocations( | ||||||
| &self, | ||||||
| ts: &Tipset, | ||||||
| ) -> anyhow::Result<HashMap<AllocationID, Allocation>> { | ||||||
| let state = self.get_verified_registry_actor_state(ts)?; | ||||||
| state.get_all_allocations(self.blockstore()) | ||||||
| } | ||||||
|
|
||||||
| pub fn verified_client_status( | ||||||
| &self, | ||||||
| addr: &Address, | ||||||
| ts: &Tipset, | ||||||
| ) -> anyhow::Result<Option<DataCap>> { | ||||||
| let id = self.lookup_required_id(addr, ts)?; | ||||||
| let network_version = self.get_network_version(ts.epoch()); | ||||||
|
|
||||||
| // Pre-network v17 (actor v9), the verified client data cap lives in the | ||||||
| // verified registry actor; at/after v17 it lives in the datacap token actor. | ||||||
| // Original: https://github.com/filecoin-project/lotus/blob/5e76b05b17771da6939c7b0bf65127c3dc70ee23/node/impl/full/state.go#L1627-L1664. | ||||||
| if (u32::from(network_version.0)) < 17 { | ||||||
| let state = self.get_verified_registry_actor_state(ts)?; | ||||||
| return state.verified_client_data_cap(self.blockstore(), id); | ||||||
| } | ||||||
|
|
||||||
| let act = self | ||||||
| .get_actor(&Address::DATACAP_TOKEN_ACTOR, *ts.parent_state()) | ||||||
| .map_err(Error::state)? | ||||||
| .ok_or_else(|| Error::state("Miner actor not found"))?; | ||||||
|
Comment on lines
+171
to
+174
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the actor name in this error path. Line 174 reports 🤖 Prompt for AI Agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @akaladarshi is this valid?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see this is from the original code, but maybe we should correct it here |
||||||
|
|
||||||
| let state = datacap::State::load(self.blockstore(), act.code, act.state)?; | ||||||
|
|
||||||
| state.verified_client_data_cap(self.blockstore(), id) | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| // Copyright 2019-2026 ChainSafe Systems | ||
| // SPDX-License-Identifier: Apache-2.0, MIT | ||
|
|
||
| use super::*; | ||
| use crate::shim::address::{Payload, Protocol}; | ||
| use anyhow::Context as _; | ||
| use bls_signatures::{PublicKey as BlsPublicKey, Serialize as _}; | ||
|
|
||
| impl<DB> StateManager<DB> | ||
| where | ||
| DB: Blockstore + Send + Sync + 'static, | ||
| { | ||
| /// Returns a BLS public key from provided address | ||
| pub fn get_bls_public_key( | ||
| db: &Arc<DB>, | ||
| addr: &Address, | ||
| state_cid: cid::Cid, | ||
| ) -> Result<BlsPublicKey, Error> { | ||
| let state = StateTree::new_from_root(Arc::clone(db), &state_cid) | ||
| .map_err(|e| Error::Other(e.to_string()))?; | ||
| let kaddr = | ||
| resolve_to_key_addr(&state, db, addr).context("Failed to resolve key address")?; | ||
|
|
||
| match kaddr.into_payload() { | ||
| Payload::BLS(key) => BlsPublicKey::from_bytes(&key) | ||
| .context("Failed to construct bls public key") | ||
| .map_err(Error::from), | ||
| _ => Err(Error::state( | ||
| "Address must be BLS address to load bls public key", | ||
| )), | ||
| } | ||
| } | ||
|
|
||
| /// Looks up ID [Address] from the state at the given [Tipset]. | ||
| pub fn lookup_id(&self, addr: &Address, ts: &Tipset) -> Result<Option<Address>, Error> { | ||
| let state_tree = StateTree::new_from_root(self.blockstore_owned(), ts.parent_state()) | ||
| .map_err(|e| format!("{e:?}"))?; | ||
| Ok(state_tree | ||
| .lookup_id(addr) | ||
| .map_err(|e| Error::Other(e.to_string()))? | ||
| .map(Address::new_id)) | ||
| } | ||
|
|
||
| /// Looks up required ID [Address] from the state at the given [Tipset]. | ||
| pub fn lookup_required_id(&self, addr: &Address, ts: &Tipset) -> Result<Address, Error> { | ||
| self.lookup_id(addr, ts)? | ||
| .ok_or_else(|| Error::Other(format!("Failed to lookup the id address {addr}"))) | ||
| } | ||
|
|
||
| /// Similar to `resolve_to_key_addr` in the `forest_vm` [`crate::state_manager`] but does not | ||
| /// allow `Actor` type of addresses. Uses `ts` to generate the VM state. | ||
| pub async fn resolve_to_key_addr( | ||
| self: &Arc<Self>, | ||
| addr: &Address, | ||
| ts: &Tipset, | ||
| ) -> anyhow::Result<Address> { | ||
| match addr.protocol() { | ||
| Protocol::BLS | Protocol::Secp256k1 | Protocol::Delegated => return Ok(*addr), | ||
| Protocol::Actor => { | ||
| return Err(Error::Other( | ||
| "cannot resolve actor address to key address".to_string(), | ||
| ) | ||
| .into()); | ||
| } | ||
| _ => {} | ||
| }; | ||
|
|
||
| // First try to resolve the actor in the parent state, so we don't have to | ||
| // compute anything. | ||
| let state = StateTree::new_from_root(self.blockstore_owned(), ts.parent_state())?; | ||
| if let Ok(addr) = resolve_to_key_addr(&state, self.blockstore(), addr) { | ||
| return Ok(addr); | ||
| } | ||
|
|
||
| // If that fails, compute the tip-set and try again. | ||
| let TipsetState { state_root, .. } = self.load_tipset_state(ts).await?; | ||
| let state = StateTree::new_from_root(self.blockstore_owned(), &state_root)?; | ||
|
|
||
| resolve_to_key_addr(&state, self.blockstore(), addr) | ||
| } | ||
|
|
||
| pub async fn resolve_to_deterministic_address( | ||
| self: &Arc<Self>, | ||
| address: Address, | ||
| ts: &Tipset, | ||
| ) -> anyhow::Result<Address> { | ||
| use crate::shim::address::Protocol::*; | ||
| match address.protocol() { | ||
| BLS | Secp256k1 | Delegated => Ok(address), | ||
| Actor => anyhow::bail!("cannot resolve actor address to key address"), | ||
| _ => { | ||
| // First try to resolve the actor in the parent state, so we don't have to compute anything. | ||
| if let Ok(state) = | ||
| StateTree::new_from_root(self.blockstore_owned(), ts.parent_state()) | ||
| && let Ok(address) = state | ||
| .resolve_to_deterministic_addr(self.chain_store().blockstore(), address) | ||
| { | ||
| return Ok(address); | ||
| } | ||
|
|
||
| // If that fails, compute the tip-set and try again. | ||
| let TipsetState { state_root, .. } = self.load_tipset_state(ts).await?; | ||
| let state = StateTree::new_from_root(self.blockstore_owned(), &state_root)?; | ||
| state.resolve_to_deterministic_addr(self.chain_store().blockstore(), address) | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add
addrto the info to make it more useful