splice: Even if the psbt’s “match” the sig data may vary
What changed, and why it matters
This change fixes a bug in Core Lightning's channel-splicing code. During a splice, two versions of a Bitcoin transaction structure (a PSBT) might look identical in their main transaction data but differ in their attached signatures. Previously, the code would skip copying the new PSBT if the main transaction hadn't changed, which could discard signatures from a related splice. The fix always copies the latest PSBT so signatures are preserved. The commit describes this as a bug that could affect 'cross splice' scenarios, but it does not label it as a security vulnerability.
Treat as a correctness fix with potential security implications for splicing operations. Review whether dropped signatures in cross-splice paths could lead to stuck channels, invalid transactions, or opportunities for protocol manipulation. Apply the patch and consider adding a regression test for signature-preservation when interactivetx_has_changes returns false.
Security signals we found
Loss of signature data in a multi-party transaction protocol
Cross-splice interaction where signatures from another splice could be silently dropped
Fix is defensive: equality check ignored part of the data structure (PSBT signatures)
No explicit security framing by the vendor; described as a correctness bug
Evidence from the diff
In channeld/channeld.c, splice_initiator_user_update() previously called splice_initiator_user_finalized() without updating peer->splicing->current_psbt when interactivetx_has_changes() returned false. Because PSBT equality in that helper does not compare signature data, a desired_psbt with new signatures could be treated as unchanged and its signatures lost. The patch unconditionally frees and clones current_psbt from desired_psbt before finalizing, ensuring signature data is propagated. The commit message says this ‘never occurred during normal operation’ but could happen in ‘cross splice’ cases, causing vital signatures to be dropped.
Changed components
channeld/channeld.cSplicing protocol implementationPSBT handling in interactive transaction constructionInspect captured patch +3 / −0
diff --git a/channeld/channeld.c b/channeld/channeld.c
index 69b322f..ea28dbc 100644
--- a/channeld/channeld.c
+++ b/channeld/channeld.c
@@ -4521,6 +4521,9 @@ static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg)
/* If there no are no changes, we consider the splice user finalized */
if (!interactivetx_has_changes(ictx, ictx->desired_psbt)) {
+ peer->splicing->current_psbt = tal_free(peer->splicing->current_psbt);
+ peer->splicing->current_psbt = clone_psbt(peer->splicing,
+ ictx->desired_psbt);
splice_initiator_user_finalized(peer);
tal_steal(last_inflight(peer), last_inflight(peer)->psbt);
return;
Why this scored 52/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.