Skip to content

Commit ec491be

Browse files
committed
multi: wire taproot RBF support throughout the stack
In this commit we, integrate the taproot RBF cooperative close functionality throughout the LND stack. This includes updating protocol configuration and peer connection handling to support the new taproot closing flow. The changes wire through the taproot channel detection, nonce exchange during shutdown, and proper handling of the enhanced wire protocol messages in the peer layer. This completes the integration of taproot RBF cooperative close functionality, providing a complete alternate closing path for taproot channels that leverages MuSig2 signatures and implements proper nonce rotation for secure RBF scenarios.
1 parent 0836a5e commit ec491be

File tree

2 files changed

+18
-20
lines changed

2 files changed

+18
-20
lines changed

lncfg/protocol.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type ProtocolOptions struct {
3737

3838
// RbfCoopClose should be set if we want to signal that we support for
3939
// the new experimental RBF coop close feature.
40-
RbfCoopClose bool `long:"rbf-coop-close" description:"if set, then lnd will signal that it supports the new RBF based coop close protocol, taproot channels are not supported"`
40+
RbfCoopClose bool `long:"rbf-coop-close" description:"if set, then lnd will signal that it supports the new RBF based coop close protocol"`
4141

4242
// NoAnchors should be set if we don't want to support opening or accepting
4343
// channels having the anchor commitment type.

peer/brontide.go

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,17 +1243,15 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
12431243
return nil, err
12441244
}
12451245

1246-
isTaprootChan := lnChan.ChanType().IsTaproot()
12471246

12481247
var (
12491248
shutdownMsg fn.Option[lnwire.Shutdown]
12501249
shutdownInfoErr error
12511250
)
12521251
shutdownInfo.WhenSome(func(info channeldb.ShutdownInfo) {
12531252
// If we can use the new RBF close feature, we don't
1254-
// need to create the legacy closer. However for taproot
1255-
// channels, we'll continue to use the legacy closer.
1256-
if p.rbfCoopCloseAllowed() && !isTaprootChan {
1253+
// need to create the legacy closer.
1254+
if p.rbfCoopCloseAllowed() {
12571255
return
12581256
}
12591257

@@ -1330,10 +1328,8 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
13301328
p.activeChannels.Store(chanID, lnChan)
13311329

13321330
// We're using the old co-op close, so we don't need to init
1333-
// the new RBF chan closer. If we have a taproot chan, then
1334-
// we'll also use the legacy type, so we don't need to make the
1335-
// new closer.
1336-
if !p.rbfCoopCloseAllowed() || isTaprootChan {
1331+
// the new RBF chan closer.
1332+
if !p.rbfCoopCloseAllowed() {
13371333
continue
13381334
}
13391335

@@ -3312,7 +3308,6 @@ func chooseDeliveryScript(upfront, requested lnwire.DeliveryAddress,
33123308
func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
33133309
*lnwire.Shutdown, error) {
33143310

3315-
isTaprootChan := lnChan.ChanType().IsTaproot()
33163311

33173312
// If this channel has status ChanStatusCoopBroadcasted and does not
33183313
// have a closing transaction, then the cooperative close process was
@@ -3366,8 +3361,8 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
33663361

33673362
// If the new RBF co-op close is negotiated, then we'll init and start
33683363
// that state machine, skipping the steps for the negotiate machine
3369-
// below. We don't support this close type for taproot channels though.
3370-
if p.rbfCoopCloseAllowed() && !isTaprootChan {
3364+
// below.
3365+
if p.rbfCoopCloseAllowed() {
33713366
_, err := p.initRbfChanCloser(lnChan)
33723367
if err != nil {
33733368
return nil, fmt.Errorf("unable to init rbf chan "+
@@ -3910,6 +3905,14 @@ func (p *Brontide) initRbfChanCloser(
39103905
),
39113906
}
39123907

3908+
// For taproot channels, we need to set both LocalMusigSession and
3909+
// RemoteMusigSession to handle nonce exchange during RBF cooperative close.
3910+
if channel.ChanType().IsTaproot() {
3911+
musigCloser := NewMusigChanCloser(channel)
3912+
env.LocalMusigSession = musigCloser
3913+
env.RemoteMusigSession = musigCloser
3914+
}
3915+
39133916
spendEvent := protofsm.RegisterSpend[chancloser.ProtocolEvent]{
39143917
OutPoint: channel.ChannelPoint(),
39153918
PkScript: channel.FundingTxOut().PkScript,
@@ -4221,7 +4224,6 @@ func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
42214224
return
42224225
}
42234226

4224-
isTaprootChan := channel.ChanType().IsTaproot()
42254227

42264228
switch req.CloseType {
42274229
// A type of CloseRegular indicates that the user has opted to close
@@ -4235,9 +4237,7 @@ func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
42354237
// iteration, in which case we'll be obtaining a new
42364238
// transaction w/ a higher fee rate.
42374239
//
4238-
// We don't support this close type for taproot channels yet
4239-
// however.
4240-
case !isTaprootChan && p.rbfCoopCloseAllowed():
4240+
case p.rbfCoopCloseAllowed():
42414241
err = p.startRbfChanCloser(
42424242
newRPCShutdownInit(req), channel.ChannelPoint(),
42434243
)
@@ -5196,12 +5196,10 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
51965196
"peer", chanPoint)
51975197
}
51985198

5199-
isTaprootChan := c.ChanType.IsTaproot()
52005199

52015200
// We're using the old co-op close, so we don't need to init the new RBF
5202-
// chan closer. If this is a taproot channel, then we'll also fall
5203-
// through, as we don't support this type yet w/ rbf close.
5204-
if !p.rbfCoopCloseAllowed() || isTaprootChan {
5201+
// chan closer.
5202+
if !p.rbfCoopCloseAllowed() {
52055203
return nil
52065204
}
52075205

0 commit comments

Comments
 (0)