@@ -556,6 +556,7 @@ access(all) contract FlowEpoch {
556556 nodes.append (FlowIDTableStaking.NodeInfo (nodeID : nodeID))
557557 }
558558
559+ // TODO: consolidate dkg phase calcs
559560 let numViewsInDKGPhase = FlowEpoch.configurableMetadata.numViewsInDKGPhase
560561 let dkgPhase1FinalView = stakingEndView + numViewsInDKGPhase
561562 let dkgPhase2FinalView = dkgPhase1FinalView + numViewsInDKGPhase
@@ -625,11 +626,14 @@ access(all) contract FlowEpoch {
625626 }
626627 }
627628
628- /// Ends the currently active epoch and starts a new one with the provided configuration.
629- /// This meta data will be emitted in the EpochRecover service event. This function differs
630- /// from recoverCurrentEpoch because it increments the epoch counter and will calculate rewards.
631- /// This function is used within sporks to recover the network from Epoch Fallback Mode (EFM).
632- access (all) fun recoverNewEpoch (recoveryEpochCounter : UInt64 ,
629+ /// Ends the currently active epoch and starts a new "recovery epoch" with the provided configuration.
630+ /// This function is used to recover from Epoch Fallback Mode (EFM).
631+ /// The "recovery epoch" config will be emitted in the EpochRecover service event.
632+ /// The "recovery epoch must have a counter exactly one greater than the current epoch counter.
633+ ///
634+ /// This function differs from recoverCurrentEpoch because it increments the epoch counter and will calculate rewards.
635+ access (all) fun recoverNewEpoch (
636+ recoveryEpochCounter : UInt64 ,
633637 startView : UInt64 ,
634638 stakingEndView : UInt64 ,
635639 endView : UInt64 ,
@@ -642,11 +646,16 @@ access(all) contract FlowEpoch {
642646 dkgIdMapping : {String : Int },
643647 nodeIDs : [String ])
644648 {
645- // sanity check recovery epoch counter should increment current epoch counter
646- assert (
647- recoveryEpochCounter == FlowEpoch.proposedEpochCounter (),
648- message : " recovery epoch counter should equal current epoch counter + 1"
649- )
649+ pre {
650+ recoveryEpochCounter == FlowEpoch.proposedEpochCounter ():
651+ " FlowEpoch.Admin.recoverNewEpoch: Recovery epoch counter must equal current epoch counter + 1. "
652+ .concat (" Got recovery epoch counter (" )
653+ .concat (recoveryEpochCounter.toString ())
654+ .concat (" ) with current epoch counter (" )
655+ .concat (FlowEpoch.currentEpochCounter.toString ())
656+ .concat (" )." )
657+ }
658+
650659 self .stopEpochComponents ()
651660 let randomSource = FlowEpoch.generateRandomSource ()
652661
@@ -693,14 +702,18 @@ access(all) contract FlowEpoch {
693702 FlowEpoch.startNewEpoch ()
694703 }
695704
696- /// Ends the currently active epoch and restarts it with the provided configuration.
697- /// This function is intended to update the current epoch configuration when a recovery
698- /// transaction needs to be submitted more than once. This function differs
699- /// from recoverNewEpoch because it does not increment the epoch counter. It also
700- /// does not calculate or distribute rewards -- calling recoverCurrentEpoch multiple times does not cause multiple reward payouts.
705+ /// Replaces the currently active epoch with a new "recovery epoch" with the provided configuration.
706+ /// This function is used to recover from Epoch Fallback Mode (EFM).
707+ /// The "recovery epoch" config will be emitted in the EpochRecover service event.
708+ /// The "recovery epoch must have a counter exactly equal to the current epoch counter.
709+ ///
710+ /// This function differs from recoverNewEpoch because it replaces the currently active epoch instead of starting a new epoch.
711+ /// This function does not calculate or distribute rewards
712+ /// Calling recoverCurrentEpoch multiple times does not cause multiple reward payouts.
701713 /// Rewards for the recovery epoch will be calculated and paid out during the course of the epoch.
702- /// This meta data will be emitted in the EpochRecover service event. This function is used
703- /// within sporks to recover the network from Epoch Fallback Mode (EFM).
714+ /// CAUTION: This causes data loss by replacing the existing current epoch metadata with the inputs to this function.
715+ /// This function exists to recover from potential race conditions that caused a prior recoverCurrentEpoch transaction to fail;
716+ /// this allows operators to retry the recovery procedure, overwriting the prior failed attempt.
704717 access (all) fun recoverCurrentEpoch (recoveryEpochCounter : UInt64 ,
705718 startView : UInt64 ,
706719 stakingEndView : UInt64 ,
@@ -779,6 +792,7 @@ access(all) contract FlowEpoch {
779792 " Invalid startView, stakingEndView, and endView configuration"
780793 }
781794
795+ // TODO: replace with stopEpochComponents?
782796 if FlowEpoch.currentEpochPhase == EpochPhase.STAKINGAUCTION {
783797 // Since we are resetting the epoch, we do not need to
784798 // start epoch setup also. We only need to end the staking auction
0 commit comments