-
Notifications
You must be signed in to change notification settings - Fork 179
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
[EFM] Add Epoch Fallback Phase #6116
[EFM] Add Epoch Fallback Phase #6116
Conversation
- checked EpochProtocolStateEntry.EpochPhase
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/efm-recovery #6116 +/- ##
=======================================================
Coverage ? 41.67%
=======================================================
Files ? 1972
Lines ? 139198
Branches ? 0
=======================================================
Hits ? 58016
Misses ? 75130
Partials ? 6052
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
Nice work. Looks good.
Overall, I have one request to properly document the convention when we have the
For now, I would just drop the following documentation into all the different places mentioned above. I have tried to not only document the epoch phases but also when the notifications are emitted. Please check that it is correct. While it is a lot of words, I think it is super important to unambiguously specify our convention (both for people using the code as well as for engineers attempting to extend the code later to not break anything). // EpochPhase returns the current epoch phase. During normal operations, each Epoch transitions through
// the phases:
//
// ║ Epoch N
// ║ ╭─────────────────────────────────┴─────────────────────────────────╮
// ║ finalize view EpochSetup EpochCommit
// ║ in epoch N service event service event
// ║ ⇣ ⇣ ⇣
// ║ ┌─────────────────┐ ┌───────────────┐ ┌───────────────────┐
// ║ │EpochPhaseStaking├─────►EpochPhaseSetup├─────►EpochPhaseCommitted├ ┄>
// ║ └─────────────────┘ └───────────────┘ └───────────────────┘
// ║ ⇣ ⇣ ⇣
// ║ EpochTransition EpochSetupPhaseStarted EpochCommittedPhaseStarted
// ║ Notification Notification Notification
//
// However, if the Protocol State encounters any unexpected epoch service events, or the subsequent epoch
// fails to be committed by the `EpochCommitSafetyThreshold`, then we enter Epoch Fallback Mode [EFM].
// Depending on whether the subsequent epoch has already been committed, the EFM progress differs slightly.
// In a nutshell, we always enter the _latest_ epoch already committed on the happy path (if there is any)
// and the follow the fallback protocol.
//
// Scenario A: the future Epoch N is already committed, when we enter EFM
//
// ║ Epoch N-1 Epoch N
// ║ ···──┴─────────────────────────╮ ╭─────────────┴───────────────────────────────────────────────╮
// ║ invalid service finalize view EpochRecover
// ║ event in epoch N service event
// ║ ⇣ ⇣ ┊ ⇣
// ║ ┌──────────────────────────┐ ┌────────────────────┊────┐ ┌───────────────────────────┐
// ║ │ EpochPhaseCommitted ├────► EpochPhaseFallback ├─────► EpochPhaseCommitted ├ ┄>
// ║ └──────────────────────────┘ └────────────────────┊────┘ └───────────────────────────┘
// ║ ⇣ ⇣ ┊ ⇣
// ║ EpochFallbackModeTriggered EpochTransition EpochExtended* EpochFallbackModeExited
// ║ Notification Notification Notification + EpochCommittedPhaseStarted Notifications
// ║ ┆ ┆
// ║ ╰┄┄┄┄┄┄┄┄┄┄ EpochFallbackTriggered is true ┄┄┄┄┄┄┄┄┄┄┄┄╯
//
// With 'EpochExtended*' we denote that there can be zero, one, or more Epoch Extension (depending on when
// we receive a valid EpochRecover service event.
//
// Scenario B: we are in Epoch N without any subsequent epoch being committed when entering EFM
//
// ║ Epoch N
// ║ ···────────────────────────┴───────────────────────────────────────────────────────────────╮
// ║ invalid service event or EpochRecover
// ║ EpochCommitSafetyThreshold reached service event
// ║ ⇣ ┊ ⇣
// ║ ┌────────────────────┐ ┌──────────────────────┊──────┐ ┌───────────────────────────┐
// ║ │ EpochPhaseStaking │ │ EpochPhaseFallback │ │ EpochPhaseCommitted │
// ║ │ or EpochPhaseSetup ├───► ┊ ├─────► ├ ┄>
// ║ └────────────────────┘ └──────────────────────┊──────┘ └───────────────────────────┘
// ║ ⇣ ┊ ⇣
// ║ EpochFallbackModeTriggered EpochExtended* EpochFallbackModeExited
// ║ Notification Notification + EpochCommittedPhaseStarted Notifications
// ║ ┆ ┆
// ║ ╰┄┄ EpochFallbackTriggered true ┄┄┄┄╯
func (e *EpochProtocolStateEntry) EpochPhase() EpochPhase { |
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.
Very clean PR, nicely done!
I've added the extended documentation only to flow.EpochPhase and linked to it in the other locations.
I added this to
Thank you for the excellent in-depth documentation. I have incorporated this into the |
This PR adds a new epoch phase to the data model, representing a state where epoch fallback mode has been triggered and we are within the view range of the latest committed epoch.
This phase is subtly different than the existing
EpochFallbackTriggered
flag in the protocol state:EpochFallbackTriggered
may be true while inEpochPhaseCommitted
(in this case the protocol state flag and the epoch phase are "unsynchronized")EpochPhaseCommitted
, then whenEpochFallbackTriggered
is true, we must be inEpochPhaseFallback