Remove stale TODO for quiescence check on incoming splice_init
What changed, and why it matters
This commit moves a safety check so that incoming splice requests from a peer are verified for 'quiescence' earlier in the validation process. Quiescence means the channel is in a quiet, stable state before starting a splice. Previously, the check was performed later in an internal code path, leaving a TODO note suggesting it should also be enforced on incoming splice_init messages. The change removes that TODO and adds the check inside the validation function used for incoming splice requests. This is a defensive hardening fix: without it, a peer might be able to initiate a splice while the channel is not quiescent, potentially causing protocol confusion or errors.
Treat as a low-to-moderate hardening fix. Review whether any other splice-related messages (e.g., splice_ack, splice_locked) have similar missing quiescence checks, and ensure tests cover peer-initiated splice while the channel is not quiescent.
Security signals we found
Missing precondition check on peer-controlled message path
Protocol-state validation hardening for Lightning splicing
Removal of TODO indicating an unimplemented safety check
Peer-triggered WarnAndDisconnect on invalid state
Evidence from the diff
In lightning/src/ln/channel.rs, validate_splice_init() now calls self.context.channel_state.is_quiescent() and returns ChannelError::WarnAndDisconnect if the channel is not quiescent. The same check is removed from the downstream on_splice_init() wrapper. Previously validate_splice_init() only had a TODO(splicing): Add check that we are the quiescence acceptor. The change enforces the quiescence precondition consistently for both locally-originated and peer-originated splice_init messages, because validate_splice_init() is the shared validation path. This prevents a peer from driving a splice before the channel has reached quiescence.
Changed components
lightning/src/ln/channel.rsSpliceInit message handlingChannel quiescence state validationInspect captured patch +4 / −6
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index c14a571..9747be7 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -11537,8 +11537,6 @@ where
pub fn validate_splice_init(
&self, msg: &msgs::SpliceInit, our_funding_contribution: SignedAmount,
) -> Result<FundingScope, ChannelError> {
- // TODO(splicing): Add check that we are the quiescence acceptor
-
if self.holder_commitment_point.current_point().is_none() {
return Err(ChannelError::WarnAndDisconnect(format!(
"Channel {} commitment point needs to be advanced once before spliced",
@@ -11546,6 +11544,10 @@ where
)));
}
+ if !self.context.channel_state.is_quiescent() {
+ return Err(ChannelError::WarnAndDisconnect("Quiescence needed to splice".to_owned()));
+ }
+
// Check if a splice has been initiated already.
if self.pending_splice.is_some() {
return Err(ChannelError::WarnAndDisconnect(format!(
@@ -11686,10 +11688,6 @@ where
ES::Target: EntropySource,
L::Target: Logger,
{
- if !self.context.channel_state.is_quiescent() {
- return Err(ChannelError::WarnAndDisconnect("Quiescence needed to splice".to_owned()));
- }
-
let our_funding_contribution = SignedAmount::from_sat(our_funding_contribution_satoshis);
let splice_funding = self.validate_splice_init(msg, our_funding_contribution)?;
Why this scored 42/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.