Make splice-funding confirmation assertions non-debug
What changed, and why it matters
This commit changes four internal consistency checks in the code that manages Lightning channel funding transactions. Previously these checks only fired during debug/test builds; now they are hard assertions that will crash the node in release builds if violated. The change reflects a belief that these particular inconsistent states could lead to losing money, so it is safer to halt than to continue.
Treat as a defensive hardening change rather than an active vulnerability with a known exploit. Review whether any reachable code path can trigger these assertions in production, and ensure monitoring/alerting captures node panics from channelmonitor. If a reproducible trigger is found, escalate as a potential consensus/state-machine bug.
Security signals we found
Hard assertion introduced for state that could cause loss of funds
Splice-funding confirmation invariants changed from debug-only to release-crashing
Commit message explicitly frames change as money-loss prevention
Evidence from the diff
In lightning/src/chain/channelmonitor.rs, four debug_assert! calls related to splice-funding confirmation state are replaced with assert!. The conditions assert that: (1) no alternative funding is already confirmed when a new splice funding is found, (2) no AlternativeFundingConfirmation event is already awaiting threshold confirmation, (3) no funding spend is already confirmed, and (4) no FundingSpendConfirmation event is already awaiting threshold confirmation. Violating any of these previously logged only in debug builds; now it panics in all builds.
Changed components
lightning/src/chain/channelmonitor.rsChannelMonitorImpl splice-funding confirmation handlingInspect captured patch +4 / −4
diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs
index 92d39f0..ff7cbf3 100644
--- a/lightning/src/chain/channelmonitor.rs
+++ b/lightning/src/chain/channelmonitor.rs
@@ -4949,13 +4949,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
.iter()
.find(|funding| funding.funding_txid() == txid)
{
- debug_assert!(self.alternative_funding_confirmed.is_none());
- debug_assert!(
+ assert!(self.alternative_funding_confirmed.is_none());
+ assert!(
!self.onchain_events_awaiting_threshold_conf.iter()
.any(|e| matches!(e.event, OnchainEvent::AlternativeFundingConfirmation {}))
);
- debug_assert!(self.funding_spend_confirmed.is_none());
- debug_assert!(
+ assert!(self.funding_spend_confirmed.is_none());
+ assert!(
!self.onchain_events_awaiting_threshold_conf.iter()
.any(|e| matches!(e.event, OnchainEvent::FundingSpendConfirmation { .. }))
);
Why this scored 53/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.