mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-14 18:30:52 +02:00
contractcourt/chain_watcher: attempt dispatchRemoteClose using data loss commitPoint
This commit makes the chainwatcher attempt to dispatch a remote close when it detects a remote state with a state number higher than our known remote state. This can mean that we lost some state, and we check the database for (hopefully) a data loss commit point retrieved during channel sync with the remote peer. If this commit point is found in the database we use it to try to recover our funds from the commitment.
This commit is contained in:
@@ -372,15 +372,50 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) {
|
|||||||
c.cfg.chanState.FundingOutpoint, err)
|
c.cfg.chanState.FundingOutpoint, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the case that somehow the commitment
|
// This is the case that somehow the commitment broadcast is
|
||||||
// broadcast is actually greater than even one beyond
|
// actually greater than even one beyond our best known state
|
||||||
// our best known state number. This should NEVER
|
// number. This should ONLY happen in case we experienced some
|
||||||
// happen, but we'll log it in any case.
|
// sort of data loss.
|
||||||
case broadcastStateNum > remoteStateNum+1:
|
case broadcastStateNum > remoteStateNum+1:
|
||||||
log.Errorf("Remote node broadcast state #%v, "+
|
log.Warnf("Remote node broadcast state #%v, "+
|
||||||
"which is more than 1 beyond best known "+
|
"which is more than 1 beyond best known "+
|
||||||
"state #%v!!!", broadcastStateNum,
|
"state #%v!!! Attempting recovery...",
|
||||||
remoteStateNum)
|
broadcastStateNum, remoteStateNum)
|
||||||
|
|
||||||
|
// If we are lucky, the remote peer sent us the correct
|
||||||
|
// commitment point during channel sync, such that we
|
||||||
|
// can sweep our funds.
|
||||||
|
// TODO(halseth): must handle the case where we haven't
|
||||||
|
// yet processed the chan sync message.
|
||||||
|
commitPoint, err := c.cfg.chanState.DataLossCommitPoint()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to retrieve commitment "+
|
||||||
|
"point for channel(%v) with lost "+
|
||||||
|
"state: %v",
|
||||||
|
c.cfg.chanState.FundingOutpoint, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Recovered commit point(%x) for "+
|
||||||
|
"channel(%v)! Now attempting to use it to "+
|
||||||
|
"sweep our funds...",
|
||||||
|
commitPoint.SerializeCompressed(),
|
||||||
|
c.cfg.chanState.FundingOutpoint)
|
||||||
|
|
||||||
|
// Since we don't have the commitment stored for this
|
||||||
|
// state, we'll just pass an empty commitment. Note
|
||||||
|
// that this means we won't be able to recover any HTLC
|
||||||
|
// funds.
|
||||||
|
// TODO(halseth): can we try to recover some HTLCs?
|
||||||
|
err = c.dispatchRemoteForceClose(
|
||||||
|
commitSpend, channeldb.ChannelCommitment{},
|
||||||
|
commitPoint,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to handle remote "+
|
||||||
|
"close for chan_point=%v: %v",
|
||||||
|
c.cfg.chanState.FundingOutpoint, err)
|
||||||
|
}
|
||||||
|
|
||||||
// If the state number broadcast is lower than the
|
// If the state number broadcast is lower than the
|
||||||
// remote node's current un-revoked height, then
|
// remote node's current un-revoked height, then
|
||||||
|
Reference in New Issue
Block a user