openingd: remove compat hacks to "intuit" opt_scid_alias.
What changed, and why it matters
This commit removes old compatibility workarounds in Core Lightning's channel-opening code. Previously, the software had to guess whether a peer wanted a private channel alias feature because older versions mishandled it. Now that all supported versions handle the feature correctly, the code simply sets it directly. This is a cleanup change, not a fix for an active security flaw, but removing compatibility shims can reduce hidden bug surface.
Treat as routine maintenance with minor security hygiene benefit. Verify that supported node versions are 23.08 or newer before deploying, since the removed shim was specifically for older peers. No urgent patching required absent additional vulnerability reports.
Security signals we found
Removal of backwards-compatibility shim for peer protocol feature negotiation
Channel type negotiation now requires exact feature-bit match instead of tolerated divergence
Eliminates silent mutation of `state->channel_type` based on peer version heuristics
No explicit vulnerability, CVE, or security advisory referenced in commit
Evidence from the diff
The patch deletes the intuit_scid_alias_type() helper and the fallback logic in funder_channel_start() and fundee_channel() that silently added OPT_SCID_ALIAS to the channel type when negotiating with older peers. It replaces the conditional acceptance logic with a straightforward check that the peer’s returned channel_type exactly matches what was offered. The change is framed as removing backwards-compatibility allowances for CLN versions before 23.08.
Changed components
openingd/openingd.cChannel opening negotiation (funder and fundee paths)OPT_SCID_ALIAS / option_scid_alias handlingInspect captured patch +6 / −60
diff --git a/openingd/openingd.c b/openingd/openingd.c
index 60faefde..e98609d0 100644
--- a/openingd/openingd.c
+++ b/openingd/openingd.c
@@ -268,28 +268,6 @@ static void set_remote_upfront_shutdown(struct state *state,
peer_failed_err(state->pps, &state->channel_id, "%s", err);
}
-/* Since we can't send OPT_SCID_ALIAS due to compat issues, intuit whether
- * we really actually want it anyway, we just can't say that. */
-static bool intuit_scid_alias_type(struct state *state, u8 channel_flags)
-{
- /* Don't need to intuit if actually set */
- if (channel_type_has(state->channel_type, OPT_SCID_ALIAS))
- return false;
-
- /* Modern peer: no intuit hacks necessary. */
- if (channel_type_has(state->channel_type, OPT_ANCHORS_ZERO_FEE_HTLC_TX))
- return false;
-
- /* Public channel: don't want OPT_SCID_ALIAS which means "only use
- * alias". */
- if (channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)
- return false;
-
- /* If we both support it, presumably we want it? */
- return feature_negotiated(state->our_features, state->their_features,
- OPT_SCID_ALIAS);
-}
-
/* We start the 'open a channel' negotation with the supplied peer, but
* stop when we get to the part where we need the funding txid */
static u8 *funder_channel_start(struct state *state, u8 channel_flags,
@@ -431,34 +409,12 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags,
}
/* Simple case: caller specified, don't allow any variants */
- if (ctype) {
- if (!featurebits_eq(accept_tlvs->channel_type, state->channel_type->features)) {
- negotiation_failed(state,
- "Return unoffered channel_type: %s",
- fmt_featurebits(tmpctx,
- accept_tlvs->channel_type));
- return NULL;
- }
- } else {
- /* Except that v23.05 could set OPT_SCID_ALIAS in reply! */
- struct channel_type *atype;
-
- atype = channel_type_from(tmpctx, accept_tlvs->channel_type);
- if (!channel_type_has(atype, OPT_ANCHORS_ZERO_FEE_HTLC_TX))
- featurebits_unset(&atype->features, OPT_SCID_ALIAS);
-
- if (!channel_type_eq(atype, state->channel_type)) {
- negotiation_failed(state,
- "Return unoffered channel_type: %s",
- fmt_featurebits(tmpctx,
- accept_tlvs->channel_type));
- return NULL;
- }
-
- /* If they "accepted" SCID_ALIAS, roll with it. */
- tal_free(state->channel_type);
- state->channel_type = channel_type_from(state,
- accept_tlvs->channel_type);
+ if (!featurebits_eq(accept_tlvs->channel_type, state->channel_type->features)) {
+ negotiation_failed(state,
+ "Return unoffered channel_type: %s",
+ fmt_featurebits(tmpctx,
+ accept_tlvs->channel_type));
+ return NULL;
}
/* BOLT #2:
@@ -564,11 +520,6 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags,
"Funding channel start: awaiting funding_txid with output to %s",
tal_hex(tmpctx, funding_output_script));
- /* Backwards/cross compat hack */
- if (!ctype && intuit_scid_alias_type(state, channel_flags)) {
- channel_type_set_scid_alias(state->channel_type);
- }
-
return towire_openingd_funder_start_reply(state,
funding_output_script,
feature_negotiated(
@@ -1163,11 +1114,6 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
&state->channel_id),
fmt_channel_id(msg, &id_in));
- /* Backwards/cross compat hack */
- if (intuit_scid_alias_type(state, channel_flags)) {
- channel_type_set_scid_alias(state->channel_type);
- }
-
/*~ Channel is ready; Report the channel parameters to the signer. */
msg = towire_hsmd_setup_channel(NULL,
false, /* is_outbound */
Why this scored 21/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.