htlcswitch/link: inspect sync errors, force close channel
This commit makes the link inspect the error encountered during channel sync, force closing the channel if we detect a remote data loss.
This commit is contained in:
parent
410b730778
commit
ebed786b2a
@ -613,10 +613,7 @@ func (l *channelLink) syncChanStates() error {
|
||||
msgsToReSend, openedCircuits, closedCircuits, err =
|
||||
l.channel.ProcessChanSyncMsg(remoteChanSyncMsg)
|
||||
if err != nil {
|
||||
// TODO(roasbeef): check concrete type of error, act
|
||||
// accordingly
|
||||
return fmt.Errorf("unable to handle upstream reestablish "+
|
||||
"message: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Repopulate any identifiers for circuits that may have been
|
||||
@ -810,13 +807,71 @@ func (l *channelLink) htlcManager() {
|
||||
if l.cfg.SyncStates {
|
||||
err := l.syncChanStates()
|
||||
if err != nil {
|
||||
l.errorf("unable to synchronize channel states: %v", err)
|
||||
if err != ErrLinkShuttingDown {
|
||||
// TODO(halseth): must be revisted when
|
||||
// data-loss protection is in.
|
||||
l.fail(LinkFailureError{code: ErrSyncError},
|
||||
err.Error())
|
||||
switch {
|
||||
case err == ErrLinkShuttingDown:
|
||||
log.Debugf("unable to sync channel states, " +
|
||||
"link is shutting down")
|
||||
return
|
||||
|
||||
// We failed syncing the commit chains, probably
|
||||
// because the remote has lost state. We should force
|
||||
// close the channel.
|
||||
// TODO(halseth): store sent chanSync message to
|
||||
// database, such that it can be resent to peer in case
|
||||
// it tries to sync the channel again.
|
||||
case err == lnwallet.ErrCommitSyncRemoteDataLoss:
|
||||
fallthrough
|
||||
|
||||
// The remote sent us an invalid last commit secret, we
|
||||
// should force close the channel.
|
||||
// TODO(halseth): and permanently ban the peer?
|
||||
case err == lnwallet.ErrInvalidLastCommitSecret:
|
||||
fallthrough
|
||||
|
||||
// The remote sent us a commit point different from
|
||||
// what they sent us before.
|
||||
// TODO(halseth): ban peer?
|
||||
case err == lnwallet.ErrInvalidLocalUnrevokedCommitPoint:
|
||||
l.fail(
|
||||
LinkFailureError{
|
||||
code: ErrSyncError,
|
||||
ForceClose: true,
|
||||
},
|
||||
"unable to synchronize channel "+
|
||||
"states: %v", err,
|
||||
)
|
||||
return
|
||||
|
||||
// We have lost state and cannot safely force close the
|
||||
// channel. Fail the channel and wait for the remote to
|
||||
// hopefully force close it. The remote has sent us its
|
||||
// latest unrevoked commitment point, that we stored in
|
||||
// the database, that we can use to retrieve the funds
|
||||
// when the remote closes the channel.
|
||||
// TODO(halseth): mark this, such that we prevent
|
||||
// channel from being force closed by the user or
|
||||
// contractcourt etc.
|
||||
case err == lnwallet.ErrCommitSyncLocalDataLoss:
|
||||
|
||||
// We determined the commit chains were not possible to
|
||||
// sync. We cautiously fail the channel, but don't
|
||||
// force close.
|
||||
// TODO(halseth): can we safely force close in any
|
||||
// cases where this error is returned?
|
||||
case err == lnwallet.ErrCannotSyncCommitChains:
|
||||
|
||||
// Other, unspecified error.
|
||||
default:
|
||||
}
|
||||
|
||||
l.fail(
|
||||
LinkFailureError{
|
||||
code: ErrSyncError,
|
||||
ForceClose: false,
|
||||
},
|
||||
"unable to synchronize channel "+
|
||||
"states: %v", err,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user