Skip to content

Commit a0515a1

Browse files
committed
htlcswitch: extract error handling for syncChanStates
1 parent 5c3a8e9 commit a0515a1

File tree

1 file changed

+78
-83
lines changed

1 file changed

+78
-83
lines changed

htlcswitch/link.go

Lines changed: 78 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)