From e0bf67e5a320760b40395d7e5dd52f13e5b5d967 Mon Sep 17 00:00:00 2001 From: Aarsh Shah Date: Wed, 25 Oct 2023 15:53:18 +0400 Subject: [PATCH] Miner Actor pre-commit event --- actors/miner/src/emit.rs | 16 ++ actors/miner/src/lib.rs | 42 ++++- .../tests/batch_method_network_fees_test.rs | 4 + .../tests/compact_sector_numbers_tests.rs | 5 +- .../tests/miner_actor_test_commitment.rs | 147 ++++++++++++++---- .../tests/miner_actor_test_precommit_batch.rs | 3 + actors/miner/tests/util.rs | 33 +++- 7 files changed, 211 insertions(+), 39 deletions(-) create mode 100644 actors/miner/src/emit.rs diff --git a/actors/miner/src/emit.rs b/actors/miner/src/emit.rs new file mode 100644 index 000000000..25d619504 --- /dev/null +++ b/actors/miner/src/emit.rs @@ -0,0 +1,16 @@ +// A namespace for helpers that build and emit Miner Actor events. + +use fil_actors_runtime::runtime::Runtime; +use fil_actors_runtime::{ActorError, EventBuilder}; +use fvm_shared::sector::SectorID; + +/// Indicates a sector has been pre-committed. +pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { + rt.emit_event( + &EventBuilder::new() + .typ("sector-precommited") + .field_indexed("miner", &id.miner) + .field_indexed("sector", &id.number) + .build()?, + ) +} diff --git a/actors/miner/src/lib.rs b/actors/miner/src/lib.rs index 0f4ac4332..0b3ea7b21 100644 --- a/actors/miner/src/lib.rs +++ b/actors/miner/src/lib.rs @@ -86,6 +86,8 @@ pub mod testing; mod types; mod vesting_state; +pub mod emit; + // The first 1000 actor-specific codes are left open for user error, i.e. things that might // actually happen without programming error in the actor code. @@ -1422,6 +1424,16 @@ impl Actor { rt: &impl Runtime, params: PreCommitSectorBatchParams, ) -> Result<(), ActorError> { + let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() { + *i + } else { + return Err(actor_error!( + illegal_state, + "runtime provided non ID receiver address {}", + rt.message().receiver() + )); + }; + let sectors = params .sectors .into_iter() @@ -1446,7 +1458,7 @@ impl Actor { } }) .collect::>()?; - Self::pre_commit_sector_batch_inner(rt, sectors) + Self::pre_commit_sector_batch_inner(rt, sectors, miner_actor_id) } /// Pledges the miner to seal and commit some new sectors. @@ -1459,6 +1471,16 @@ impl Actor { rt: &impl Runtime, params: PreCommitSectorBatchParams2, ) -> Result<(), ActorError> { + let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() { + *i + } else { + return Err(actor_error!( + illegal_state, + "runtime provided non ID receiver address {}", + rt.message().receiver() + )); + }; + Self::pre_commit_sector_batch_inner( rt, params @@ -1475,6 +1497,7 @@ impl Actor { unsealed_cid: Some(spci.unsealed_cid), }) .collect(), + miner_actor_id, ) } @@ -1483,6 +1506,7 @@ impl Actor { fn pre_commit_sector_batch_inner( rt: &impl Runtime, sectors: Vec, + miner_actor_id: ActorID, ) -> Result<(), ActorError> { let curr_epoch = rt.curr_epoch(); { @@ -1635,6 +1659,8 @@ impl Actor { let sector_weight_for_deposit = qa_power_max(info.sector_size); let deposit_req = pre_commit_deposit_for_power(&reward_stats.this_epoch_reward_smoothed, &power_total.quality_adj_power_smoothed, §or_weight_for_deposit); + let mut precommited_sectors = vec![]; + for (i, precommit) in sectors.into_iter().enumerate() { // Sector must have the same Window PoSt proof type as the miner's recorded seal type. let sector_wpost_proof = precommit.seal_proof @@ -1696,6 +1722,8 @@ impl Actor { // ConfirmSectorProofsValid would fail to find it. let clean_up_bound = curr_epoch + msd + rt.policy().expired_pre_commit_clean_up_delay; clean_up_events.push((clean_up_bound, precommit.sector_number)); + + precommited_sectors.push(precommit.sector_number); } // Batch update actor state. if available_balance < total_deposit_required { @@ -1720,9 +1748,20 @@ impl Actor { .map_err(|e| { e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to add pre-commit expiry to queue") })?; + + // Activate miner cron needs_cron = !state.deadline_cron_active; state.deadline_cron_active = true; + + for sector_num in precommited_sectors.into_iter() { + let sector_id = SectorID{ + miner: miner_actor_id, + number: sector_num, + }; + emit::sector_precommited(rt, sector_id)?; + } + Ok(()) })?; burn_funds(rt, fee_to_burn)?; @@ -1736,6 +1775,7 @@ impl Actor { CronEventPayload { event_type: CRON_EVENT_PROVING_DEADLINE }, )?; } + Ok(()) } diff --git a/actors/miner/tests/batch_method_network_fees_test.rs b/actors/miner/tests/batch_method_network_fees_test.rs index 06e0a1766..6fb0cb79e 100644 --- a/actors/miner/tests/batch_method_network_fees_test.rs +++ b/actors/miner/tests/batch_method_network_fees_test.rs @@ -100,6 +100,7 @@ fn insufficient_funds_for_batch_precommit_network_fee() { PreCommitSectorBatchParams { sectors: precommits }, &PreCommitBatchConfig { first_for_miner: true, ..Default::default() }, &base_fee, + false, ); // state untouched @@ -156,6 +157,7 @@ fn insufficient_funds_for_batch_precommit_in_combination_of_fee_debt_and_network PreCommitSectorBatchParams { sectors: precommits }, &PreCommitBatchConfig { first_for_miner: true, ..Default::default() }, &base_fee, + false, ); // state untouched @@ -211,6 +213,7 @@ fn enough_funds_for_fee_debt_and_network_fee_but_not_for_pcd() { PreCommitSectorBatchParams { sectors: precommits }, &PreCommitBatchConfig { first_for_miner: true, ..Default::default() }, &base_fee, + false, ); expect_abort_contains_message( @@ -274,6 +277,7 @@ fn enough_funds_for_everything() { PreCommitSectorBatchParams { sectors: precommits }, &PreCommitBatchConfig { first_for_miner: true, ..Default::default() }, &base_fee, + true, ) .unwrap(); diff --git a/actors/miner/tests/compact_sector_numbers_tests.rs b/actors/miner/tests/compact_sector_numbers_tests.rs index df04f3b33..6bc230fd0 100644 --- a/actors/miner/tests/compact_sector_numbers_tests.rs +++ b/actors/miner/tests/compact_sector_numbers_tests.rs @@ -49,7 +49,7 @@ mod compact_sector_numbers_test { ); expect_abort( ExitCode::USR_ILLEGAL_ARGUMENT, - h.pre_commit_sector(&rt, precommit, util::PreCommitConfig::default(), false), + h.pre_commit_sector(&rt, precommit, util::PreCommitConfig::default(), false, false), ); } @@ -60,7 +60,8 @@ mod compact_sector_numbers_test { expiration, vec![], ); - h.pre_commit_sector(&rt, precommit, util::PreCommitConfig::default(), false).unwrap(); + h.pre_commit_sector(&rt, precommit, util::PreCommitConfig::default(), false, true) + .unwrap(); } check_state_invariants_from_mock_runtime(&rt); } diff --git a/actors/miner/tests/miner_actor_test_commitment.rs b/actors/miner/tests/miner_actor_test_commitment.rs index 836cd05c6..5cb7e16d6 100644 --- a/actors/miner/tests/miner_actor_test_commitment.rs +++ b/actors/miner/tests/miner_actor_test_commitment.rs @@ -128,7 +128,13 @@ mod miner_actor_test_commitment { expect_abort( ExitCode::USR_INSUFFICIENT_FUNDS, - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), true), + h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + true, + false, + ), ); rt.reset(); h.check_state(&rt); @@ -158,7 +164,8 @@ mod miner_actor_test_commitment { let precommit_params = h.make_pre_commit_params(101, challenge_epoch, expiration, vec![1]); - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), true).unwrap(); + h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), true, true) + .unwrap(); let st: State = rt.get_state(); assert_eq!(TokenAmount::zero(), st.fee_debt); h.check_state(&rt); @@ -199,8 +206,13 @@ mod miner_actor_test_commitment { false, ); // Duplicate pre-commit sector ID - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "already allocated", ret); rt.reset(); } @@ -213,8 +225,13 @@ mod miner_actor_test_commitment { expiration, vec![], ); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "already allocated", ret); rt.reset(); } @@ -224,8 +241,13 @@ mod miner_actor_test_commitment { let mut precommit_params = h.make_pre_commit_params(102, challenge_epoch, deadline.period_end(), vec![]); precommit_params.sealed_cid = make_cid_poseidon("Random Data".as_bytes(), 0); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "sealed CID had wrong prefix", @@ -239,8 +261,13 @@ mod miner_actor_test_commitment { let mut precommit_params = h.make_pre_commit_params(102, challenge_epoch, deadline.period_end(), vec![]); precommit_params.seal_proof = RegisteredSealProof::StackedDRG8MiBV1; - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "unsupported seal proof type", @@ -253,8 +280,13 @@ mod miner_actor_test_commitment { { let precommit_params = h.make_pre_commit_params(102, challenge_epoch, *rt.epoch.borrow(), vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "must be after activation", @@ -267,8 +299,13 @@ mod miner_actor_test_commitment { { let precommit_params = h.make_pre_commit_params(102, challenge_epoch, *rt.epoch.borrow() - 1, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "must be after activation", @@ -282,8 +319,13 @@ mod miner_actor_test_commitment { let early_expiration = rt.policy.min_sector_expiration - EPOCHS_IN_DAY; let precommit_params = h.make_pre_commit_params(102, challenge_epoch, early_expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "must exceed", ret); rt.reset(); } @@ -296,8 +338,13 @@ mod miner_actor_test_commitment { - 1; let precommit_params = h.make_pre_commit_params(102, challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "must exceed", ret); rt.reset(); } @@ -311,8 +358,13 @@ mod miner_actor_test_commitment { + 1); let precommit_params = h.make_pre_commit_params(102, challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "invalid expiration", @@ -327,8 +379,13 @@ mod miner_actor_test_commitment { let expiration = *rt.epoch.borrow() + rt.policy.max_sector_expiration_extension + 1; let precommit_params = h.make_pre_commit_params(102, challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "invalid expiration", @@ -345,8 +402,13 @@ mod miner_actor_test_commitment { expiration, vec![], ); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "out of range", ret); rt.reset(); } @@ -359,8 +421,13 @@ mod miner_actor_test_commitment { - 1; let precommit_params = h.make_pre_commit_params(102, too_old_challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_ILLEGAL_ARGUMENT, "too old", ret); rt.reset(); } @@ -372,8 +439,13 @@ mod miner_actor_test_commitment { rt.replace_state(&st); let precommit_params = h.make_pre_commit_params(102, challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message( ExitCode::USR_INSUFFICIENT_FUNDS, "unlocked balance can not repay fee debt", @@ -397,8 +469,13 @@ mod miner_actor_test_commitment { h.report_consensus_fault(&rt, test_addr, Some(fault), ExitCode::OK).unwrap(); let precommit_params = h.make_pre_commit_params(102, challenge_epoch, expiration, vec![]); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), false); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + false, + false, + ); expect_abort_contains_message(ExitCode::USR_FORBIDDEN, "active consensus fault", ret); // reset state back to normal rt.replace_state(&st); @@ -447,8 +524,13 @@ mod miner_actor_test_commitment { expiration, make_deal_ids(limit + 1), ); - let ret = - h.pre_commit_sector(&rt, precommit_params, util::PreCommitConfig::default(), true); + let ret = h.pre_commit_sector( + &rt, + precommit_params, + util::PreCommitConfig::default(), + true, + false, + ); expect_abort_contains_message( ExitCode::USR_ILLEGAL_ARGUMENT, "too many deals for sector", @@ -502,6 +584,7 @@ mod miner_actor_test_commitment { precommit_params.clone(), util::PreCommitConfig::default(), true, + false, ), ); rt.reset(); diff --git a/actors/miner/tests/miner_actor_test_precommit_batch.rs b/actors/miner/tests/miner_actor_test_precommit_batch.rs index 41eb49e1b..b6edeeb1d 100644 --- a/actors/miner/tests/miner_actor_test_precommit_batch.rs +++ b/actors/miner/tests/miner_actor_test_precommit_batch.rs @@ -99,6 +99,7 @@ fn assert_simple_batch( PreCommitSectorBatchParams { sectors }, &conf, &base_fee, + false, ), ); rt.reset(); @@ -306,6 +307,7 @@ mod miner_actor_precommit_batch { PreCommitSectorBatchParams { sectors }, &PreCommitBatchConfig { sector_unsealed_cid: vec![], first_for_miner: true }, &TokenAmount::zero(), + false, ), ); rt.reset(); @@ -346,6 +348,7 @@ mod miner_actor_precommit_batch { PreCommitSectorBatchParams { sectors }, &PreCommitBatchConfig { sector_unsealed_cid: vec![], first_for_miner: true }, &TokenAmount::zero(), + false, ), ); rt.reset(); diff --git a/actors/miner/tests/util.rs b/actors/miner/tests/util.rs index b1ebf631f..6f297e6be 100644 --- a/actors/miner/tests/util.rs +++ b/actors/miner/tests/util.rs @@ -83,7 +83,7 @@ use fil_actor_power::{ use fil_actor_reward::{Method as RewardMethod, ThisEpochRewardReturn}; use fil_actors_runtime::cbor::serialize; use fil_actors_runtime::runtime::{DomainSeparationTag, Runtime, RuntimePolicy}; -use fil_actors_runtime::{test_utils::*, BatchReturn, BatchReturnGen}; +use fil_actors_runtime::{test_utils::*, BatchReturn, BatchReturnGen, EventBuilder}; use fil_actors_runtime::{ ActorDowncast, ActorError, Array, DealWeight, MessageAccumulator, BURNT_FUNDS_ACTOR_ADDR, INIT_ACTOR_ADDR, REWARD_ACTOR_ADDR, STORAGE_MARKET_ACTOR_ADDR, STORAGE_POWER_ACTOR_ADDR, @@ -604,6 +604,7 @@ impl ActorHarness { params: PreCommitSectorBatchParams, conf: &PreCommitBatchConfig, base_fee: &TokenAmount, + expect_event: bool, ) -> Result, ActorError> { let v2: Vec<_> = params .sectors @@ -620,6 +621,18 @@ impl ActorHarness { }) .collect(); + if expect_event { + for si in v2.iter() { + rt.expect_emitted_event( + EventBuilder::new() + .typ("sector-precommited") + .field_indexed("miner", &RECEIVER_ID) + .field_indexed("sector", &si.sector_number) + .build()?, + ); + } + } + if self.options.use_v2_pre_commit_and_replica_update { return self.pre_commit_sector_batch_inner( rt, @@ -726,7 +739,8 @@ impl ActorHarness { conf: &PreCommitBatchConfig, base_fee: &TokenAmount, ) -> Vec { - let result = self.pre_commit_sector_batch(rt, params.clone(), conf, base_fee).unwrap(); + let result = + self.pre_commit_sector_batch(rt, params.clone(), conf, base_fee, true).unwrap(); expect_empty(result); rt.verify(); @@ -740,6 +754,7 @@ impl ActorHarness { params: PreCommitSectorParams, conf: PreCommitConfig, first: bool, + emits_event: bool, ) -> Result, ActorError> { rt.set_caller(*ACCOUNT_ACTOR_CODE_ID, self.worker); rt.expect_validate_caller_addr(self.caller_addrs()); @@ -795,6 +810,16 @@ impl ActorHarness { ); } + if emits_event { + rt.expect_emitted_event( + EventBuilder::new() + .typ("sector-precommited") + .field_indexed("miner", &RECEIVER_ID) + .field_indexed("sector", ¶ms.sector_number) + .build()?, + ); + } + let result = rt.call::( Method::PreCommitSector as u64, IpldBlock::serialize_cbor(¶ms.clone()).unwrap(), @@ -809,7 +834,7 @@ impl ActorHarness { conf: PreCommitConfig, first: bool, ) -> SectorPreCommitOnChainInfo { - let result = self.pre_commit_sector(rt, params.clone(), conf, first); + let result = self.pre_commit_sector(rt, params.clone(), conf, first, true); expect_empty(result.unwrap()); rt.verify(); @@ -3314,7 +3339,7 @@ impl CronControl { dlinfo.period_end() + DEFAULT_SECTOR_EXPIRATION as i64 * rt.policy.wpost_proving_period; // something on deadline boundary but > 180 days let precommit_params = h.make_pre_commit_params(sector_no, pre_commit_epoch - 1, expiration, vec![]); - h.pre_commit_sector(rt, precommit_params, PreCommitConfig::default(), true).unwrap(); + h.pre_commit_sector(rt, precommit_params, PreCommitConfig::default(), true, true).unwrap(); // PCD != 0 so cron must be active self.require_cron_active(h, rt);