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