@@ -144,6 +144,11 @@ func ExecuteChannelUpgrade(ctx context.Context, pathName string, src, dst *Prova
144144	logger  :=  GetChannelPairLogger (src , dst )
145145	defer  logger .TimeTrackContext (ctx , time .Now (), "ExecuteChannelUpgrade" )
146146
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+ 
147152	failures  :=  0 
148153	firstCall  :=  true 
149154	err  :=  runUntilComplete (ctx , interval , func () (bool , error ) {
@@ -381,12 +386,15 @@ func upgradeChannelStep(ctx context.Context, src, dst *ProvableChain, targetSrcS
381386		),
382387	)}
383388
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+ 			}
388396		} 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" )
390398		}
391399		out .Last  =  true 
392400		return  out , nil 
@@ -397,7 +405,8 @@ func upgradeChannelStep(ctx context.Context, src, dst *ProvableChain, targetSrcS
397405	dstAction  :=  UPGRADE_ACTION_NONE 
398406	switch  {
399407	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" )
401410	case  srcState  ==  UPGRADE_STATE_INIT  &&  dstState  ==  UPGRADE_STATE_UNINIT :
402411		if  dstChan .Channel .UpgradeSequence  >=  srcChan .Channel .UpgradeSequence  {
403412			srcAction  =  UPGRADE_ACTION_CANCEL 
@@ -793,3 +802,31 @@ func buildActionMsg(
793802		panic (fmt .Errorf ("unexpected action: %s" , action ))
794803	}
795804}
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