@@ -13711,8 +13711,10 @@ where
1371113711 provided_node_features(&self.config.read().unwrap())
1371213712 }
1371313713
13714- fn provided_init_features(&self, _their_init_features: PublicKey) -> InitFeatures {
13715- provided_init_features(&self.config.read().unwrap())
13714+ fn provided_init_features(&self, their_node_id: PublicKey) -> InitFeatures {
13715+ let mut features = provided_init_features(&self.config.read().unwrap());
13716+ strip_acinq_splice_prototype(&mut features, &their_node_id);
13717+ features
1371613718 }
1371713719
1371813720 #[rustfmt::skip]
@@ -15667,6 +15669,11 @@ where
1566715669
1566815670/// Fetches the set of [`NodeFeatures`] flags that are provided by or required by
1566915671/// [`ChannelManager`].
15672+ ///
15673+ /// Note: the ACINQ splice-prototype carve-out applied in
15674+ /// [`BaseMessageHandler::provided_init_features`] is intentionally *not*
15675+ /// applied here. The issue with dual-advertise is in `Init`, not in
15676+ /// gossip `node_announcement`s, and gossip is broadcast not per-peer.
1567015677pub(crate) fn provided_node_features(config: &UserConfig) -> NodeFeatures {
1567115678 let mut node_features = provided_init_features(config).to_context();
1567215679 node_features.set_keysend_optional();
@@ -15701,6 +15708,25 @@ pub(crate) fn provided_channel_type_features(config: &UserConfig) -> ChannelType
1570115708 ChannelTypeFeatures::from_init(&provided_init_features(config))
1570215709}
1570315710
15711+ /// ACINQ mainnet node id. Eclair (ACINQ's stack) chokes on dual-advertise of
15712+ /// the splice prototype (bit 155) and production (bit 63) feature bits, so we
15713+ /// strip the prototype bit when peering with this specific node. ACINQ has
15714+ /// already moved to bit 63 so they will accept splice via the production bit.
15715+ /// See MDK-799.
15716+ const ACINQ_MAINNET_NODE_ID: [u8; 33] = [
15717+ 0x03, 0x86, 0x4e, 0xf0, 0x25, 0xfd, 0xe8, 0xfb, 0x58, 0x7d, 0x98, 0x91, 0x86, 0xce, 0x6a, 0x4a,
15718+ 0x18, 0x68, 0x95, 0xee, 0x44, 0xa9, 0x26, 0xbf, 0xc3, 0x70, 0xe2, 0xc3, 0x66, 0x59, 0x7a, 0x3f,
15719+ 0x8f,
15720+ ];
15721+
15722+ /// If `their_node_id` is the ACINQ mainnet node, clear the splice prototype
15723+ /// (bit 155) feature. See [`ACINQ_MAINNET_NODE_ID`] for context.
15724+ fn strip_acinq_splice_prototype(features: &mut InitFeatures, their_node_id: &PublicKey) {
15725+ if their_node_id.serialize() == ACINQ_MAINNET_NODE_ID {
15726+ features.clear_splicing();
15727+ }
15728+ }
15729+
1570415730/// Fetches the set of [`InitFeatures`] flags that are provided by or required by
1570515731/// [`ChannelManager`].
1570615732pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
@@ -15725,6 +15751,9 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
1572515751 features.set_simple_close_optional();
1572615752 features.set_quiescence_optional();
1572715753 features.set_splicing_optional();
15754+ // Dual-advertise alongside the prototype bit during the LDK 0.2.2 migration.
15755+ // Stripped per-peer for ACINQ in the BaseMessageHandler impl above. See MDK-799.
15756+ features.set_splicing_production_optional();
1572815757
1572915758 if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx {
1573015759 features.set_anchors_zero_fee_htlc_tx_optional();
0 commit comments