Skip to content

Commit e8a521f

Browse files
committed
Power actor: Add exported getters for raw power (#810)
* Power actor: Add exported getters for raw power * FRC-XXXX is FRC-0042 * Power actor: network_raw_power: Return this_epoch_raw_byte_power * Power actor: miner_raw_power: Return whether above consensus min power * Power actor: types: serialize one-element structs transparently * Address review * Miner actor: Add exported getters for info and monies (#811) * Miner actor: Add exported getters for info and monies * Tweak comment * Miner actor: Replace GetWorker and GetControls with IsControllingAddress * Miner actor: Add exported GetAvailableBalance * Miner actor: Add exported GetVestingFunds * Miner actor: Remove exported monies getters * Miner actor: types: serialize one-element structs transparently * Address review * Address review
1 parent 43569bb commit e8a521f

File tree

17 files changed

+480
-50
lines changed

17 files changed

+480
-50
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

actors/datacap/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ lazy_static! {
4646

4747
/// Datacap actor methods available
4848
/// Some methods are available under 2 method nums -- a static number for "private" builtin actor usage,
49-
/// and via FRC-XXXX calling convention, with number determined by method name.
49+
/// and via FRC-0042 calling convention, with number determined by method name.
5050
#[derive(FromPrimitive)]
5151
#[repr(u64)]
5252
pub enum Method {
@@ -67,7 +67,7 @@ pub enum Method {
6767
Burn = 19,
6868
BurnFrom = 20,
6969
Allowance = 21,
70-
// Method numbers derived from FRC-XXXX standards
70+
// Method numbers derived from FRC-0042 standards
7171
NameExported = frc42_dispatch::method_hash!("Name"),
7272
SymbolExported = frc42_dispatch::method_hash!("Symbol"),
7373
TotalSupplyExported = frc42_dispatch::method_hash!("TotalSupply"),

actors/init/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum Method {
3434
Exec4 = 3,
3535
#[cfg(feature = "m2-native")]
3636
InstallCode = 4,
37-
// Method numbers derived from FRC-XXXX standards
37+
// Method numbers derived from FRC-0042 standards
3838
ExecExported = frc42_dispatch::method_hash!("Exec"),
3939
}
4040

actors/miner/src/lib.rs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use fvm_shared::reward::ThisEpochRewardReturn;
2323
use fvm_shared::sector::*;
2424
use fvm_shared::smooth::FilterEstimate;
2525
use fvm_shared::{MethodNum, METHOD_CONSTRUCTOR, METHOD_SEND};
26+
use itertools::Itertools;
2627
use log::{error, info, warn};
2728
use multihash::Code::Blake2b256;
2829
use num_derive::FromPrimitive;
@@ -123,9 +124,14 @@ pub enum Method {
123124
ChangeBeneficiary = 30,
124125
GetBeneficiary = 31,
125126
ExtendSectorExpiration2 = 32,
126-
// Method numbers derived from FRC-XXXX standards
127+
// Method numbers derived from FRC-0042 standards
127128
ChangeBenificiaryExported = frc42_dispatch::method_hash!("ChangeBeneficiary"),
128129
GetBeneficiaryExported = frc42_dispatch::method_hash!("GetBeneficiary"),
130+
GetOwnerExported = frc42_dispatch::method_hash!("GetOwner"),
131+
IsControllingAddressExported = frc42_dispatch::method_hash!("IsControllingAddress"),
132+
GetSectorSizeExported = frc42_dispatch::method_hash!("GetSectorSize"),
133+
GetAvailableBalanceExported = frc42_dispatch::method_hash!("GetAvailableBalance"),
134+
GetVestingFundsExported = frc42_dispatch::method_hash!("GetVestingFunds"),
129135
}
130136

131137
pub const ERR_BALANCE_INVARIANTS_BROKEN: ExitCode = ExitCode::new(1000);
@@ -205,6 +211,7 @@ impl Actor {
205211
Ok(())
206212
}
207213

214+
/// Returns the "controlling" addresses: the owner, the worker, and all control addresses
208215
fn control_addresses(rt: &mut impl Runtime) -> Result<GetControlAddressesReturn, ActorError> {
209216
rt.validate_immediate_caller_accept_any()?;
210217
let state: State = rt.state()?;
@@ -216,6 +223,71 @@ impl Actor {
216223
})
217224
}
218225

226+
/// Returns the owner address
227+
fn get_owner(rt: &mut impl Runtime) -> Result<GetOwnerReturn, ActorError> {
228+
rt.validate_immediate_caller_accept_any()?;
229+
let state: State = rt.state()?;
230+
let owner = get_miner_info(rt.store(), &state)?.owner;
231+
Ok(GetOwnerReturn { owner })
232+
}
233+
234+
/// Returns whether the provided address is "controlling".
235+
/// The "controlling" addresses are the Owner, the Worker, and all Control Addresses.
236+
fn is_controlling_address(
237+
rt: &mut impl Runtime,
238+
params: IsControllingAddressParam,
239+
) -> Result<IsControllingAddressReturn, ActorError> {
240+
rt.validate_immediate_caller_accept_any()?;
241+
let input = match rt.resolve_address(&params.address) {
242+
Some(a) => Address::new_id(a),
243+
None => return Ok(IsControllingAddressReturn { is_controlling: false }),
244+
};
245+
let state: State = rt.state()?;
246+
let info = get_miner_info(rt.store(), &state)?;
247+
let is_controlling = info
248+
.control_addresses
249+
.iter()
250+
.chain(&[info.worker, info.owner])
251+
.into_iter()
252+
.any(|a| *a == input);
253+
254+
Ok(IsControllingAddressReturn { is_controlling })
255+
}
256+
257+
/// Returns the miner's sector size
258+
fn get_sector_size(rt: &mut impl Runtime) -> Result<GetSectorSizeReturn, ActorError> {
259+
rt.validate_immediate_caller_accept_any()?;
260+
let state: State = rt.state()?;
261+
let sector_size = get_miner_info(rt.store(), &state)?.sector_size;
262+
Ok(GetSectorSizeReturn { sector_size })
263+
}
264+
265+
/// Returns the available balance of this miner.
266+
/// This is calculated as actor balance - (vesting funds + pre-commit deposit + ip requirement + fee debt)
267+
/// Can go negative if the miner is in IP debt.
268+
fn get_available_balance(
269+
rt: &mut impl Runtime,
270+
) -> Result<GetAvailableBalanceReturn, ActorError> {
271+
rt.validate_immediate_caller_accept_any()?;
272+
let state: State = rt.state()?;
273+
let available_balance =
274+
state.get_available_balance(&rt.current_balance()).map_err(|e| {
275+
actor_error!(illegal_state, "failed to calculate available balance: {}", e)
276+
})?;
277+
Ok(GetAvailableBalanceReturn { available_balance })
278+
}
279+
280+
/// Returns the funds vesting in this miner as a list of (vesting_epoch, vesting_amount) tuples.
281+
fn get_vesting_funds(rt: &mut impl Runtime) -> Result<GetVestingFundsReturn, ActorError> {
282+
rt.validate_immediate_caller_accept_any()?;
283+
let state: State = rt.state()?;
284+
let vesting_funds = state
285+
.load_vesting_funds(rt.store())
286+
.map_err(|e| actor_error!(illegal_state, "failed to load vesting funds: {}", e))?;
287+
let ret = vesting_funds.funds.into_iter().map(|v| (v.epoch, v.amount)).collect_vec();
288+
Ok(GetVestingFundsReturn { vesting_funds: ret })
289+
}
290+
219291
/// Will ALWAYS overwrite the existing control addresses with the control addresses passed in the params.
220292
/// If an empty addresses vector is passed, the control addresses will be cleared.
221293
/// A worker change will be scheduled if the worker passed in the params is different from the existing worker.
@@ -5001,6 +5073,26 @@ impl ActorCode for Actor {
50015073
Ok(RawBytes::default())
50025074
}
50035075
None => Err(actor_error!(unhandled_message, "Invalid method")),
5076+
Some(Method::GetOwnerExported) => {
5077+
let res = Self::get_owner(rt)?;
5078+
Ok(RawBytes::serialize(res)?)
5079+
}
5080+
Some(Method::IsControllingAddressExported) => {
5081+
let res = Self::is_controlling_address(rt, cbor::deserialize_params(params)?)?;
5082+
Ok(RawBytes::serialize(res)?)
5083+
}
5084+
Some(Method::GetSectorSizeExported) => {
5085+
let res = Self::get_sector_size(rt)?;
5086+
Ok(RawBytes::serialize(res)?)
5087+
}
5088+
Some(Method::GetAvailableBalanceExported) => {
5089+
let res = Self::get_available_balance(rt)?;
5090+
Ok(RawBytes::serialize(res)?)
5091+
}
5092+
Some(Method::GetVestingFundsExported) => {
5093+
let res = Self::get_vesting_funds(rt)?;
5094+
Ok(RawBytes::serialize(res)?)
5095+
}
50045096
}
50055097
}
50065098
}

actors/miner/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ impl State {
983983
&self,
984984
actor_balance: &TokenAmount,
985985
) -> anyhow::Result<TokenAmount> {
986-
// (actor_balance - &self.locked_funds) - &self.pre_commit_deposit
986+
// (actor_balance - &self.locked_funds) - &self.pre_commit_deposit - &self.initial_pledge
987987
Ok(self.get_unlocked_balance(actor_balance)? - &self.fee_debt)
988988
}
989989

actors/miner/src/types.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use fvm_shared::econ::TokenAmount;
1313
use fvm_shared::randomness::Randomness;
1414
use fvm_shared::sector::{
1515
PoStProof, RegisteredPoStProof, RegisteredSealProof, RegisteredUpdateProof, SectorNumber,
16-
StoragePower,
16+
SectorSize, StoragePower,
1717
};
1818
use fvm_shared::smooth::FilterEstimate;
1919

@@ -482,3 +482,50 @@ pub struct GetBeneficiaryReturn {
482482
}
483483

484484
impl Cbor for GetBeneficiaryReturn {}
485+
486+
#[derive(Serialize_tuple, Deserialize_tuple)]
487+
#[serde(transparent)]
488+
pub struct GetOwnerReturn {
489+
pub owner: Address,
490+
}
491+
492+
impl Cbor for GetOwnerReturn {}
493+
494+
#[derive(Serialize_tuple, Deserialize_tuple)]
495+
#[serde(transparent)]
496+
pub struct IsControllingAddressParam {
497+
pub address: Address,
498+
}
499+
500+
impl Cbor for IsControllingAddressParam {}
501+
502+
#[derive(Serialize_tuple, Deserialize_tuple)]
503+
#[serde(transparent)]
504+
pub struct IsControllingAddressReturn {
505+
pub is_controlling: bool,
506+
}
507+
508+
impl Cbor for IsControllingAddressReturn {}
509+
510+
#[derive(Serialize_tuple, Deserialize_tuple)]
511+
#[serde(transparent)]
512+
pub struct GetSectorSizeReturn {
513+
pub sector_size: SectorSize,
514+
}
515+
516+
impl Cbor for GetSectorSizeReturn {}
517+
518+
#[derive(Serialize_tuple, Deserialize_tuple)]
519+
#[serde(transparent)]
520+
pub struct GetAvailableBalanceReturn {
521+
pub available_balance: TokenAmount,
522+
}
523+
524+
impl Cbor for GetAvailableBalanceReturn {}
525+
526+
#[derive(Serialize_tuple, Deserialize_tuple)]
527+
pub struct GetVestingFundsReturn {
528+
pub vesting_funds: Vec<(ChainEpoch, TokenAmount)>,
529+
}
530+
531+
impl Cbor for GetVestingFundsReturn {}

actors/miner/tests/apply_rewards.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use fvm_shared::error::ExitCode;
1818
use fvm_shared::METHOD_SEND;
1919

2020
mod util;
21+
2122
use fil_actor_miner::testing::check_state_invariants;
2223
use util::*;
2324

@@ -165,11 +166,12 @@ fn rewards_pay_back_fee_debt() {
165166
assert!(st.locked_funds.is_zero());
166167

167168
let amt = rt.get_balance();
168-
let available_before = st.get_available_balance(&amt).unwrap();
169+
let available_before = h.get_available_balance(&mut rt).unwrap();
169170
assert!(available_before.is_positive());
170171
let init_fee_debt: TokenAmount = 2 * &amt; // FeeDebt twice total balance
171172
st.fee_debt = init_fee_debt.clone();
172-
let available_after = st.get_available_balance(&amt).unwrap();
173+
rt.replace_state(&st);
174+
let available_after = h.get_available_balance(&mut rt).unwrap();
173175
assert!(available_after.is_negative());
174176

175177
rt.replace_state(&st);
@@ -178,7 +180,7 @@ fn rewards_pay_back_fee_debt() {
178180
let penalty = TokenAmount::zero();
179181
// manually update actor balance to include the added funds from outside
180182
let new_balance = &amt + &reward;
181-
rt.set_balance(new_balance.clone());
183+
rt.set_balance(new_balance);
182184

183185
// pledge change is new reward - reward taken for fee debt
184186
// 3*LockedRewardFactor*amt - 2*amt = remainingLocked
@@ -203,7 +205,7 @@ fn rewards_pay_back_fee_debt() {
203205
BURNT_FUNDS_ACTOR_ADDR,
204206
METHOD_SEND,
205207
RawBytes::default(),
206-
expect_burnt.clone(),
208+
expect_burnt,
207209
RawBytes::default(),
208210
ExitCode::OK,
209211
);
@@ -212,13 +214,10 @@ fn rewards_pay_back_fee_debt() {
212214
rt.call::<Actor>(Method::ApplyRewards as u64, &RawBytes::serialize(params).unwrap()).unwrap();
213215
rt.verify();
214216

215-
// Set balance to deduct fee
216-
let final_balance = &new_balance - &expect_burnt;
217-
218217
let st = h.get_state(&rt);
219218
// balance funds used to pay off fee debt
220219
// available balance should be 2
221-
let available_balance = st.get_available_balance(&final_balance).unwrap();
220+
let available_balance = h.get_available_balance(&mut rt).unwrap();
222221
assert_eq!(available_before + reward - init_fee_debt - &remaining_locked, available_balance);
223222
assert!(!st.fee_debt.is_positive());
224223
// remaining funds locked in vesting table

0 commit comments

Comments
 (0)