Skip to main content

forest/state_manager/
actor_queries.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use super::*;
5use crate::shim::actors::miner::{MinerInfo, MinerPower, Partition};
6use crate::shim::actors::verifreg::ext::VerifiedRegistryStateExt as _;
7use crate::shim::actors::verifreg::{Allocation, AllocationID, Claim};
8use ahash::HashMap;
9use fil_actor_verifreg_state::v12::DataCap;
10use fil_actor_verifreg_state::v13::ClaimID;
11use fil_actors_shared::fvm_ipld_bitfield::BitField;
12
13impl<DB> StateManager<DB>
14where
15    DB: Blockstore + Send + Sync + 'static,
16{
17    /// Retrieves market state
18    pub fn market_state(&self, ts: &Tipset) -> Result<market::State, Error> {
19        let actor = self.get_required_actor(&Address::MARKET_ACTOR, *ts.parent_state())?;
20        let market_state = market::State::load(self.blockstore(), actor.code, actor.state)?;
21        Ok(market_state)
22    }
23
24    /// Retrieves market balance in escrow and locked tables.
25    pub fn market_balance(&self, addr: &Address, ts: &Tipset) -> Result<MarketBalance, Error> {
26        let market_state = self.market_state(ts)?;
27        let new_addr = self.lookup_required_id(addr, ts)?;
28        let out = MarketBalance {
29            escrow: {
30                market_state
31                    .escrow_table(self.blockstore())?
32                    .get(&new_addr)?
33            },
34            locked: {
35                market_state
36                    .locked_table(self.blockstore())?
37                    .get(&new_addr)?
38            },
39        };
40
41        Ok(out)
42    }
43
44    /// Retrieves miner info.
45    pub fn miner_info(&self, addr: &Address, ts: &Tipset) -> Result<MinerInfo, Error> {
46        let actor = self.get_actor(addr, *ts.parent_state())?.ok_or_else(|| {
47            Error::state(format!(
48                "Miner actor {addr} not found at epoch {}",
49                ts.epoch()
50            ))
51        })?;
52        let state = miner::State::load(self.blockstore(), actor.code, actor.state)?;
53
54        Ok(state.info(self.blockstore())?)
55    }
56
57    /// Retrieves miner faults.
58    pub fn miner_faults(&self, addr: &Address, ts: &Tipset) -> Result<BitField, Error> {
59        self.all_partition_sectors(addr, ts, |partition| partition.faulty_sectors().clone())
60    }
61
62    /// Retrieves miner recoveries.
63    pub fn miner_recoveries(&self, addr: &Address, ts: &Tipset) -> Result<BitField, Error> {
64        self.all_partition_sectors(addr, ts, |partition| partition.recovering_sectors().clone())
65    }
66
67    fn all_partition_sectors(
68        &self,
69        addr: &Address,
70        ts: &Tipset,
71        get_sector: impl Fn(Partition<'_>) -> BitField,
72    ) -> Result<BitField, Error> {
73        let actor = self.get_actor(addr, *ts.parent_state())?.ok_or_else(|| {
74            Error::state(format!(
75                "Miner actor {addr} not found at epoch {}",
76                ts.epoch()
77            ))
78        })?;
79
80        let state = miner::State::load(self.blockstore(), actor.code, actor.state)?;
81
82        let mut partitions = Vec::new();
83
84        state.for_each_deadline(
85            &self.chain_config().policy,
86            self.blockstore(),
87            |_, deadline| {
88                deadline.for_each(self.blockstore(), |_, partition| {
89                    partitions.push(get_sector(partition));
90                    Ok(())
91                })
92            },
93        )?;
94
95        Ok(BitField::union(partitions.iter()))
96    }
97
98    /// Retrieves miner power.
99    pub fn miner_power(&self, addr: &Address, ts: &Tipset) -> Result<MinerPower, Error> {
100        if let Some((miner_power, total_power)) = self.get_power(ts.parent_state(), Some(addr))? {
101            return Ok(MinerPower {
102                miner_power,
103                total_power,
104                has_min_power: true,
105            });
106        }
107
108        Ok(MinerPower {
109            has_min_power: false,
110            miner_power: Default::default(),
111            total_power: Default::default(),
112        })
113    }
114
115    pub fn get_verified_registry_actor_state(
116        &self,
117        ts: &Tipset,
118    ) -> anyhow::Result<verifreg::State> {
119        let act = self
120            .get_actor(&Address::VERIFIED_REGISTRY_ACTOR, *ts.parent_state())
121            .map_err(Error::state)?
122            .ok_or_else(|| Error::state("actor not found"))?;
123        verifreg::State::load(self.blockstore(), act.code, act.state)
124    }
125    pub fn get_claim(
126        &self,
127        addr: &Address,
128        ts: &Tipset,
129        claim_id: ClaimID,
130    ) -> anyhow::Result<Option<Claim>> {
131        let id_address = self.lookup_required_id(addr, ts)?;
132        let state = self.get_verified_registry_actor_state(ts)?;
133        state.get_claim(self.blockstore(), id_address, claim_id)
134    }
135
136    pub fn get_all_claims(&self, ts: &Tipset) -> anyhow::Result<HashMap<ClaimID, Claim>> {
137        let state = self.get_verified_registry_actor_state(ts)?;
138        state.get_all_claims(self.blockstore())
139    }
140
141    pub fn get_allocation(
142        &self,
143        addr: &Address,
144        ts: &Tipset,
145        allocation_id: AllocationID,
146    ) -> anyhow::Result<Option<Allocation>> {
147        let id_address = self.lookup_required_id(addr, ts)?;
148        let state = self.get_verified_registry_actor_state(ts)?;
149        state.get_allocation(self.blockstore(), id_address.id()?, allocation_id)
150    }
151
152    pub fn get_all_allocations(
153        &self,
154        ts: &Tipset,
155    ) -> anyhow::Result<HashMap<AllocationID, Allocation>> {
156        let state = self.get_verified_registry_actor_state(ts)?;
157        state.get_all_allocations(self.blockstore())
158    }
159
160    pub fn verified_client_status(
161        &self,
162        addr: &Address,
163        ts: &Tipset,
164    ) -> anyhow::Result<Option<DataCap>> {
165        let id = self.lookup_required_id(addr, ts)?;
166        let network_version = self.get_network_version(ts.epoch());
167
168        // This is a copy of Lotus code, we need to treat all the actors below version 9
169        // differently. Which maps to network below version 17.
170        // Original: https://github.com/filecoin-project/lotus/blob/5e76b05b17771da6939c7b0bf65127c3dc70ee23/node/impl/full/state.go#L1627-L1664.
171        if (u32::from(network_version.0)) < 17 {
172            let state = self.get_verified_registry_actor_state(ts)?;
173            return state.verified_client_data_cap(self.blockstore(), id);
174        }
175
176        let act = self
177            .get_actor(&Address::DATACAP_TOKEN_ACTOR, *ts.parent_state())
178            .map_err(Error::state)?
179            .ok_or_else(|| {
180                Error::state(format!(
181                    "Data cap actor {} not found",
182                    Address::DATACAP_TOKEN_ACTOR
183                ))
184            })?;
185
186        let state = datacap::State::load(self.blockstore(), act.code, act.state)?;
187
188        state.verified_client_data_cap(self.blockstore(), id)
189    }
190}