Skip to content
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

Merged
merged 14 commits into from
Oct 30, 2023

Conversation

aarshkshah1992
Copy link
Contributor

@aarshkshah1992 aarshkshah1992 commented Oct 25, 2023

For #1464.

This PR implements the following sector lifecycle events for the Miner Actor:

  1. Sector Precommitted
  2. Sector Activated
  3. Sector Updated
  4. Sector Temrinated

@codecov-commenter
Copy link

codecov-commenter commented Oct 25, 2023

Codecov Report

❗ No coverage uploaded for pull request base (integration/actor-events@7500bab). Click here to learn what that means.
The diff coverage is n/a.

Additional details and impacted files

Impacted file tree graph

@@                     Coverage Diff                     @@
##             integration/actor-events    #1462   +/-   ##
===========================================================
  Coverage                            ?   91.03%           
===========================================================
  Files                               ?      150           
  Lines                               ?    28145           
  Branches                            ?        0           
===========================================================
  Hits                                ?    25622           
  Misses                              ?     2523           
  Partials                            ?        0           

@aarshkshah1992 aarshkshah1992 changed the title [WIP] Emit Sector Pre-commited and Sector Proven events for the Miner Actor Emit Sector Pre-commited and Sector Proven events for the Miner Actor Oct 25, 2023
@@ -4935,7 +4973,17 @@ fn activate_new_sector_infos(
data_activations: Vec<DataActivationOutput>,
pledge_inputs: &NetworkPledgeInputs,
info: &MinerInfo,
emit_event: bool,
Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

@anorth anorth left a 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.

use fvm_shared::sector::SectorID;

/// Indicates a sector has been pre-committed.
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {
pub fn sector_precommitted(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {
rt.emit_event(
&EventBuilder::new()
.typ("sector-precommited")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.typ("sector-precommited")
.typ("sector-precommitted")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

use fvm_shared::sector::SectorID;

/// Indicates a sector has been pre-committed.
pub fn sector_precommited(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done.

}

/// Indicates a sector has been proven.
pub fn sector_proven(rt: &impl Runtime, id: SectorID) -> Result<(), ActorError> {
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -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 =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activated_sector_nums

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 1754 to 1760
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)?;
}
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -4935,7 +4973,17 @@ fn activate_new_sector_infos(
data_activations: Vec<DataActivationOutput>,
pledge_inputs: &NetworkPledgeInputs,
info: &MinerInfo,
emit_event: bool,
Copy link
Member

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.

) -> Result<(), ActorError> {
let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just unwrap

Copy link
Contributor Author

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),
Copy link
Member

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.

Copy link
Contributor Author

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,
Copy link
Member

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

Copy link
Contributor Author

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.

.push(EmittedEvent { emitter: self.msg.to.id().unwrap(), event: event.clone() });

Copy link
Contributor Author

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.

Copy link
Member

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.

@aarshkshah1992 aarshkshah1992 changed the title Emit Sector Pre-commited and Sector Proven events for the Miner Actor Miner Actor events for Sector lifecycle Oct 26, 2023
@aarshkshah1992
Copy link
Contributor Author

aarshkshah1992 commented Oct 26, 2023

@anorth

I have addressed your review and have added events for the Sector Updated and Sector Terminated transitions. Some notes/questions:

  1. The failing integration tests are because of Miner Actor events for Sector lifecycle #1462 (comment). Should we change the test runtime to accept non-ID addresses when events are emitted or should we change the tests to only use ID addresses ? I am not sure of the tradeoffs here.

  2. There are no unit tests for the ProveReplicaUpdate* method and so no event emission tests for that. I think we will have to cover this when we get to integration tests as we do have integration tests for this work. Any suggestions/concerns ?

Copy link
Member

@anorth anorth left a 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.

@@ -878,6 +880,7 @@ impl Actor {
}
burn_funds(rt, aggregate_fee)?;
state.check_balance_invariants(&rt.current_balance()).map_err(balance_invariants_broken)?;

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done.

@@ -1484,6 +1495,8 @@ impl Actor {
rt: &impl Runtime,
sectors: Vec<SectorPreCommitInfoInner>,
) -> Result<(), ActorError> {
let miner_actor_id: u64 = rt.message().receiver().id().unwrap();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: unnecessary blank

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

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();
Copy link
Member

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.

Copy link
Contributor Author

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.

.typ("sector-precommitted")
.field_indexed("miner", &RECEIVER_ID)
.field_indexed("sector", &si.sector_number)
.build()?,
Copy link
Member

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.

Copy link
Contributor Author

@aarshkshah1992 aarshkshah1992 Oct 27, 2023

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,
Copy link
Member

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.

@aarshkshah1992
Copy link
Contributor Author

@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.

@aarshkshah1992 aarshkshah1992 merged commit af222d7 into integration/actor-events Oct 30, 2023
13 checks passed
@aarshkshah1992 aarshkshah1992 deleted the feat/miner-precommit-event branch October 30, 2023 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants