diff --git a/peer/brontide.go b/peer/brontide.go index f50cba89b..7023707d8 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -141,8 +141,22 @@ type closeMsg struct { // PendingUpdate describes the pending state of a closing channel. type PendingUpdate struct { - Txid []byte + // Txid is the txid of the closing transaction. + Txid []byte + + // OutputIndex is the output index of our output in the closing + // transaction. OutputIndex uint32 + + // FeePerVByte is an optional field, that is set only when the new RBF + // coop close flow is used. This indicates the new closing fee rate on + // the closing transaction. + FeePerVbyte fn.Option[chainfee.SatPerVByte] + + // IsLocalCloseTx is an optional field that indicates if this update is + // sent for our local close txn, or the close txn of the remote party. + // This is only set if the new RBF coop close flow is used. + IsLocalCloseTx fn.Option[bool] } // ChannelCloseUpdate contains the outcome of the close channel operation. @@ -3516,7 +3530,10 @@ func (p *Brontide) observeRbfCloseUpdates(chanCloser *chancloser.RbfChanCloser, newStateChan := coopCloseStates.NewItemCreated.ChanOut() - var lastLocalTxid, lastRemoteTxid chainhash.Hash + var ( + lastLocalTxid, lastRemoteTxid chainhash.Hash + lastFeeRate chainfee.SatPerVByte + ) maybeNotifyTxBroadcast := func(state chancloser.AsymmetricPeerState, local bool) { @@ -3529,6 +3546,20 @@ func (p *Brontide) observeRbfCloseUpdates(chanCloser *chancloser.RbfChanCloser, return } + // Only notify if the fee rate is greater. + if closePending.FeeRate <= lastFeeRate { + return + } + + lastFeeRate = closePending.FeeRate + + // We'll also only notify if the transaction was actually able + // to enter the mempool. + err := p.cfg.Wallet.PublishTransaction(closePending.CloseTx, "") + if err != nil { + return + } + lastTxid := lastLocalTxid if !local { lastTxid = lastRemoteTxid @@ -3540,10 +3571,11 @@ func (p *Brontide) observeRbfCloseUpdates(chanCloser *chancloser.RbfChanCloser, closingTxid := closePending.CloseTx.TxHash() if closeReq != nil && closingTxid != lastTxid { closeReq.Updates <- &PendingUpdate{ - Txid: closingTxid[:], + Txid: closingTxid[:], + FeePerVbyte: fn.Some(closePending.FeeRate), + IsLocalCloseTx: fn.Some(local), } } - } // We'll consume each new incoming state to send out the appropriate diff --git a/rpcserver.go b/rpcserver.go index 525847f94..905ef9da1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2912,6 +2912,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, return err } } + out: for { select { @@ -2957,6 +2958,7 @@ out: h, _ := chainhash.NewHash(closeUpdate.ClosingTxid) rpcsLog.Infof("[closechannel] close completed: "+ "txid(%v)", h) + break out } @@ -3047,12 +3049,23 @@ func createRPCCloseUpdate( }, nil case *peer.PendingUpdate: + upd := &lnrpc.PendingUpdate{ + Txid: u.Txid, + OutputIndex: u.OutputIndex, + } + + // Potentially set the optional fields that are only set for + // the new RBF close flow. + u.IsLocalCloseTx.WhenSome(func(isLocal bool) { + upd.LocalCloseTx = isLocal + }) + u.FeePerVbyte.WhenSome(func(feeRate chainfee.SatPerVByte) { + upd.FeePerVbyte = int64(feeRate) + }) + return &lnrpc.CloseStatusUpdate{ Update: &lnrpc.CloseStatusUpdate_ClosePending{ - ClosePending: &lnrpc.PendingUpdate{ - Txid: u.Txid, - OutputIndex: u.OutputIndex, - }, + ClosePending: upd, }, }, nil }