Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chancloser+lnwire: add range-based negotiation #7062

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions channeldb/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,51 @@ func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
return input.ComputeCommitmentPoint(revocation[:]), nil
}

// PersistDeliveryScript is used during the cooperative close flow to persist
// a script sent in Shutdown when we did not set an upfront shutdown script
// during the funding flow.
func (c *OpenChannel) PersistDeliveryScript(
deliveryScript lnwire.DeliveryAddress) error {

c.Lock()
defer c.Unlock()

if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
chanBucket, err := fetchChanBucketRw(
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
)
if err != nil {
return err
}

channel, err := fetchOpenChannel(
chanBucket, &c.FundingOutpoint,
)
if err != nil {
return err
}

channel.LocalShutdownScript = deliveryScript

return putOpenChannel(chanBucket, channel)
}, func() {}); err != nil {
return err
}

c.LocalShutdownScript = deliveryScript

return nil
}

// GetLocalShutdownScript fetches the local shutdown script with the read
// mutex.
func (c *OpenChannel) GetLocalShutdownScript() lnwire.DeliveryAddress {
c.RLock()
defer c.RUnlock()

return c.LocalShutdownScript
}

// ChanSyncMsg returns the ChannelReestablish message that should be sent upon
// reconnection with the remote peer that we're maintaining this channel with.
// The information contained within this message is necessary to re-sync our
Expand Down
11 changes: 11 additions & 0 deletions lnwallet/chancloser/chancloser.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,17 @@ func (c *ChanCloser) initChanShutdown() (*lnwire.Shutdown, error) {
c.chanPoint, err)
}

// Persist the delivery script used before marking the state as coop
// broadcasted so we can recover in case of a crash.
if len(c.Channel().LocalUpfrontShutdownScript()) == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we also commit the fee range at this point as well? This way we can deterministically resume if the connection dies for w/e reason.

err := c.Channel().State().PersistDeliveryScript(
c.localDeliveryScript,
)
if err != nil {
return nil, err
}
}

// Before continuing, mark the channel as cooperatively closed with a nil
// txn. Even though we haven't negotiated the final txn, this guarantees
// that our listchannels rpc will be externally consistent, and reflect
Expand Down
2 changes: 1 addition & 1 deletion lnwallet/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -5654,7 +5654,7 @@ func (lc *LightningChannel) ShortChanID() lnwire.ShortChannelID {
// LocalUpfrontShutdownScript returns the local upfront shutdown script for the
// channel. If it was not set, an empty byte array is returned.
func (lc *LightningChannel) LocalUpfrontShutdownScript() lnwire.DeliveryAddress {
return lc.channelState.LocalShutdownScript
return lc.channelState.GetLocalShutdownScript()
}

// RemoteUpfrontShutdownScript returns the remote upfront shutdown script for the
Expand Down
11 changes: 6 additions & 5 deletions peer/brontide.go
Original file line number Diff line number Diff line change
Expand Up @@ -2664,9 +2664,9 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
// have a closing transaction, then the cooperative close process was
// started but never finished. We'll re-create the chanCloser state
// machine and resend Shutdown. BOLT#2 requires that we retransmit
// Shutdown exactly, but doing so would mean persisting the RPC
// provided close script. Instead use the LocalUpfrontShutdownScript
// or generate a script.
// Shutdown exactly, but for 0.15.0 nodes, we don't persist the RPC
// provided close script. 0.16.0 nodes do persist the closing script
// if it's not an upfront shutdown script.
c := lnChan.State()
_, err := c.BroadcastedCooperative()
if err != nil && err != channeldb.ErrNoCloseTx {
Expand All @@ -2678,8 +2678,9 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
return nil, nil
}

// As mentioned above, we don't re-create the delivery script.
deliveryScript := c.LocalShutdownScript
// As mentioned above, we may not re-create the delivery script for
// older nodes.
deliveryScript := c.GetLocalShutdownScript()
if len(deliveryScript) == 0 {
var err error
deliveryScript, err = p.genDeliveryScript()
Expand Down
5 changes: 3 additions & 2 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4210,9 +4210,10 @@ func createRPCOpenChannel(r *rpcServer, dbChannel *channeldb.OpenChannel,
channel.PushAmountSat = uint64(amt)
}

if len(dbChannel.LocalShutdownScript) > 0 {
if len(dbChannel.GetLocalShutdownScript()) > 0 {
_, addresses, _, err := txscript.ExtractPkScriptAddrs(
dbChannel.LocalShutdownScript, r.cfg.ActiveNetParams.Params,
dbChannel.GetLocalShutdownScript(),
r.cfg.ActiveNetParams.Params,
)
if err != nil {
return nil, err
Expand Down