diff --git a/docs/release-notes/release-notes-0.17.0.md b/docs/release-notes/release-notes-0.17.0.md index 883c46376..433901be5 100644 --- a/docs/release-notes/release-notes-0.17.0.md +++ b/docs/release-notes/release-notes-0.17.0.md @@ -141,6 +141,9 @@ It is possible to distinguish between defaults and examples now. A check script has been developed and integrated into the building process to compare the default values between lnd and sample-lnd.conf. +* [Cancel rebroadcasting of a transaction when abandoning +a channel](https://github.com/lightningnetwork/lnd/pull/7819) + ## Code Health * Updated [our fork for serializing protobuf as JSON to be based on the diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 200939da3..31954bfbf 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -2315,6 +2315,15 @@ func (l *LightningWallet) ValidateChannel(channelState *channeldb.OpenChannel, return nil } +// CancelRebroadcast cancels the rebroadcast of the given transaction. +func (l *LightningWallet) CancelRebroadcast(txid chainhash.Hash) { + // For neutrino, we don't config the rebroadcaster for the wallet as it + // manages the rebroadcasting logic in neutrino itself. + if l.Cfg.Rebroadcaster != nil { + l.Cfg.Rebroadcaster.MarkAsConfirmed(txid) + } +} + // CoinSource is a wrapper around the wallet that implements the // chanfunding.CoinSource interface. type CoinSource struct { diff --git a/rpcserver.go b/rpcserver.go index 2a1bacfeb..70f8fa49f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2740,12 +2740,21 @@ func abandonChanFromGraph(chanGraph *channeldb.ChannelGraph, func (r *rpcServer) abandonChan(chanPoint *wire.OutPoint, bestHeight uint32) error { + // Before we remove the channel we cancel the rebroadcasting of the + // transaction. If this transaction does not exist in the rebroadcast + // queue anymore it is a noop. + txid, err := chainhash.NewHash(chanPoint.Hash[:]) + if err != nil { + return err + } + r.server.cc.Wallet.CancelRebroadcast(*txid) + // Abandoning a channel is a three-step process: remove from the open // channel state, remove from the graph, remove from the contract // court. Between any step it's possible that the users restarts the // process all over again. As a result, each of the steps below are // intended to be idempotent. - err := r.server.chanStateDB.AbandonChannel(chanPoint, bestHeight) + err = r.server.chanStateDB.AbandonChannel(chanPoint, bestHeight) if err != nil { return err }