Fetch HolderCommitmentPoint::current_point on read
What changed, and why it matters
This change fixes a channel-recovery edge case in the Lightning Dev Kit. When an older serialized channel state is loaded after an upgrade, the code now tries to re-derive a missing 'current commitment point' from the signer instead of leaving it blank. That lets splicing work immediately after restore; if the signer cannot provide the point, the code falls back to the old behavior rather than failing. It is a robustness improvement, not a clear exploitable vulnerability.
Treat as a normal bugfix/robustness patch. Reviewers should verify that holder_commitment_next_transaction_number + 1 is always the right index for the current point across all channel states, and that the .ok() fallback does not mask signer errors that should be surfaced elsewhere. No urgent security response is indicated by the diff alone.
Security signals we found
Missing commitment point could previously leave restored channels in a state where splicing was blocked
New code derives the point from the signer at the next transaction number, which is the correct derivation path
Failure is handled gracefully (.ok()), so a unavailable signer does not cause a panic or deserialization failure
Change is narrowly scoped to channel state restoration after an upgrade
Evidence from the diff
In channel.rs deserialization, HolderCommitmentPoint::current_point is now populated from holder_signer.get_per_commitment_point(holder_commitment_next_transaction_number + 1, &secp_ctx) when it was not serialized. The call is wrapped in .ok() so failure is non-fatal. The change removes a requirement that the HolderCommitmentPoint be advanced before splicing can be initiated on a restored channel. No cryptographic validation logic is bypassed; the fallback simply preserves prior behavior.
Changed components
lightning/src/ln/channel.rsHolderCommitmentPoint deserialization / channel restoration pathSplicing initiation logic for restored channelsInspect captured patch +20 / −4
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index a30b3d5..f3ffd1c 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -13837,11 +13837,26 @@ where
// If we're restoring this channel for the first time after an upgrade, then we require that the
// signer be available so that we can immediately populate the next commitment point. Channel
// restoration will fail if this is not possible.
- let holder_commitment_point =
+ let holder_commitment_point = {
+ let current_point = holder_commitment_point_current_opt.or_else(|| {
+ if holder_commitment_next_transaction_number == INITIAL_COMMITMENT_NUMBER {
+ None
+ } else {
+ // If the current point is not available then splicing can't be initiated
+ // until the next point is advanced and becomes the current point.
+ holder_signer
+ .get_per_commitment_point(
+ holder_commitment_next_transaction_number + 1,
+ &secp_ctx,
+ )
+ .ok()
+ }
+ });
+
match (holder_commitment_point_next_opt, holder_commitment_point_pending_next_opt) {
(Some(next_point), pending_next_point) => HolderCommitmentPoint {
next_transaction_number: holder_commitment_next_transaction_number,
- current_point: holder_commitment_point_current_opt,
+ current_point,
next_point,
pending_next_point,
},
@@ -13861,12 +13876,13 @@ where
);
HolderCommitmentPoint {
next_transaction_number: holder_commitment_next_transaction_number,
- current_point: holder_commitment_point_current_opt,
+ current_point,
next_point,
pending_next_point: Some(pending_next_point),
}
},
- };
+ }
+ };
Ok(FundedChannel {
funding: FundingScope {
Why this scored 30/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.