use crate::convert::*;
use crate::list_miners_for_state;
use crate::Policy;
use anyhow::Context;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_shared::{address::Address, econ::TokenAmount, sector::StoragePower};
use serde::{Deserialize, Serialize};
use crate::{io::get_obj, FilterEstimate};
pub const ADDRESS: Address = Address::new_id(4);
pub type Method = fil_actor_power_state::v8::Method;
pub fn is_v8_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v8.contains(cid)
}
pub fn is_v9_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v9.contains(cid)
}
pub fn is_v10_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v10.contains(cid)
}
pub fn is_v11_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v11.contains(cid)
}
pub fn is_v12_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v12.contains(cid)
}
pub fn is_v13_power_cid(cid: &Cid) -> bool {
crate::KNOWN_CIDS.actor.power.v13.contains(cid)
}
#[derive(Serialize, Debug)]
#[serde(untagged)]
pub enum State {
V8(fil_actor_power_state::v8::State),
V9(fil_actor_power_state::v9::State),
V10(fil_actor_power_state::v10::State),
V11(fil_actor_power_state::v11::State),
V12(fil_actor_power_state::v12::State),
V13(fil_actor_power_state::v13::State),
}
impl State {
pub fn load<BS>(store: &BS, code: Cid, state: Cid) -> anyhow::Result<State>
where
BS: Blockstore,
{
if is_v8_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V8)
.context("Actor state doesn't exist in store");
}
if is_v9_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V9)
.context("Actor state doesn't exist in store");
}
if is_v10_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V10)
.context("Actor state doesn't exist in store");
}
if is_v11_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V11)
.context("Actor state doesn't exist in store");
}
if is_v12_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V12)
.context("Actor state doesn't exist in store");
}
if is_v13_power_cid(&code) {
return get_obj(store, &state)?
.map(State::V13)
.context("Actor state doesn't exist in store");
}
Err(anyhow::anyhow!("Unknown power actor code {}", code))
}
pub fn into_total_quality_adj_power(self) -> StoragePower {
match self {
State::V8(st) => st.total_quality_adj_power,
State::V9(st) => st.total_quality_adj_power,
State::V10(st) => st.total_quality_adj_power,
State::V11(st) => st.total_quality_adj_power,
State::V12(st) => st.total_quality_adj_power,
State::V13(st) => st.total_quality_adj_power,
}
}
pub fn list_all_miners<BS: Blockstore>(self, store: &BS) -> anyhow::Result<Vec<Address>> {
match self {
State::V8(st) => list_miners_for_state!(st, store, v8),
State::V9(st) => list_miners_for_state!(st, store, v9),
State::V10(st) => list_miners_for_state!(st, store, v10),
State::V11(st) => list_miners_for_state!(st, store, v11),
State::V12(st) => {
let claims = st.load_claims(store)?;
let mut miners = Vec::new();
claims.for_each(|addr, _claim| {
miners.push(from_address_v4_to_v2(addr));
Ok(())
})?;
Ok(miners)
}
State::V13(st) => {
let claims = st.load_claims(store)?;
let mut miners = Vec::new();
claims.for_each(|addr, _claim| {
miners.push(from_address_v4_to_v2(addr));
Ok(())
})?;
Ok(miners)
}
}
}
pub fn total_power(&self) -> Claim {
match self {
State::V8(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
State::V9(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
State::V10(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
State::V11(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
State::V12(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
State::V13(st) => Claim {
raw_byte_power: st.total_raw_byte_power.clone(),
quality_adj_power: st.total_quality_adj_power.clone(),
},
}
}
pub fn into_total_locked(self) -> TokenAmount {
match self {
State::V8(st) => st.into_total_locked(),
State::V9(st) => st.into_total_locked(),
State::V10(st) => from_token_v3_to_v2(&st.into_total_locked()),
State::V11(st) => from_token_v3_to_v2(&st.into_total_locked()),
State::V12(st) => from_token_v4_to_v2(&st.into_total_locked()),
State::V13(st) => from_token_v4_to_v2(&st.into_total_locked()),
}
}
pub fn miner_power<BS: Blockstore>(
&self,
s: &BS,
miner: &Address,
) -> anyhow::Result<Option<Claim>> {
match self {
State::V8(st) => Ok(st.miner_power(&s, miner)?.map(From::from)),
State::V9(st) => Ok(st.miner_power(&s, miner)?.map(From::from)),
State::V10(st) => Ok(st
.miner_power(&s, &from_address_v2_to_v3(*miner))?
.map(From::from)),
State::V11(st) => Ok(st
.miner_power(&s, &from_address_v2_to_v3(*miner))?
.map(From::from)),
State::V12(st) => Ok(st
.miner_power(&s, &from_address_v2_to_v4(*miner))?
.map(From::from)),
State::V13(st) => Ok(st
.miner_power(&s, &from_address_v2_to_v4(*miner))?
.map(From::from)),
}
}
pub fn miner_nominal_power_meets_consensus_minimum<BS: Blockstore>(
&self,
policy: &Policy,
s: &BS,
miner: &Address,
) -> anyhow::Result<bool> {
match self {
State::V8(st) => st.miner_nominal_power_meets_consensus_minimum(
&from_policy_v10_to_v9(policy),
&s,
miner,
),
State::V9(st) => st.miner_nominal_power_meets_consensus_minimum(
&from_policy_v10_to_v9(policy),
&s,
miner,
),
State::V10(st) => st
.miner_nominal_power_meets_consensus_minimum(policy, &s, miner.id()?)
.map(|(_, bool_val)| bool_val)
.map_err(|e| anyhow::anyhow!("{}", e)),
State::V11(st) => st
.miner_nominal_power_meets_consensus_minimum(
&from_policy_v10_to_v11(policy),
&s,
miner.id()?,
)
.map(|(_, bool_val)| bool_val)
.map_err(|e| anyhow::anyhow!("{}", e)),
State::V12(st) => st
.miner_nominal_power_meets_consensus_minimum(
&from_policy_v10_to_v12(policy),
&s,
miner.id()?,
)
.map(|(_, bool_val)| bool_val)
.map_err(|e| anyhow::anyhow!("{}", e)),
State::V13(st) => st
.miner_nominal_power_meets_consensus_minimum(
&from_policy_v10_to_v13(policy),
&s,
miner.id()?,
)
.map(|(_, bool_val)| bool_val)
.map_err(|e| anyhow::anyhow!("{}", e)),
}
}
pub fn total_power_smoothed(&self) -> FilterEstimate {
match self {
State::V8(st) => st.this_epoch_qa_power_smoothed.clone(),
State::V9(st) => st.this_epoch_qa_power_smoothed.clone(),
State::V10(st) => {
from_filter_estimate_v3_to_v2(st.this_epoch_qa_power_smoothed.clone())
}
State::V11(st) => {
from_filter_estimate_v3_to_v2(st.this_epoch_qa_power_smoothed.clone())
}
State::V12(st) => {
from_filter_estimate_v4_to_v2(st.this_epoch_qa_power_smoothed.clone())
}
State::V13(st) => {
from_filter_estimate_v4_to_v2(st.this_epoch_qa_power_smoothed.clone())
}
}
}
pub fn total_locked(&self) -> TokenAmount {
match self {
State::V8(st) => st.total_pledge_collateral.clone(),
State::V9(st) => st.total_pledge_collateral.clone(),
State::V10(st) => from_token_v3_to_v2(&st.total_pledge_collateral),
State::V11(st) => from_token_v3_to_v2(&st.total_pledge_collateral),
State::V12(st) => from_token_v4_to_v2(&st.total_pledge_collateral.clone()),
State::V13(st) => from_token_v4_to_v2(&st.total_pledge_collateral.clone()),
}
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Claim {
pub raw_byte_power: StoragePower,
pub quality_adj_power: StoragePower,
}
impl From<fil_actor_power_state::v8::Claim> for Claim {
fn from(cl: fil_actor_power_state::v8::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
impl From<fil_actor_power_state::v9::Claim> for Claim {
fn from(cl: fil_actor_power_state::v9::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
impl From<fil_actor_power_state::v10::Claim> for Claim {
fn from(cl: fil_actor_power_state::v10::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
impl From<fil_actor_power_state::v11::Claim> for Claim {
fn from(cl: fil_actor_power_state::v11::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
impl From<fil_actor_power_state::v12::Claim> for Claim {
fn from(cl: fil_actor_power_state::v12::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
impl From<fil_actor_power_state::v13::Claim> for Claim {
fn from(cl: fil_actor_power_state::v13::Claim) -> Self {
Self {
raw_byte_power: cl.raw_byte_power,
quality_adj_power: cl.quality_adj_power,
}
}
}
#[macro_export]
macro_rules! list_miners_for_state {
($state:ident, $store:ident, $version:ident) => {{
let claims =
fil_actors_shared::$version::make_map_with_root::<_, Claim>(&$state.claims, $store)?;
let mut miners = Vec::new();
claims.for_each(|bytes, _claim| {
miners.push(Address::from_bytes(bytes).expect("Cannot get address from bytes"));
Ok(())
})?;
Ok(miners)
}};
}