-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Miner Actor events for Sector lifecycle #1462
Miner Actor events for Sector lifecycle #1462
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## integration/actor-events #1462 +/- ##
===========================================================
Coverage ? 91.03%
===========================================================
Files ? 150
Lines ? 28145
Branches ? 0
===========================================================
Hits ? 25622
Misses ? 2523
Partials ? 0 |
actors/miner/src/lib.rs
Outdated
@@ -4935,7 +4973,17 @@ fn activate_new_sector_infos( | |||
data_activations: Vec<DataActivationOutput>, | |||
pledge_inputs: &NetworkPledgeInputs, | |||
info: &MinerInfo, | |||
emit_event: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anorth We need this as we only want the emit here if this call is from the cron callback to CONFIRM_SECTOR_PROOFS_VALID
which in turn is scheduled by the vanilla prove commit method.
For the prove commit aggregate method, we don't want to emit the event here as we also need to check if we have enough funds for gas fees. Doing it this way makes it work nicely with the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right trade-off. Emitting the events here is a good place to ensure that future code changes will still emit events exactly according to activations, and will simplify code elsewhere. There are more paths into sector activation coming in integration/direct-onboarding
.
We don't need to make checks about funds etc before emitting events - if those checks fail the whole thing will abort anyway. We may need to update testing support code to allow us to write the main code in the straightforward way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done. We no longer have this flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change the testing patterns to remove the boolean configuration of which expectations to set, and instead reset the mock after a method aborts.
We also need events for data activation via ProveReplicaUpdates. I can't tell from the PR description whether you intended this to be the only PR to miner actor, or would follow-up. But I think it probably makes sense to do it all at once here so we can confirm the same patterns work for both.
actors/miner/src/emit.rs
Outdated
use fvm_shared::sector::SectorID; | ||
|
||
/// Indicates a sector has been pre-committed. | ||
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { | |
pub fn sector_precommitted(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
actors/miner/src/emit.rs
Outdated
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { | ||
rt.emit_event( | ||
&EventBuilder::new() | ||
.typ("sector-precommited") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.typ("sector-precommited") | |
.typ("sector-precommitted") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
actors/miner/src/emit.rs
Outdated
use fvm_shared::sector::SectorID; | ||
|
||
/// Indicates a sector has been pre-committed. | ||
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the SectorID type has exactly what you want, but please pass two separate parameters here for the miner actor ID and sector number separately. The SectorID type only exists as part of SealVerifyInfo; it's defined outside of our repo and is unused except when forced by the FVM SDK API. I was genuinely surprised to see it as I'd forgotten it exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done.
actors/miner/src/emit.rs
Outdated
} | ||
|
||
/// Indicates a sector has been proven. | ||
pub fn sector_proven(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename to sector-activated. Today these always happen at the same time, but in the future we may separate them. If we do, it's likely that most users of the event really care about the activation, rather than an un-activated proof. We'll reserve sector-proven for that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
actors/miner/src/lib.rs
Outdated
@@ -852,12 +854,16 @@ impl Actor { | |||
activate_deals(rt, &data_activations, compute_commd)?; | |||
let successful_activations = batch_return.successes(&precommits_to_confirm); | |||
|
|||
let proven_sector_nums = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
activated_sector_nums
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
actors/miner/src/lib.rs
Outdated
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)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this up a few lines so it's directly after the state updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
actors/miner/src/lib.rs
Outdated
@@ -4935,7 +4973,17 @@ fn activate_new_sector_infos( | |||
data_activations: Vec<DataActivationOutput>, | |||
pledge_inputs: &NetworkPledgeInputs, | |||
info: &MinerInfo, | |||
emit_event: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right trade-off. Emitting the events here is a good place to ensure that future code changes will still emit events exactly according to activations, and will simplify code elsewhere. There are more paths into sector activation coming in integration/direct-onboarding
.
We don't need to make checks about funds etc before emitting events - if those checks fail the whole thing will abort anyway. We may need to update testing support code to allow us to write the main code in the straightforward way.
actors/miner/src/lib.rs
Outdated
) -> Result<(), ActorError> { | ||
let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just unwrap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -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), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have to pass this flag. This pattern doesn't scale to all the possible expectations and abort points that a method might hit.
The mock should always set expectations for the events. If the method aborts before emitting them, then at line 54 you should rt.reset()
to void any remaining expectations. Most places will probably already do this, but this one forgot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been fixed in all tests. Done.
@@ -720,7 +720,7 @@ pub fn aggregate_one_precommit_expires_test(v: &dyn VM) { | |||
apply_ok( | |||
v, | |||
&worker, | |||
&robust_addr, | |||
&miner_addr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this change necessary? It shouldn't be
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anorth This is because the Test Runtime always expects the receiver address to be an ID Address.
builtin-actors/test_vm/src/messaging.rs
Line 643 in 7500bab
.push(EmittedEvent { emitter: self.msg.to.id().unwrap(), event: event.clone() }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the emitter field here to be just an Address
instead ? We can then worry about what to do with it once we get to the integration tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The event emitter must always be an ID. The runtime should always give the actor an ID address as receiver()
. The problem is somewhere in our TestVM which should resolve an address to an ID address before making it available as the receiver (but not too soon, in case the actor doesn't yet exist and needs to be created on the fly to receive the message). It's important that we can support calls to non-ID addresses like this but then have everything still work.
I have addressed your review and have added events for the Sector Updated and Sector Terminated transitions. Some notes/questions:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want us to figure out the address resolution in tests, but otherwise this looks good.
actors/miner/src/lib.rs
Outdated
@@ -878,6 +880,7 @@ impl Actor { | |||
} | |||
burn_funds(rt, aggregate_fee)?; | |||
state.check_balance_invariants(&rt.current_balance()).map_err(balance_invariants_broken)?; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: unnecessary blank line. Some others similar below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done.
actors/miner/src/lib.rs
Outdated
@@ -1484,6 +1495,8 @@ impl Actor { | |||
rt: &impl Runtime, | |||
sectors: Vec<SectorPreCommitInfoInner>, | |||
) -> Result<(), ActorError> { | |||
let miner_actor_id: u64 = rt.message().receiver().id().unwrap(); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: unnecessary blank
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
actors/miner/tests/prove_commit.rs
Outdated
let st = h.get_state(&rt); | ||
assert!(st.get_sector(&rt.store, sector_no_a).unwrap().is_none()); | ||
assert!(st.get_sector(&rt.store, sector_no_b).unwrap().is_some()); | ||
h.check_state(&rt); | ||
rt.reset(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This call didn't abort, so this should rt.verify()
instead. Or you can skip it because it's automatic when dropped, which happens immediately next. If you added this because expectations are failing, something is wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, we don't need this. It's a remanent of something I was debugging earlier.
actors/miner/tests/util.rs
Outdated
.typ("sector-precommitted") | ||
.field_indexed("miner", &RECEIVER_ID) | ||
.field_indexed("sector", &si.sector_number) | ||
.build()?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's enough repeated code here that it's probably just worth adding a method to factor it out, like expect_event(rt, "sector-precommitted", &RECEIVER_ID, &si.sector_number)
. This can be broadly useful because all the miner events have the same schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored this into it's own function.
@@ -720,7 +720,7 @@ pub fn aggregate_one_precommit_expires_test(v: &dyn VM) { | |||
apply_ok( | |||
v, | |||
&worker, | |||
&robust_addr, | |||
&miner_addr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The event emitter must always be an ID. The runtime should always give the actor an ID address as receiver()
. The problem is somewhere in our TestVM which should resolve an address to an ID address before making it available as the receiver (but not too soon, in case the actor doesn't yet exist and needs to be created on the fly to receive the message). It's important that we can support calls to non-ID addresses like this but then have everything still work.
@anorth I've fixed the problem of the receiver address not being an ID address in the TestVM. Things work well now without any changes to the integration tests and so have rolled those changes back. |
For #1464.
This PR implements the following sector lifecycle events for the Miner Actor: