@@ -1086,6 +1086,83 @@ func (l *channelLink) loadAndRemove() error {
10861086 return l .channel .RemoveFwdPkgs (removeHeights ... )
10871087}
10881088
1089+ // handleChanSyncErr performs the error handling logic in the case where we
1090+ // could not successfully syncChanStates with our channel peer.
1091+ func (l * channelLink ) handleChanSyncErr (err error ) {
1092+ l .log .Warnf ("error when syncing channel states: %v" , err )
1093+
1094+ var errDataLoss * lnwallet.ErrCommitSyncLocalDataLoss
1095+
1096+ switch {
1097+ case errors .Is (err , ErrLinkShuttingDown ):
1098+ l .log .Debugf ("unable to sync channel states, link is " +
1099+ "shutting down" )
1100+ return
1101+
1102+ // We failed syncing the commit chains, probably because the remote has
1103+ // lost state. We should force close the channel.
1104+ case errors .Is (err , lnwallet .ErrCommitSyncRemoteDataLoss ):
1105+ fallthrough
1106+
1107+ // The remote sent us an invalid last commit secret, we should force
1108+ // close the channel.
1109+ // TODO(halseth): and permanently ban the peer?
1110+ case errors .Is (err , lnwallet .ErrInvalidLastCommitSecret ):
1111+ fallthrough
1112+
1113+ // The remote sent us a commit point different from what they sent us
1114+ // before.
1115+ // TODO(halseth): ban peer?
1116+ case errors .Is (err , lnwallet .ErrInvalidLocalUnrevokedCommitPoint ):
1117+ // We'll fail the link and tell the peer to force close the
1118+ // channel. Note that the database state is not updated here,
1119+ // but will be updated when the close transaction is ready to
1120+ // avoid that we go down before storing the transaction in the
1121+ // db.
1122+ l .failf (
1123+ LinkFailureError {
1124+ code : ErrSyncError ,
1125+ FailureAction : LinkFailureForceClose ,
1126+ },
1127+ "unable to synchronize channel states: %v" , err ,
1128+ )
1129+
1130+ // We have lost state and cannot safely force close the channel. Fail
1131+ // the channel and wait for the remote to hopefully force close it. The
1132+ // remote has sent us its latest unrevoked commitment point, and we'll
1133+ // store it in the database, such that we can attempt to recover the
1134+ // funds if the remote force closes the channel.
1135+ case errors .As (err , & errDataLoss ):
1136+ err := l .channel .MarkDataLoss (
1137+ errDataLoss .CommitPoint ,
1138+ )
1139+ if err != nil {
1140+ l .log .Errorf ("unable to mark channel data loss: %v" ,
1141+ err )
1142+ }
1143+
1144+ // We determined the commit chains were not possible to sync. We
1145+ // cautiously fail the channel, but don't force close.
1146+ // TODO(halseth): can we safely force close in any cases where this
1147+ // error is returned?
1148+ case errors .Is (err , lnwallet .ErrCannotSyncCommitChains ):
1149+ if err := l .channel .MarkBorked (); err != nil {
1150+ l .log .Errorf ("unable to mark channel borked: %v" , err )
1151+ }
1152+
1153+ // Other, unspecified error.
1154+ default :
1155+ }
1156+
1157+ l .failf (
1158+ LinkFailureError {
1159+ code : ErrRecoveryError ,
1160+ FailureAction : LinkFailureForceNone ,
1161+ },
1162+ "unable to synchronize channel states: %v" , err ,
1163+ )
1164+ }
1165+
10891166// htlcManager is the primary goroutine which drives a channel's commitment
10901167// update state-machine in response to messages received via several channels.
10911168// This goroutine reads messages from the upstream (remote) peer, and also from
@@ -1121,89 +1198,7 @@ func (l *channelLink) htlcManager() {
11211198 if l .cfg .SyncStates {
11221199 err := l .syncChanStates ()
11231200 if err != nil {
1124- l .log .Warnf ("error when syncing channel states: %v" , err )
1125-
1126- errDataLoss , localDataLoss :=
1127- err .(* lnwallet.ErrCommitSyncLocalDataLoss )
1128-
1129- switch {
1130- case err == ErrLinkShuttingDown :
1131- l .log .Debugf ("unable to sync channel states, " +
1132- "link is shutting down" )
1133- return
1134-
1135- // We failed syncing the commit chains, probably
1136- // because the remote has lost state. We should force
1137- // close the channel.
1138- case err == lnwallet .ErrCommitSyncRemoteDataLoss :
1139- fallthrough
1140-
1141- // The remote sent us an invalid last commit secret, we
1142- // should force close the channel.
1143- // TODO(halseth): and permanently ban the peer?
1144- case err == lnwallet .ErrInvalidLastCommitSecret :
1145- fallthrough
1146-
1147- // The remote sent us a commit point different from
1148- // what they sent us before.
1149- // TODO(halseth): ban peer?
1150- case err == lnwallet .ErrInvalidLocalUnrevokedCommitPoint :
1151- // We'll fail the link and tell the peer to
1152- // force close the channel. Note that the
1153- // database state is not updated here, but will
1154- // be updated when the close transaction is
1155- // ready to avoid that we go down before
1156- // storing the transaction in the db.
1157- l .failf (
1158- //nolint:lll
1159- LinkFailureError {
1160- code : ErrSyncError ,
1161- FailureAction : LinkFailureForceClose ,
1162- },
1163- "unable to synchronize channel " +
1164- "states: %v" , err ,
1165- )
1166- return
1167-
1168- // We have lost state and cannot safely force close the
1169- // channel. Fail the channel and wait for the remote to
1170- // hopefully force close it. The remote has sent us its
1171- // latest unrevoked commitment point, and we'll store
1172- // it in the database, such that we can attempt to
1173- // recover the funds if the remote force closes the
1174- // channel.
1175- case localDataLoss :
1176- err := l .channel .MarkDataLoss (
1177- errDataLoss .CommitPoint ,
1178- )
1179- if err != nil {
1180- l .log .Errorf ("unable to mark channel " +
1181- "data loss: %v" , err )
1182- }
1183-
1184- // We determined the commit chains were not possible to
1185- // sync. We cautiously fail the channel, but don't
1186- // force close.
1187- // TODO(halseth): can we safely force close in any
1188- // cases where this error is returned?
1189- case err == lnwallet .ErrCannotSyncCommitChains :
1190- if err := l .channel .MarkBorked (); err != nil {
1191- l .log .Errorf ("unable to mark channel " +
1192- "borked: %v" , err )
1193- }
1194-
1195- // Other, unspecified error.
1196- default :
1197- }
1198-
1199- l .failf (
1200- LinkFailureError {
1201- code : ErrRecoveryError ,
1202- FailureAction : LinkFailureForceNone ,
1203- },
1204- "unable to synchronize channel " +
1205- "states: %v" , err ,
1206- )
1201+ l .handleChanSyncErr (err )
12071202 return
12081203 }
12091204 }
0 commit comments