Skip to content

Commit b6571e0

Browse files
committed
Refactor ExecuteChannelUpgrade
Signed-off-by: abicky <takeshi.arabiki@gmail.com>
1 parent d883820 commit b6571e0

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

core/channel-upgrade.go

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,8 @@ 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-
// Assume the current state pair is (INIT, UNINIT).
148-
// The target state pair (INIT, UNINIT) and (UNINIT, INIT) are invalid:
149-
// - (INIT, UNINIT) is meaningless as a target since this function won't cause any state change
150-
// - (UNINIT, INIT) is unreachable
151-
// Therefore, it is unlikely that a user would intentionally set either pair after
152-
// initializing an upgrade on only one side, so return an error.
153-
if (targetSrcState == UPGRADE_STATE_UNINIT && targetDstState == UPGRADE_STATE_INIT) ||
154-
(targetSrcState == UPGRADE_STATE_INIT && targetDstState == UPGRADE_STATE_UNINIT) {
155-
return fmt.Errorf("unreachable target state pair: (%s, %s)", targetSrcState, targetDstState)
147+
if err := validateTargetStates(targetSrcState, targetDstState); err != nil {
148+
return err
156149
}
157150

158151
failures := 0
@@ -167,7 +160,7 @@ func ExecuteChannelUpgrade(ctx context.Context, pathName string, src, dst *Prova
167160
firstCall = false
168161

169162
if steps.Last {
170-
logger.InfoContext(ctx, "Channel upgrade completed")
163+
logger.InfoContext(ctx, "Channel upgrade steps completed up to the target states. Check the resulting states, as cancellations or timeouts can also lead to this result.")
171164
return true, nil
172165
}
173166

@@ -809,21 +802,55 @@ func buildActionMsg(
809802
}
810803
}
811804

812-
// hasReachedOrPassedTargetState checks if the current state has reached or passed the target state,
813-
// including cases where the target state is skipped.
805+
// validateTargetStates returns an error if the target state pair is meaningless or unreachable.
806+
// Assume the current state pair is (INIT, UNINIT).
807+
//
808+
// - The target state pair (INIT, UNINIT) is meaningless as a target
809+
// because this function would not cause any state change.
810+
// - The target state pair (UNINIT, INIT) is unreachable.
811+
//
812+
// Therefore, it is unlikely that a user would intentionally specify either pair
813+
// after initializing an upgrade on only one side, so we treat them as invalid
814+
// and return an error.
815+
//
816+
// This validation also simplifies the logic of hasPassedTargetState.
817+
// For example,
818+
//
819+
// - target state pair: (UNINIT, INIT)
820+
// - current state pair: (INIT, UNINIT)
821+
//
822+
// In this case, hasPassedTargetState(UNINIT, INIT, INIT) returns false
823+
// and the upgrade proceeds to the next step, which is unexpected.
824+
// By rejecting this target state pair, the function does not need to handle this case.
825+
func validateTargetStates(targetSrcState, targetDstState UpgradeState) error {
826+
if (targetSrcState == UPGRADE_STATE_UNINIT && targetDstState == UPGRADE_STATE_INIT) ||
827+
(targetSrcState == UPGRADE_STATE_INIT && targetDstState == UPGRADE_STATE_UNINIT) {
828+
return fmt.Errorf("unreachable target state pair: (%s, %s)", targetSrcState, targetDstState)
829+
}
830+
831+
return nil
832+
}
833+
834+
// hasReachedOrPassedTargetState checks if the current state has reached or passed the target state.
835+
// For more details, see hasPassedTargetState.
814836
func hasReachedOrPassedTargetState(currentState, targetState, counterpartyCurrentState UpgradeState) bool {
815837
return currentState == targetState || hasPassedTargetState(currentState, targetState, counterpartyCurrentState)
816838
}
817839

818840
// hasPassedTargetState checks if the current state has passed the target state,
819-
// including cases where the target state is skipped.
841+
// including cases where the target state is skipped. For example, UPGRADE_STATE_INIT can transition
842+
// directly to UPGRADE_STATE_FLUSHCOMPLETE, skipping UPGRADE_STATE_FLUSHING.
820843
func hasPassedTargetState(currentState, targetState, counterpartyCurrentState UpgradeState) bool {
821844
// Each chain can cancel the upgrade and initialize another upgrade at any time. This means that the state
822-
// can transition to UNINIT from any state except the case where the counterparty is in INIT state.
845+
// can transition to UNINIT from any state.
846+
// However, in the case where the counterparty state is INIT, the current state can be UNINIT when the upgrade
847+
// has not been initialized. In this case this function should return false,
848+
// so we treat UNINIT as unreachable.
823849
isUninitReachable := counterpartyCurrentState != UPGRADE_STATE_INIT
824850

825851
// Check if the current state has passed the target state.
826-
// For simplicity, we consider that any state that can be reached after the target state has passed the target state.
852+
// For simplicity, any state reachable after the target state is considered to have passed the target state,
853+
// including cases where the upgrade has been cancelled or timed out.
827854
switch targetState {
828855
case UPGRADE_STATE_INIT:
829856
return currentState == UPGRADE_STATE_FLUSHING || currentState == UPGRADE_STATE_FLUSHCOMPLETE ||

0 commit comments

Comments
 (0)