peer: fix MarkCoopBroadcasted to correctly use local parameter
What changed, and why it matters
A bug in LND's cooperative channel close tracking caused the software to always label the close transaction as 'locally initiated', even when the other peer initiated it. This is a bookkeeping error in how close events are recorded, not a direct theft-of-funds bug, but it could mislead downstream logic that relies on accurate close-initiator information.
Review consumers of MarkCoopBroadcasted and the persisted close-initiator metadata to determine whether the mislabeling could affect fee attribution, close reporting, or any automated follow-up behavior. Apply the patch and verify release notes are accurate.
Security signals we found
Incorrect use of API parameter leading to misattribution of on-chain channel close events
Persistent state written with wrong party identifier for cooperative close
Potential for downstream logic to act on incorrect close-initiator metadata
Evidence from the diff
peer/chan_observer.go’s MarkCoopBroadcasted wrapper ignored its local bool parameter and hardcoded lntypes.Local when calling l.chanView.MarkCoopBroadcasted. The fix maps local=true to lntypes.Local and local=false to lntypes.Remote. The release notes describe this as correcting the persistent marking of cooperative close transactions so remote-initiated closes are no longer mislabeled as local.
Changed components
peer/chan_observer.goMarkCoopBroadcasted methodcooperative close state trackingInspect captured patch +13 / −2
diff --git a/docs/release-notes/release-notes-0.21.0.md b/docs/release-notes/release-notes-0.21.0.md
index 13e0484..0787656 100644
--- a/docs/release-notes/release-notes-0.21.0.md
+++ b/docs/release-notes/release-notes-0.21.0.md
@@ -45,12 +45,18 @@
has been removed from the public key parsing methods, and proper mutex
protection has been added to the cache access in `DisconnectBlockAtHeight`.
-- [Fixed TLV decoders to reject malformed records with incorrect lengths](https://github.com/lightningnetwork/lnd/pull/10249).
+- [Fixed TLV decoders to reject malformed records with incorrect lengths](https://github.com/lightningnetwork/lnd/pull/10249).
TLV decoders now strictly enforce fixed-length requirements for Fee (8 bytes),
Musig2Nonce (66 bytes), ShortChannelID (8 bytes), Vertex (33 bytes), and
DBytes33 (33 bytes) records, preventing malformed TLV data from being
accepted.
+- [Fixed `MarkCoopBroadcasted` to correctly use the `local`
+ parameter](https://github.com/lightningnetwork/lnd/pull/10532). The method was
+ ignoring the `local` parameter and always marking cooperative close
+ transactions as locally initiated, even when they were initiated by the remote
+ peer.
+
# New Features
- Basic Support for [onion messaging forwarding](https://github.com/lightningnetwork/lnd/pull/9868)
diff --git a/peer/chan_observer.go b/peer/chan_observer.go
index 7570bcf..dcdc3c3 100644
--- a/peer/chan_observer.go
+++ b/peer/chan_observer.go
@@ -119,7 +119,12 @@ func (l *chanObserver) DisableOutgoingAdds() error {
// MarkCoopBroadcasted persistently marks that the channel close transaction
// has been broadcast.
func (l *chanObserver) MarkCoopBroadcasted(tx *wire.MsgTx, local bool) error {
- return l.chanView.MarkCoopBroadcasted(tx, lntypes.Local)
+ party := lntypes.Remote
+ if local {
+ party = lntypes.Local
+ }
+
+ return l.chanView.MarkCoopBroadcasted(tx, party)
}
// MarkShutdownSent persists the given ShutdownInfo. The existence of the
Why this scored 43/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.