Skip to content

Commit 5e08d67

Browse files
committed
feat(FIP-0077): add create miner deposit
1 parent b4ed8cf commit 5e08d67

17 files changed

+355
-59
lines changed

actors/miner/src/lib.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub use expiration_queue::*;
4646
use fil_actors_runtime::cbor::{serialize, serialize_vec};
4747
use fil_actors_runtime::reward::{FilterEstimate, ThisEpochRewardReturn};
4848
use fil_actors_runtime::runtime::builtins::Type;
49-
use fil_actors_runtime::runtime::policy_constants::MAX_SECTOR_NUMBER;
49+
use fil_actors_runtime::runtime::policy_constants::{MAX_SECTOR_NUMBER, MINIMUM_CONSENSUS_POWER};
5050
use fil_actors_runtime::runtime::{ActorCode, DomainSeparationTag, Policy, Runtime};
5151
use fil_actors_runtime::{
5252
actor_dispatch, actor_error, deserialize_block, extract_send_result, util, ActorContext,
@@ -181,6 +181,14 @@ impl Actor {
181181
check_peer_info(rt.policy(), &params.peer_id, &params.multi_addresses)?;
182182
check_valid_post_proof_type(rt.policy(), params.window_post_proof_type)?;
183183

184+
let balance = rt.current_balance();
185+
let deposit = calculate_create_miner_deposit(rt, params.network_qap)?;
186+
if balance < deposit {
187+
return Err(actor_error!(insufficient_funds;
188+
"not enough balance to lock for create miner deposit: \
189+
sent balance {} < deposit {}", balance.atto(), deposit.atto()));
190+
}
191+
184192
let owner = rt.resolve_address(&params.owner).ok_or_else(|| {
185193
actor_error!(illegal_argument, "unable to resolve owner address: {}", params.owner)
186194
})?;
@@ -239,7 +247,10 @@ impl Actor {
239247
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to construct illegal state")
240248
})?;
241249

242-
let st = State::new(policy, rt.store(), info_cid, period_start, deadline_idx)?;
250+
let store = rt.store();
251+
let mut st = State::new(policy, store, info_cid, period_start, deadline_idx)?;
252+
st.add_locked_funds(store, rt.curr_epoch(), &deposit, &REWARD_VESTING_SPEC)
253+
.map_err(|e| actor_error!(illegal_state, e))?;
243254
rt.create(&st)?;
244255
Ok(())
245256
}
@@ -312,6 +323,7 @@ impl Actor {
312323
.load_vesting_funds(rt.store())
313324
.map_err(|e| actor_error!(illegal_state, "failed to load vesting funds: {}", e))?;
314325
let ret = vesting_funds.funds.into_iter().map(|v| (v.epoch, v.amount)).collect_vec();
326+
315327
Ok(GetVestingFundsReturn { vesting_funds: ret })
316328
}
317329

@@ -756,6 +768,7 @@ impl Actor {
756768

757769
Ok(())
758770
}
771+
759772
/// Checks state of the corresponding sector pre-commitments and verifies aggregate proof of replication
760773
/// of these sectors. If valid, the sectors' deals are activated, sectors are assigned a deadline and charged pledge
761774
/// and precommit state is removed.
@@ -5240,7 +5253,6 @@ fn resolve_worker_address(rt: &impl Runtime, raw: Address) -> Result<ActorID, Ac
52405253
}
52415254

52425255
fn burn_funds(rt: &impl Runtime, amount: TokenAmount) -> Result<(), ActorError> {
5243-
log::debug!("storage provder {} burning {}", rt.message().receiver(), amount);
52445256
if amount.is_positive() {
52455257
extract_send_result(rt.send_simple(&BURNT_FUNDS_ACTOR_ADDR, METHOD_SEND, None, amount))?;
52465258
}
@@ -5642,6 +5654,53 @@ fn activate_new_sector_infos(
56425654
Ok(())
56435655
}
56445656

5657+
/// Calculate create miner deposit by MINIMUM_CONSENSUS_POWER x StateMinerInitialPledgeCollateral
5658+
/// See FIP-0077, https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0077.md
5659+
pub fn calculate_create_miner_deposit(
5660+
rt: &impl Runtime,
5661+
network_qap: FilterEstimate,
5662+
) -> Result<TokenAmount, ActorError> {
5663+
// set network pledge inputs
5664+
let rew = request_current_epoch_block_reward(rt)?;
5665+
let pwr = request_current_total_power(rt)?;
5666+
let circulating_supply = rt.total_fil_circ_supply();
5667+
let pledge_inputs = NetworkPledgeInputs {
5668+
network_qap,
5669+
network_baseline: rew.this_epoch_baseline_power,
5670+
circulating_supply,
5671+
epoch_reward: rew.this_epoch_reward_smoothed,
5672+
epochs_since_ramp_start: rt.curr_epoch() - pwr.ramp_start_epoch,
5673+
ramp_duration_epochs: pwr.ramp_duration_epochs,
5674+
};
5675+
5676+
/// set sector size with min power
5677+
#[cfg(feature = "min-power-2k")]
5678+
let sector_size = SectorSize::_2KiB;
5679+
#[cfg(feature = "min-power-2g")]
5680+
let sector_size = SectorSize::_8MiB;
5681+
#[cfg(feature = "min-power-32g")]
5682+
let sector_size = SectorSize::_512MiB;
5683+
#[cfg(not(any(
5684+
feature = "min-power-2k",
5685+
feature = "min-power-2g",
5686+
feature = "min-power-32g"
5687+
)))]
5688+
let sector_size = SectorSize::_32GiB;
5689+
5690+
let sector_number = MINIMUM_CONSENSUS_POWER / sector_size as i64;
5691+
let power = qa_power_for_weight(sector_size, MIN_SECTOR_EXPIRATION, &BigInt::zero());
5692+
let sector_initial_pledge = initial_pledge_for_power(
5693+
&power,
5694+
&pledge_inputs.network_baseline,
5695+
&pledge_inputs.epoch_reward,
5696+
&pledge_inputs.network_qap,
5697+
&pledge_inputs.circulating_supply,
5698+
pledge_inputs.epochs_since_ramp_start,
5699+
pledge_inputs.ramp_duration_epochs,
5700+
);
5701+
Ok(sector_initial_pledge * sector_number)
5702+
}
5703+
56455704
pub struct SectorPiecesActivationInput {
56465705
pub piece_manifests: Vec<PieceActivationManifest>,
56475706
pub sector_expiry: ChainEpoch,

actors/miner/src/state.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl State {
214214
pub fn deadline_info(&self, policy: &Policy, current_epoch: ChainEpoch) -> DeadlineInfo {
215215
new_deadline_info_from_offset_and_epoch(policy, self.proving_period_start, current_epoch)
216216
}
217+
217218
// Returns deadline calculations for the state recorded proving period and deadline.
218219
// This is out of date if the a miner does not have an active miner cron
219220
pub fn recorded_deadline_info(
@@ -877,6 +878,7 @@ impl State {
877878
amount_unlocked
878879
));
879880
}
881+
880882
// add locked funds now
881883
vesting_funds.add_locked_funds(current_epoch, vesting_sum, self.proving_period_start, spec);
882884
self.locked_funds += vesting_sum;
@@ -937,6 +939,7 @@ impl State {
937939

938940
Ok(std::mem::take(&mut self.fee_debt))
939941
}
942+
940943
/// Unlocks an amount of funds that have *not yet vested*, if possible.
941944
/// The soonest-vesting entries are unlocked first.
942945
/// Returns the amount actually unlocked.
@@ -1008,6 +1011,7 @@ impl State {
10081011
pub fn get_unlocked_balance(&self, actor_balance: &TokenAmount) -> anyhow::Result<TokenAmount> {
10091012
let unlocked_balance =
10101013
actor_balance - &self.locked_funds - &self.pre_commit_deposits - &self.initial_pledge;
1014+
10111015
if unlocked_balance.is_negative() {
10121016
return Err(anyhow!("negative unlocked balance {}", unlocked_balance));
10131017
}
@@ -1039,6 +1043,7 @@ impl State {
10391043
}
10401044

10411045
let min_balance = &self.pre_commit_deposits + &self.locked_funds + &self.initial_pledge;
1046+
10421047
if balance < &min_balance {
10431048
return Err(anyhow!("fee debt is negative: {}", self.fee_debt));
10441049
}

actors/miner/src/testing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ fn check_miner_balances<BS: Blockstore>(
269269
format!("miner fee debt is less than zero: {}", state.fee_debt),
270270
);
271271

272-
acc.require(!(balance - &state.locked_funds - &state.pre_commit_deposits - &state.initial_pledge).is_negative(), format!("miner balance {balance} is less than sum of locked funds ({}), precommit deposit ({}) and initial pledge ({})", state.locked_funds, state.pre_commit_deposits, state.initial_pledge));
272+
acc.require(!(balance - &state.locked_funds - &state.pre_commit_deposits - &state.initial_pledge).is_negative(), format!("miner balance {balance} is less than sum of locked funds ({}), precommit deposit ({}), initial pledge ({})", state.locked_funds, state.pre_commit_deposits, state.initial_pledge));
273273

274274
// locked funds must be sum of vesting table and vesting table payments must be quantized
275275
let mut vesting_sum = TokenAmount::zero();

actors/miner/src/types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub struct MinerConstructorParams {
4545
#[serde(with = "strict_bytes")]
4646
pub peer_id: Vec<u8>,
4747
pub multi_addresses: Vec<BytesDe>,
48+
pub network_qap: FilterEstimate,
4849
}
4950

5051
#[derive(Serialize_tuple, Deserialize_tuple)]
@@ -105,6 +106,11 @@ pub struct DeferredCronEventParams {
105106
pub quality_adj_power_smoothed: FilterEstimate,
106107
}
107108

109+
#[derive(Serialize_tuple, Deserialize_tuple)]
110+
pub struct LockCreateMinerDepositParams {
111+
pub amount: TokenAmount,
112+
}
113+
108114
#[derive(Serialize_tuple, Deserialize_tuple)]
109115
pub struct PoStPartition {
110116
/// Partitions are numbered per-deadline, from zero.

actors/miner/tests/aggregate_prove_commit.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const DEFAULT_SECTOR_EXPIRATION: ChainEpoch = 220;
2121
fn valid_precommits_then_aggregate_provecommit() {
2222
let period_offset = ChainEpoch::from(100);
2323

24+
println!("#0");
25+
2426
let actor = ActorHarness::new(period_offset);
2527
let rt = actor.new_runtime();
2628
rt.add_balance(BIG_BALANCE.clone());
@@ -29,6 +31,8 @@ fn valid_precommits_then_aggregate_provecommit() {
2931
actor.construct_and_verify(&rt);
3032
let dl_info = actor.deadline(&rt);
3133

34+
println!("#1");
35+
3236
// make a good commitment for the proof to target
3337

3438
let prove_commit_epoch = precommit_epoch + rt.policy.pre_commit_challenge_delay + 1;
@@ -51,6 +55,8 @@ fn valid_precommits_then_aggregate_provecommit() {
5155
precommits.push(precommit);
5256
}
5357

58+
println!("#2");
59+
5460
// run prove commit logic
5561
rt.set_epoch(prove_commit_epoch);
5662
rt.set_balance(TokenAmount::from_whole(1000));
@@ -63,6 +69,8 @@ fn valid_precommits_then_aggregate_provecommit() {
6369
);
6470
}
6571

72+
println!("#3");
73+
6674
actor
6775
.prove_commit_aggregate_sector(
6876
&rt,
@@ -73,13 +81,17 @@ fn valid_precommits_then_aggregate_provecommit() {
7381
)
7482
.unwrap();
7583

84+
println!("#4");
85+
7686
// expect precommits to have been removed
7787
let st = actor.get_state(&rt);
7888

7989
for sector_no in sector_nos_bf.iter() {
8090
assert!(!actor.has_precommit(&rt, sector_no));
8191
}
8292

93+
println!("#5");
94+
8395
// expect deposit to have been transferred to initial pledges
8496
assert!(st.pre_commit_deposits.is_zero());
8597

@@ -107,6 +119,8 @@ fn valid_precommits_then_aggregate_provecommit() {
107119
let ten_sectors_initial_pledge = BigInt::from(10i32) * expected_initial_pledge.clone();
108120
assert_eq!(ten_sectors_initial_pledge, st.initial_pledge);
109121

122+
println!("#6");
123+
110124
// expect new onchain sector
111125
for sector_no in sector_nos_bf.iter() {
112126
let sector = actor.get_sector(&rt, sector_no);
@@ -127,6 +141,8 @@ fn valid_precommits_then_aggregate_provecommit() {
127141
assert_eq!(0, pidx);
128142
}
129143

144+
println!("#7");
145+
130146
let sector_power = PowerPair::new(BigInt::from(actor.sector_size as i64), qa_power);
131147
let ten_sectors_power = PowerPair::new(
132148
BigInt::from(10u32) * sector_power.raw,
@@ -158,6 +174,8 @@ fn valid_precommits_then_aggregate_provecommit() {
158174
assert_eq!(PowerPair::zero(), partition.faulty_power);
159175
assert_eq!(PowerPair::zero(), partition.recovering_power);
160176

177+
println!("#8");
178+
161179
let p_queue = actor.collect_partition_expirations(&rt, &partition);
162180
let entry = p_queue.get(&quantized_expiration).cloned().unwrap();
163181
assert_eq!(entry.on_time_sectors, sector_nos_bf);

actors/miner/tests/apply_rewards.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ fn funds_vest() {
4444
rt.set_balance(BIG_BALANCE.clone());
4545
h.construct_and_verify(&rt);
4646
let st = h.get_state(&rt);
47-
4847
let vesting_funds = st.load_vesting_funds(&rt.store).unwrap();
49-
5048
// Nothing vesting to start
5149
assert!(vesting_funds.funds.is_empty());
5250
assert!(st.locked_funds.is_zero());

0 commit comments

Comments
 (0)