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 =
|
msgsToReSend, openedCircuits, closedCircuits, err =
|
||||||
l.channel.ProcessChanSyncMsg(remoteChanSyncMsg)
|
l.channel.ProcessChanSyncMsg(remoteChanSyncMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(roasbeef): check concrete type of error, act
|
return err
|
||||||
// accordingly
|
|
||||||
return fmt.Errorf("unable to handle upstream reestablish "+
|
|
||||||
"message: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repopulate any identifiers for circuits that may have been
|
// Repopulate any identifiers for circuits that may have been
|
||||||
@ -810,13 +807,71 @@ func (l *channelLink) htlcManager() {
|
|||||||
if l.cfg.SyncStates {
|
if l.cfg.SyncStates {
|
||||||
err := l.syncChanStates()
|
err := l.syncChanStates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.errorf("unable to synchronize channel states: %v", err)
|
switch {
|
||||||
if err != ErrLinkShuttingDown {
|
case err == ErrLinkShuttingDown:
|
||||||
// TODO(halseth): must be revisted when
|
log.Debugf("unable to sync channel states, " +
|
||||||
// data-loss protection is in.
|
"link is shutting down")
|
||||||
l.fail(LinkFailureError{code: ErrSyncError},
|
return
|
||||||
err.Error())
|
|
||||||
|
// 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user