From: Matt Corallo Date: Tue, 1 Feb 2022 17:23:52 +0000 (+0000) Subject: Add support for the SCIDAlias feature bit in incoming channels X-Git-Tag: v0.0.106~4^2~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=5d652bfec8944617070b828c8d29517908c7b033;p=rust-lightning Add support for the SCIDAlias feature bit in incoming channels This does not, however, ever send the scid_alias feature bit for outgoing channels, as that would cause the immediately prior version of LDK to be unable to read channel data. --- diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index e1f292b76..0bba70e5e 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -1009,6 +1009,7 @@ impl Channel { L::Target: Logger, { let opt_anchors = false; // TODO - should be based on features + let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false }; // First check the channel type is known, failing before we do anything else if we don't // support this channel type. @@ -1016,8 +1017,18 @@ impl Channel { if channel_type.supports_any_optional_bits() { return Err(ChannelError::Close("Channel Type field contained optional bits - this is not allowed".to_owned())); } - if *channel_type != ChannelTypeFeatures::only_static_remote_key() { - return Err(ChannelError::Close("Channel Type was not understood".to_owned())); + // We currently only allow two channel types, so write it all out here - we allow + // `only_static_remote_key` in all contexts, and further allow + // `static_remote_key|scid_privacy` if the channel is not publicly announced. + let mut allowed_type = ChannelTypeFeatures::only_static_remote_key(); + if *channel_type != allowed_type { + allowed_type.set_scid_privacy_required(); + if *channel_type != allowed_type { + return Err(ChannelError::Close("Channel Type was not understood".to_owned())); + } + if announced_channel { + return Err(ChannelError::Close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); + } } channel_type.clone() } else { @@ -1098,14 +1109,13 @@ impl Channel { // Convert things into internal flags and prep our state: - let announce = if (msg.channel_flags & 1) == 1 { true } else { false }; if config.peer_channel_config_limits.force_announced_channel_preference { - if local_config.announced_channel != announce { + if local_config.announced_channel != announced_channel { return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours".to_owned())); } } // we either accept their preference or the preferences match - local_config.announced_channel = announce; + local_config.announced_channel = announced_channel; let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis); if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 87f894190..f524cda84 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2420,7 +2420,13 @@ impl ChannelMana // Note that the behavior here should be identical to the above block - we // should NOT reveal the existence or non-existence of a private channel if // we don't allow forwards outbound over them. - break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None)); + break Some(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None)); + } + if chan.get_channel_type().supports_scid_privacy() && *short_channel_id != chan.outbound_scid_alias() { + // `option_scid_alias` (referred to in LDK as `scid_privacy`) means + // "refuse to forward unless the SCID alias was used", so we pretend + // we don't have the channel here. + break Some(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None)); } // Note that we could technically not return an error yet here and just hope diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 7d7553dfa..4512ee800 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -143,7 +143,7 @@ mod sealed { // Byte 4 , // Byte 5 - ChannelType, + ChannelType | SCIDPrivacy, ], }); define_context!(NodeContext { @@ -175,7 +175,7 @@ mod sealed { // Byte 4 , // Byte 5 - ChannelType, + ChannelType | SCIDPrivacy, // Byte 6 Keysend, ], @@ -214,6 +214,10 @@ mod sealed { , // Byte 3 , + // Byte 4 + , + // Byte 5 + SCIDPrivacy, ], optional_features: [ // Byte 0 @@ -224,6 +228,10 @@ mod sealed { , // Byte 3 , + // Byte 4 + , + // Byte 5 + , ], }); @@ -388,6 +396,10 @@ mod sealed { define_feature!(45, ChannelType, [InitContext, NodeContext], "Feature flags for `option_channel_type`.", set_channel_type_optional, set_channel_type_required, supports_channel_type, requires_channel_type); + define_feature!(47, SCIDPrivacy, [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for only forwarding with SCID aliasing. Called `option_scid_alias` in the BOLTs", + set_scid_privacy_optional, set_scid_privacy_required, supports_scid_privacy, requires_scid_privacy); + define_feature!(55, Keysend, [NodeContext], "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required, supports_keysend, requires_keysend); @@ -826,6 +838,11 @@ mod tests { assert!(InitFeatures::known().supports_shutdown_anysegwit()); assert!(NodeFeatures::known().supports_shutdown_anysegwit()); + assert!(InitFeatures::known().supports_scid_privacy()); + assert!(NodeFeatures::known().supports_scid_privacy()); + assert!(!InitFeatures::known().requires_scid_privacy()); + assert!(!NodeFeatures::known().requires_scid_privacy()); + let mut init_features = InitFeatures::known(); assert!(init_features.initial_routing_sync()); init_features.clear_initial_routing_sync(); @@ -864,14 +881,14 @@ mod tests { // - basic_mpp // - opt_shutdown_anysegwit // - - // - option_channel_type + // - option_channel_type | option_scid_alias assert_eq!(node_features.flags.len(), 6); assert_eq!(node_features.flags[0], 0b00000010); assert_eq!(node_features.flags[1], 0b01010001); assert_eq!(node_features.flags[2], 0b00000010); assert_eq!(node_features.flags[3], 0b00001000); assert_eq!(node_features.flags[4], 0b00000000); - assert_eq!(node_features.flags[5], 0b00100000); + assert_eq!(node_features.flags[5], 0b10100000); } // Check that cleared flags are kept blank when converting back: diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index ef2fc0fd9..8b5a04370 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -433,6 +433,12 @@ pub enum Event { /// The features that this channel will operate with. If you reject the channel, a /// well-behaved counterparty may automatically re-attempt the channel with a new set of /// feature flags. + /// + /// Note that if [`ChannelTypeFeatures::supports_scid_privacy`] returns true on this type, + /// the resulting [`ChannelManager`] will not be readable by versions of LDK prior to + /// 0.0.106. + /// + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager channel_type: ChannelTypeFeatures, }, }