contractcourt: don't wait for DLP point if commit is tweakless on remote close
In this commit, we update the logic in the `chainWatcher` to no longer wait until the DLP point has been populated in the database before we dispatch the force close summary to any registered clients. Instead, we can sweep immediately, as we have all the information we need to sweep the funds (just our key).
This commit is contained in:
parent
fdec603279
commit
d22f2a1936
@ -584,48 +584,32 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) {
|
|||||||
"state #%v!!! Attempting recovery...",
|
"state #%v!!! Attempting recovery...",
|
||||||
broadcastStateNum, remoteStateNum)
|
broadcastStateNum, remoteStateNum)
|
||||||
|
|
||||||
// If we are lucky, the remote peer sent us the correct
|
tweaklessCommit := (c.cfg.chanState.ChanType ==
|
||||||
// commitment point during channel sync, such that we
|
channeldb.SingleFunderTweakless)
|
||||||
// can sweep our funds. If we cannot find the commit
|
|
||||||
// point, there's not much we can do other than wait
|
|
||||||
// for us to retrieve it. We will attempt to retrieve
|
|
||||||
// it from the peer each time we connect to it.
|
|
||||||
//
|
|
||||||
// TODO(halseth): actively initiate re-connection to
|
|
||||||
// the peer?
|
|
||||||
var commitPoint *btcec.PublicKey
|
|
||||||
backoff := minCommitPointPollTimeout
|
|
||||||
for {
|
|
||||||
commitPoint, err = c.cfg.chanState.DataLossCommitPoint()
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Errorf("Unable to retrieve commitment "+
|
// If this isn't a tweakless commitment, then we'll
|
||||||
"point for channel(%v) with lost "+
|
// need to wait for the remote party's latest unrevoked
|
||||||
"state: %v. Retrying in %v.",
|
// commitment point to be presented to us as we need
|
||||||
c.cfg.chanState.FundingOutpoint,
|
// this to sweep. Otherwise, we can dispatch the remote
|
||||||
err, backoff)
|
// close and sweep immediately using a fake commitPoint
|
||||||
|
// as it isn't actually needed for recovery anymore.
|
||||||
select {
|
commitPoint := c.cfg.chanState.RemoteCurrentRevocation
|
||||||
// Wait before retrying, with an exponential
|
if !tweaklessCommit {
|
||||||
// backoff.
|
commitPoint = c.waitForCommitmentPoint()
|
||||||
case <-time.After(backoff):
|
if commitPoint == nil {
|
||||||
backoff = 2 * backoff
|
|
||||||
if backoff > maxCommitPointPollTimeout {
|
|
||||||
backoff = maxCommitPointPollTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-c.quit:
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Recovered commit point(%x) for "+
|
log.Infof("Recovered commit point(%x) for "+
|
||||||
"channel(%v)! Now attempting to use it to "+
|
"channel(%v)! Now attempting to use it to "+
|
||||||
"sweep our funds...",
|
"sweep our funds...",
|
||||||
commitPoint.SerializeCompressed(),
|
commitPoint.SerializeCompressed(),
|
||||||
c.cfg.chanState.FundingOutpoint)
|
c.cfg.chanState.FundingOutpoint)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.Infof("ChannelPoint(%v) is tweakless, " +
|
||||||
|
"moving to sweep directly on chain")
|
||||||
|
}
|
||||||
|
|
||||||
// Since we don't have the commitment stored for this
|
// Since we don't have the commitment stored for this
|
||||||
// state, we'll just pass an empty commitment within
|
// state, we'll just pass an empty commitment within
|
||||||
@ -1009,3 +993,39 @@ func (c *chainWatcher) dispatchContractBreach(spendEvent *chainntnfs.SpendDetail
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitForCommitmentPoint waits for the commitment point to be inserted into
|
||||||
|
// the local database. We'll use this method in the DLP case, to wait for the
|
||||||
|
// remote party to send us their point, as we can't proceed until we have that.
|
||||||
|
func (c *chainWatcher) waitForCommitmentPoint() *btcec.PublicKey {
|
||||||
|
// If we are lucky, the remote peer sent us the correct commitment
|
||||||
|
// point during channel sync, such that we can sweep our funds. If we
|
||||||
|
// cannot find the commit point, there's not much we can do other than
|
||||||
|
// wait for us to retrieve it. We will attempt to retrieve it from the
|
||||||
|
// peer each time we connect to it.
|
||||||
|
//
|
||||||
|
// TODO(halseth): actively initiate re-connection to the peer?
|
||||||
|
backoff := minCommitPointPollTimeout
|
||||||
|
for {
|
||||||
|
commitPoint, err := c.cfg.chanState.DataLossCommitPoint()
|
||||||
|
if err == nil {
|
||||||
|
return commitPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Errorf("Unable to retrieve commitment point for "+
|
||||||
|
"channel(%v) with lost state: %v. Retrying in %v.",
|
||||||
|
c.cfg.chanState.FundingOutpoint, err, backoff)
|
||||||
|
|
||||||
|
select {
|
||||||
|
// Wait before retrying, with an exponential backoff.
|
||||||
|
case <-time.After(backoff):
|
||||||
|
backoff = 2 * backoff
|
||||||
|
if backoff > maxCommitPointPollTimeout {
|
||||||
|
backoff = maxCommitPointPollTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-c.quit:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user