@@ -144,6 +144,11 @@ func ExecuteChannelUpgrade(ctx context.Context, pathName string, src, dst *Prova
144
144
logger := GetChannelPairLogger (src , dst )
145
145
defer logger .TimeTrackContext (ctx , time .Now (), "ExecuteChannelUpgrade" )
146
146
147
+ if (targetSrcState == UPGRADE_STATE_UNINIT && targetDstState == UPGRADE_STATE_INIT ) ||
148
+ (targetSrcState == UPGRADE_STATE_INIT && targetDstState == UPGRADE_STATE_UNINIT ) {
149
+ return fmt .Errorf ("unreachable target state pair: (%s, %s)" , targetSrcState , targetDstState )
150
+ }
151
+
147
152
failures := 0
148
153
firstCall := true
149
154
err := runUntilComplete (ctx , interval , func () (bool , error ) {
@@ -381,12 +386,15 @@ func upgradeChannelStep(ctx context.Context, src, dst *ProvableChain, targetSrcS
381
386
),
382
387
)}
383
388
384
- // check if both chains have reached the target states or UNINIT states
385
- if srcState == targetSrcState && dstState == targetDstState {
386
- if firstCall && srcState == UPGRADE_STATE_UNINIT && dstState == UPGRADE_STATE_UNINIT {
387
- logger .InfoContext (ctx , "both chains have already reached the target states, or the channel upgrade has not been initialized" )
389
+ if hasReachedOrPassedTargetState (srcState , targetSrcState , dstState ) && hasReachedOrPassedTargetState (dstState , targetDstState , srcState ) {
390
+ if firstCall {
391
+ if srcState == UPGRADE_STATE_UNINIT && targetSrcState == UPGRADE_STATE_UNINIT {
392
+ logger .InfoContext (ctx , "both chains have already reached or passed the target states, or the channel upgrade has not been initialized" )
393
+ } else {
394
+ logger .InfoContext (ctx , "both chains have already reached or passed the target states" )
395
+ }
388
396
} else {
389
- logger .InfoContext (ctx , "both chains have reached the target states" )
397
+ logger .InfoContext (ctx , "both chains have reached or passed the target states" )
390
398
}
391
399
out .Last = true
392
400
return out , nil
@@ -397,7 +405,8 @@ func upgradeChannelStep(ctx context.Context, src, dst *ProvableChain, targetSrcS
397
405
dstAction := UPGRADE_ACTION_NONE
398
406
switch {
399
407
case srcState == UPGRADE_STATE_UNINIT && dstState == UPGRADE_STATE_UNINIT :
400
- return nil , errors .New ("channel upgrade has not been initialized; it will never reach the target states" )
408
+ // This line should never be reached because the channel upgrade is considered completed
409
+ return nil , errors .New ("unexpected transition" )
401
410
case srcState == UPGRADE_STATE_INIT && dstState == UPGRADE_STATE_UNINIT :
402
411
if dstChan .Channel .UpgradeSequence >= srcChan .Channel .UpgradeSequence {
403
412
srcAction = UPGRADE_ACTION_CANCEL
@@ -793,3 +802,31 @@ func buildActionMsg(
793
802
panic (fmt .Errorf ("unexpected action: %s" , action ))
794
803
}
795
804
}
805
+
806
+ // hasReachedOrPassedTargetState checks if the current state has reached or passed the target state,
807
+ // including cases where the target state is skipped.
808
+ func hasReachedOrPassedTargetState (currentState , targetState , counterpartyCurrentState UpgradeState ) bool {
809
+ return currentState == targetState || hasPassedTargetState (currentState , targetState , counterpartyCurrentState )
810
+ }
811
+
812
+ // hasPassedTargetState checks if the current state has passed the target state,
813
+ // including cases where the target state is skipped.
814
+ func hasPassedTargetState (currentState , targetState , counterpartyCurrentState UpgradeState ) bool {
815
+ // Check if the current state has passed the target state.
816
+ // For simplicity, we consider that any state that can be reached after the target state has passed the target state.
817
+ // NOTE: Each chain can cancel the upgrade and initialize another upgrade at any time. This means that the state
818
+ // can transition to UNINIT from any state except the case where the counterparty is in INIT state.
819
+
820
+ isUninitReachable := counterpartyCurrentState != UPGRADE_STATE_INIT
821
+ switch targetState {
822
+ case UPGRADE_STATE_INIT :
823
+ return currentState == UPGRADE_STATE_FLUSHING || currentState == UPGRADE_STATE_FLUSHCOMPLETE ||
824
+ (isUninitReachable && currentState == UPGRADE_STATE_UNINIT )
825
+ case UPGRADE_STATE_FLUSHING :
826
+ return currentState == UPGRADE_STATE_FLUSHCOMPLETE || (isUninitReachable && currentState == UPGRADE_STATE_UNINIT )
827
+ case UPGRADE_STATE_FLUSHCOMPLETE :
828
+ return isUninitReachable && currentState == UPGRADE_STATE_UNINIT
829
+ default :
830
+ return false
831
+ }
832
+ }
0 commit comments