peer/lnwallet: persist shutdown info on send
In this commit, we start persisting shutdown info when we send the Shutdown message. When starting up a link, we also first check if we have previously persisted Shutdown info and if we have, we start the link in shutdown mode meaning that it will not accept any new outgoing HTLC additions and it will queue the shutdown message after any pending CommitSig has been sent.
This commit is contained in:
3 files changed
+114
-38
No files matched your search
+84
-12
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/discovery"
|
||||
"github.com/lightningnetwork/lnd/feature"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||
@@ -986,6 +987,59 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
|
||||
continue
|
||||
}
|
||||
|
||||
shutdownInfo, err := lnChan.State().ShutdownInfo()
|
||||
if err != nil && !errors.Is(err, channeldb.ErrNoShutdownInfo) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
shutdownMsg fn.Option[lnwire.Shutdown]
|
||||
shutdownInfoErr error
|
||||
)
|
||||
shutdownInfo.WhenSome(func(info channeldb.ShutdownInfo) {
|
||||
// Compute an ideal fee.
|
||||
feePerKw, err := p.cfg.FeeEstimator.EstimateFeePerKW(
|
||||
p.cfg.CoopCloseTargetConfs,
|
||||
)
|
||||
if err != nil {
|
||||
shutdownInfoErr = fmt.Errorf("unable to "+
|
||||
"estimate fee: %w", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
chanCloser, err := p.createChanCloser(
|
||||
lnChan, info.DeliveryScript.Val, feePerKw, nil,
|
||||
info.LocalInitiator.Val,
|
||||
)
|
||||
if err != nil {
|
||||
shutdownInfoErr = fmt.Errorf("unable to "+
|
||||
"create chan closer: %w", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
chanID := lnwire.NewChanIDFromOutPoint(
|
||||
&lnChan.State().FundingOutpoint,
|
||||
)
|
||||
|
||||
p.activeChanCloses[chanID] = chanCloser
|
||||
|
||||
// Create the Shutdown message.
|
||||
shutdown, err := chanCloser.ShutdownChan()
|
||||
if err != nil {
|
||||
delete(p.activeChanCloses, chanID)
|
||||
shutdownInfoErr = err
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
shutdownMsg = fn.Some[lnwire.Shutdown](*shutdown)
|
||||
})
|
||||
if shutdownInfoErr != nil {
|
||||
return nil, shutdownInfoErr
|
||||
}
|
||||
|
||||
// Subscribe to the set of on-chain events for this channel.
|
||||
chainEvents, err := p.cfg.ChainArb.SubscribeChannelEvents(
|
||||
*chanPoint,
|
||||
@@ -996,7 +1050,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
|
||||
|
||||
err = p.addLink(
|
||||
chanPoint, lnChan, forwardingPolicy, chainEvents,
|
||||
true,
|
||||
true, shutdownMsg,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to add link %v to "+
|
||||
@@ -1014,7 +1068,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
|
||||
lnChan *lnwallet.LightningChannel,
|
||||
forwardingPolicy *models.ForwardingPolicy,
|
||||
chainEvents *contractcourt.ChainEventSubscription,
|
||||
syncStates bool) error {
|
||||
syncStates bool, shutdownMsg fn.Option[lnwire.Shutdown]) error {
|
||||
|
||||
// onChannelFailure will be called by the link in case the channel
|
||||
// fails for some reason.
|
||||
@@ -1083,6 +1137,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
|
||||
NotifyInactiveLinkEvent: p.cfg.ChannelNotifier.NotifyInactiveLinkEvent,
|
||||
HtlcNotifier: p.cfg.HtlcNotifier,
|
||||
GetAliases: p.cfg.GetAliases,
|
||||
PreviouslySentShutdown: shutdownMsg,
|
||||
}
|
||||
|
||||
// Before adding our new link, purge the switch of any pending or live
|
||||
@@ -2802,15 +2857,32 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// As mentioned above, we don't re-create the delivery script.
|
||||
deliveryScript := c.LocalShutdownScript
|
||||
if len(deliveryScript) == 0 {
|
||||
var err error
|
||||
deliveryScript, err = p.genDeliveryScript()
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to gen delivery script: %v",
|
||||
err)
|
||||
return nil, fmt.Errorf("close addr unavailable")
|
||||
var deliveryScript []byte
|
||||
|
||||
shutdownInfo, err := c.ShutdownInfo()
|
||||
switch {
|
||||
// We have previously stored the delivery script that we need to use
|
||||
// in the shutdown message. Re-use this script.
|
||||
case err == nil:
|
||||
shutdownInfo.WhenSome(func(info channeldb.ShutdownInfo) {
|
||||
deliveryScript = info.DeliveryScript.Val
|
||||
})
|
||||
|
||||
// An error other than ErrNoShutdownInfo was returned
|
||||
case err != nil && !errors.Is(err, channeldb.ErrNoShutdownInfo):
|
||||
return nil, err
|
||||
|
||||
case errors.Is(err, channeldb.ErrNoShutdownInfo):
|
||||
deliveryScript = c.LocalShutdownScript
|
||||
if len(deliveryScript) == 0 {
|
||||
var err error
|
||||
deliveryScript, err = p.genDeliveryScript()
|
||||
if err != nil {
|
||||
p.log.Errorf("unable to gen delivery script: "+
|
||||
"%v", err)
|
||||
|
||||
return nil, fmt.Errorf("close addr unavailable")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3905,7 +3977,7 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
|
||||
// Create the link and add it to the switch.
|
||||
err = p.addLink(
|
||||
chanPoint, lnChan, initialPolicy, chainEvents,
|
||||
shouldReestablish,
|
||||
shouldReestablish, fn.None[lnwire.Shutdown](),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't register new channel link(%v) with "+
|
||||
|
||||
Reference in new issue
Block a user