Skip to content

Commit

Permalink
Power actor: Export methods to CreateMiner and get miner counts (#868)
Browse files Browse the repository at this point in the history
* Power: Export CreateMiner

* Power Actor: Export MinerCount and MinerConsensusCount

* Update actors/power/src/lib.rs

Co-authored-by: Alex <445306+anorth@users.noreply.github.com>

Co-authored-by: Alex <445306+anorth@users.noreply.github.com>
  • Loading branch information
arajasek and anorth committed Nov 29, 2022
1 parent e861a7d commit 6fbbcc9
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 14 deletions.
33 changes: 32 additions & 1 deletion actors/power/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ pub enum Method {
SubmitPoRepForBulkVerify = 8,
CurrentTotalPower = 9,
// Method numbers derived from FRC-0042 standards
CreateMinerExported = frc42_dispatch::method_hash!("CreateMiner"),
NetworkRawPowerExported = frc42_dispatch::method_hash!("NetworkRawPower"),
MinerRawPowerExported = frc42_dispatch::method_hash!("MinerRawPower"),
MinerCountExported = frc42_dispatch::method_hash!("MinerCount"),
MinerConsensusCountExported = frc42_dispatch::method_hash!("MinerConsensusCount"),
}

pub const ERR_TOO_MANY_PROVE_COMMITS: ExitCode = ExitCode::new(32);
Expand Down Expand Up @@ -396,6 +399,26 @@ impl Actor {
Ok(MinerRawPowerReturn { raw_byte_power, meets_consensus_minimum })
}

/// Returns the total number of miners created, regardless of whether or not
/// they have any pledged storage.
fn miner_count(rt: &mut impl Runtime) -> Result<MinerCountReturn, ActorError> {
rt.validate_immediate_caller_accept_any()?;
let st: State = rt.state()?;

Ok(MinerCountReturn { miner_count: st.miner_count })
}

/// Returns the total number of miners that have more than the consensus minimum amount of storage active.
/// Active means that the storage must not be faulty.
fn miner_consensus_count(
rt: &mut impl Runtime,
) -> Result<MinerConsensusCountReturn, ActorError> {
rt.validate_immediate_caller_accept_any()?;
let st: State = rt.state()?;

Ok(MinerConsensusCountReturn { miner_consensus_count: st.miner_above_min_power_count })
}

fn process_batch_proof_verifies(
rt: &mut impl Runtime,
rewret: &ThisEpochRewardReturn,
Expand Down Expand Up @@ -663,7 +686,7 @@ impl ActorCode for Actor {
Self::constructor(rt)?;
Ok(RawBytes::default())
}
Some(Method::CreateMiner) => {
Some(Method::CreateMiner) | Some(Method::CreateMinerExported) => {
let res = Self::create_miner(rt, cbor::deserialize_params(params)?)?;
Ok(RawBytes::serialize(res)?)
}
Expand Down Expand Up @@ -700,6 +723,14 @@ impl ActorCode for Actor {
let res = Self::miner_raw_power(rt, cbor::deserialize_params(params)?)?;
Ok(RawBytes::serialize(res)?)
}
Some(Method::MinerCountExported) => {
let res = Self::miner_count(rt)?;
Ok(RawBytes::serialize(res)?)
}
Some(Method::MinerConsensusCountExported) => {
let res = Self::miner_consensus_count(rt)?;
Ok(RawBytes::serialize(res)?)
}
None => Err(actor_error!(unhandled_message; "Invalid method")),
}
}
Expand Down
12 changes: 12 additions & 0 deletions actors/power/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,15 @@ pub struct MinerRawPowerReturn {
}

impl Cbor for MinerRawPowerReturn {}

#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
#[serde(transparent)]
pub struct MinerCountReturn {
pub miner_count: i64,
}

#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
#[serde(transparent)]
pub struct MinerConsensusCountReturn {
pub miner_consensus_count: i64,
}
29 changes: 22 additions & 7 deletions actors/power/tests/harness/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use cid::Cid;
use fil_actor_power::detail::GAS_ON_SUBMIT_VERIFY_SEAL;
use fil_actor_power::epoch_key;
use fil_actor_power::ext::miner::ConfirmSectorProofsParams;
use fil_actor_power::ext::miner::CONFIRM_SECTOR_PROOFS_VALID_METHOD;
use fil_actor_power::ext::reward::Method::ThisEpochReward;
use fil_actor_power::ext::reward::UPDATE_NETWORK_KPI;
use fil_actor_power::testing::check_state_invariants;
use fil_actor_power::CronEvent;
use fil_actor_power::EnrollCronEventParams;
use fil_actor_power::CRON_QUEUE_AMT_BITWIDTH;
use fil_actor_power::CRON_QUEUE_HAMT_BITWIDTH;
use fil_actor_power::{epoch_key, MinerCountReturn};
use fil_actor_power::{CronEvent, MinerConsensusCountReturn};
use fil_actors_runtime::runtime::RuntimePolicy;
use fil_actors_runtime::test_utils::CRON_ACTOR_CODE_ID;
use fil_actors_runtime::Multimap;
Expand Down Expand Up @@ -210,9 +210,15 @@ impl Harness {
keys.iter().map(|k| Address::from_bytes(k).unwrap()).collect::<Vec<_>>()
}

pub fn miner_count(&self, rt: &MockRuntime) -> i64 {
let st: State = rt.get_state();
st.miner_count
pub fn miner_count(&self, rt: &mut MockRuntime) -> i64 {
rt.expect_validate_caller_any();
let ret: MinerCountReturn = rt
.call::<PowerActor>(Method::MinerCountExported as MethodNum, &RawBytes::default())
.unwrap()
.deserialize()
.unwrap();

ret.miner_count
}

pub fn this_epoch_baseline_power(&self) -> &StoragePower {
Expand Down Expand Up @@ -366,8 +372,17 @@ impl Harness {
}

pub fn expect_miners_above_min_power(&self, rt: &mut MockRuntime, count: i64) {
let st: State = rt.get_state();
assert_eq!(count, st.miner_above_min_power_count);
rt.expect_validate_caller_any();
let ret: MinerConsensusCountReturn = rt
.call::<PowerActor>(
Method::MinerConsensusCountExported as MethodNum,
&RawBytes::default(),
)
.unwrap()
.deserialize()
.unwrap();

assert_eq!(count, ret.miner_consensus_count);
}

pub fn expect_query_network_info(&self, rt: &mut MockRuntime) {
Expand Down
80 changes: 74 additions & 6 deletions actors/power/tests/power_actor_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use fvm_shared::clock::ChainEpoch;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::sector::{RegisteredPoStProof, StoragePower};
use fvm_shared::MethodNum;
use num_traits::Zero;
use std::ops::Neg;

use fil_actor_power::{
consensus_miner_min_power, Actor as PowerActor, Actor, CreateMinerParams,
consensus_miner_min_power, Actor as PowerActor, Actor, CreateMinerParams, CreateMinerReturn,
EnrollCronEventParams, Method, MinerRawPowerParams, MinerRawPowerReturn, NetworkRawPowerReturn,
State, UpdateClaimedPowerParams, CONSENSUS_MINER_MIN_MINERS,
};
Expand Down Expand Up @@ -326,8 +327,7 @@ fn new_miner_updates_miner_above_min_power_count() {
h.window_post_proof = test.proof;
h.create_miner_basic(&mut rt, *OWNER, *OWNER, MINER1).unwrap();

let st: State = rt.get_state();
assert_eq!(test.expected_miners, st.miner_above_min_power_count);
h.expect_miners_above_min_power(&mut rt, test.expected_miners);
h.check_state(&rt);
}
}
Expand Down Expand Up @@ -372,8 +372,7 @@ fn power_accounting_crossing_threshold() {
let expected_total_above = &(power_unit * 4);
h.expect_total_power_eager(&mut rt, expected_total_above, &(expected_total_above * 10));

let st: State = rt.get_state();
assert_eq!(4, st.miner_above_min_power_count);
h.expect_miners_above_min_power(&mut rt, 4);

// Less than 4 miners above threshold again small miner power is counted again
h.update_claimed_power(&mut rt, MINER4, &delta.neg(), &(delta.neg() * 10));
Expand Down Expand Up @@ -1011,7 +1010,7 @@ mod cron_tests {
assert!(h.get_claim(&rt, &miner1).is_none());

// miner count has been reduced to 1
assert_eq!(h.miner_count(&rt), 1);
assert_eq!(h.miner_count(&mut rt), 1);

// next epoch, only the reward actor is invoked
rt.set_epoch(3);
Expand Down Expand Up @@ -1440,3 +1439,72 @@ mod submit_porep_for_bulk_verify_tests {
h.check_state(&rt);
}
}

#[test]
fn create_miner_restricted_correctly() {
let (h, mut rt) = setup();

let peer = "miner".as_bytes().to_vec();
let multiaddrs = vec![BytesDe("multiaddr".as_bytes().to_vec())];

let params = serialize(
&CreateMinerParams {
owner: *OWNER,
worker: *OWNER,
window_post_proof_type: RegisteredPoStProof::StackedDRGWinning2KiBV1,
peer: peer.clone(),
multiaddrs: multiaddrs.clone(),
},
"create miner params",
)
.unwrap();

rt.set_caller(make_identity_cid(b"1234"), *OWNER);

// cannot call the unexported method
expect_abort_contains_message(
ExitCode::USR_FORBIDDEN,
"must be built-in",
rt.call::<PowerActor>(Method::CreateMiner as MethodNum, &params),
);

// can call the exported method

rt.expect_validate_caller_any();
let expected_init_params = ExecParams {
code_cid: *MINER_ACTOR_CODE_ID,
constructor_params: serialize(
&MinerConstructorParams {
owner: *OWNER,
worker: *OWNER,
control_addresses: vec![],
window_post_proof_type: RegisteredPoStProof::StackedDRGWinning2KiBV1,
peer_id: peer,
multi_addresses: multiaddrs,
},
"minerctor params",
)
.unwrap(),
};
let create_miner_ret = CreateMinerReturn { id_address: *MINER, robust_address: *ACTOR };
rt.expect_send(
INIT_ACTOR_ADDR,
EXEC_METHOD,
RawBytes::serialize(expected_init_params).unwrap(),
TokenAmount::zero(),
RawBytes::serialize(create_miner_ret).unwrap(),
ExitCode::OK,
);

let ret: CreateMinerReturn = rt
.call::<PowerActor>(Method::CreateMinerExported as MethodNum, &params)
.unwrap()
.deserialize()
.unwrap();
rt.verify();

assert_eq!(ret.id_address, *MINER);
assert_eq!(ret.robust_address, *ACTOR);

h.check_state(&rt);
}

0 comments on commit 6fbbcc9

Please sign in to comment.