From fe8b4c7836cd46558597fb2426a5ffaa6dde5223 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 11:54:22 -0400 Subject: [PATCH 1/8] Enable all feature sets to OR with another set of the same type --- lightning/src/ln/features.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 91922f1a45f..a680d0184e7 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -470,6 +470,17 @@ pub struct Features { mark: PhantomData, } +impl Features { + pub(crate) fn or(mut self, o: Self) -> Self { + let total_feature_len = cmp::max(self.flags.len(), o.flags.len()); + self.flags.resize(total_feature_len, 0u8); + for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) { + *byte |= *o_byte; + } + self + } +} + impl Clone for Features { fn clone(&self) -> Self { Self { @@ -532,16 +543,6 @@ impl InitFeatures { Ok(()) } - /// or's another InitFeatures into this one. - pub(crate) fn or(mut self, o: InitFeatures) -> InitFeatures { - let total_feature_len = cmp::max(self.flags.len(), o.flags.len()); - self.flags.resize(total_feature_len, 0u8); - for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) { - *byte |= *o_byte; - } - self - } - /// Converts `InitFeatures` to `Features`. Only known `InitFeatures` relevant to context `C` /// are included in the result. pub(crate) fn to_context(&self) -> Features { From c106d4ff9f60a9225f662ab68cb054f416ce8361 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 12:12:50 -0400 Subject: [PATCH 2/8] OR NodeFeatures from both Channel and Routing message handlers When we broadcast a node announcement, the features we support are really a combination of all the various features our different handlers support. This commit captures this concept by OR'ing our NodeFeatures across both our channel and routing message handlers. --- lightning-net-tokio/src/lib.rs | 1 + lightning/src/ln/msgs.rs | 4 ++++ lightning/src/ln/peer_handler.rs | 5 ++++- lightning/src/routing/gossip.rs | 6 ++++++ lightning/src/util/test_utils.rs | 6 ++++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index c50e3e69bd2..d5feb993652 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -582,6 +582,7 @@ mod tests { fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) } fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: QueryChannelRange) -> Result<(), LightningError> { Ok(()) } fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) } + fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::known() } fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::known() } } impl ChannelMessageHandler for MsgHandler { diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index e063c31464f..a6d096bffb9 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -958,6 +958,10 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider { fn handle_query_short_channel_ids(&self, their_node_id: &PublicKey, msg: QueryShortChannelIds) -> Result<(), LightningError>; // Handler information: + /// Gets the node feature flags which this handler itself supports. All available handlers are + /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`] + /// which are broadcasted in our [`NodeAnnouncement`] message. + fn provided_node_features(&self) -> NodeFeatures; /// Gets the init feature flags which should be sent to the given peer. All available handlers /// are queried similarly and their feature flags are OR'd together to form the [`InitFeatures`] /// which are sent in our [`Init`] message. diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 417b14d15b2..5e69389933e 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -77,6 +77,7 @@ impl RoutingMessageHandler for IgnoringMessageHandler { fn handle_reply_short_channel_ids_end(&self, _their_node_id: &PublicKey, _msg: msgs::ReplyShortChannelIdsEnd) -> Result<(), LightningError> { Ok(()) } fn handle_query_channel_range(&self, _their_node_id: &PublicKey, _msg: msgs::QueryChannelRange) -> Result<(), LightningError> { Ok(()) } fn handle_query_short_channel_ids(&self, _their_node_id: &PublicKey, _msg: msgs::QueryShortChannelIds) -> Result<(), LightningError> { Ok(()) } + fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { InitFeatures::empty() } @@ -1969,8 +1970,10 @@ impl NodeFeatures { + let mut features = NodeFeatures::empty(); + features.set_gossip_queries_optional(); + features + } + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { let mut features = InitFeatures::empty(); features.set_gossip_queries_optional(); diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 7c7aeb5d44f..abeb874b3d6 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -511,6 +511,12 @@ impl msgs::RoutingMessageHandler for TestRoutingMessageHandler { Ok(()) } + fn provided_node_features(&self) -> NodeFeatures { + let mut features = NodeFeatures::empty(); + features.set_gossip_queries_optional(); + features + } + fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures { let mut features = InitFeatures::empty(); features.set_gossip_queries_optional(); From 7eee7974b0cf207e8d867c7ffaa9771c1e9d5822 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 12:17:33 -0400 Subject: [PATCH 3/8] Add a new NodeFeatures constructor to capture the types of flags When ChannelMessageHandler implementations wish to return a NodeFeatures which contain all the known flags that are relevant to channel handling, but not gossip handling, they currently need to do so by manually constructing a NodeFeatures with all known flags and then clearing the ones they don't want. Instead of spreading this logic across the codebase, this consolidates such construction into one place in features.rs. --- lightning/src/ln/channelmanager.rs | 2 +- lightning/src/ln/features.rs | 10 +++++++++- lightning/src/util/test_utils.rs | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 7d09a5b81a8..7495af879c7 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -6122,7 +6122,7 @@ impl } fn provided_node_features(&self) -> NodeFeatures { - NodeFeatures::known() + NodeFeatures::known_channel_features() } fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures { diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index a680d0184e7..ceb78a4a0d2 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -164,7 +164,8 @@ mod sealed { ], optional_features: [ // Note that if new "non-channel-related" flags are added here they should be - // explicitly cleared in InitFeatures::known_channel_features. + // explicitly cleared in InitFeatures::known_channel_features and + // NodeFeatures::known_channel_features. // Byte 0 DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries, // Byte 1 @@ -558,6 +559,13 @@ impl InitFeatures { } } +impl NodeFeatures { + /// Returns the set of known node features that are related to channels. + pub fn known_channel_features() -> NodeFeatures { + Self::known().clear_gossip_queries() + } +} + impl InvoiceFeatures { /// Converts `InvoiceFeatures` to `Features`. Only known `InvoiceFeatures` relevant to /// context `C` are included in the result. diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index abeb874b3d6..b0f9ba0a98e 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -358,7 +358,7 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler { self.received_msg(wire::Message::Error(msg.clone())); } fn provided_node_features(&self) -> NodeFeatures { - NodeFeatures::empty() + NodeFeatures::known_channel_features() } fn provided_init_features(&self, _their_init_features: &PublicKey) -> InitFeatures { InitFeatures::known_channel_features() From f5e12559b5770eb7e54244cf520012b547065f86 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Sat, 6 Aug 2022 18:23:30 -0400 Subject: [PATCH 4/8] Add missing wumbo feature bit docs --- lightning/src/ln/features.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index ceb78a4a0d2..820e3165f72 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -39,6 +39,8 @@ //! (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md) for more information). //! - `BasicMPP` - requires/supports that a node can receive basic multi-part payments //! (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md#basic-multi-part-payments) for more information). +//! - `Wumbo` - requires/supports that a node create large channels. Called `option_support_large_channel` in the spec. +//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message) for more information). //! - `ShutdownAnySegwit` - requires/supports that future segwit versions are allowed in `shutdown` //! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information). //! - `ChannelType` - node supports the channel_type field in open/accept From 1ac3fccd980af35f38ef3b5a0f4a348ec21bd000 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 26 Aug 2022 19:40:10 -0400 Subject: [PATCH 5/8] Support forwarding onion messages in advertised features In upcoming commit(s), onion message support will be advertised conditionally based on the OnionMessageProvider provided to PeerManager. --- lightning/src/ln/features.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 820e3165f72..34dd2833721 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -43,6 +43,9 @@ //! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message) for more information). //! - `ShutdownAnySegwit` - requires/supports that future segwit versions are allowed in `shutdown` //! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information). +//! - `OnionMessages` - requires/supports forwarding onion messages +//! (see [BOLT-7](https://github.com/lightning/bolts/pull/759/files) for more information). +//! TODO: update link //! - `ChannelType` - node supports the channel_type field in open/accept //! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information). //! - `SCIDPrivacy` - supply channel aliases for routing @@ -177,7 +180,7 @@ mod sealed { // Byte 3 ShutdownAnySegwit, // Byte 4 - , + OnionMessages, // Byte 5 ChannelType | SCIDPrivacy, // Byte 6 @@ -211,7 +214,7 @@ mod sealed { // Byte 3 ShutdownAnySegwit, // Byte 4 - , + OnionMessages, // Byte 5 ChannelType | SCIDPrivacy, // Byte 6 @@ -438,8 +441,6 @@ mod sealed { define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext], "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional, set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit); - // We do not yet advertise the onion messages feature bit, but we need to detect when peers - // support it. define_feature!(39, OnionMessages, [InitContext, NodeContext], "Feature flags for `option_onion_messages`.", set_onion_messages_optional, set_onion_messages_required, supports_onion_messages, requires_onion_messages); @@ -924,6 +925,11 @@ mod tests { assert!(!InitFeatures::known().requires_wumbo()); assert!(!NodeFeatures::known().requires_wumbo()); + assert!(InitFeatures::known().supports_onion_messages()); + assert!(NodeFeatures::known().supports_onion_messages()); + assert!(!InitFeatures::known().requires_onion_messages()); + assert!(!NodeFeatures::known().requires_onion_messages()); + assert!(InitFeatures::known().supports_zero_conf()); assert!(!InitFeatures::known().requires_zero_conf()); assert!(NodeFeatures::known().supports_zero_conf()); @@ -968,7 +974,7 @@ mod tests { // - var_onion_optin (req) | static_remote_key (req) | payment_secret(req) // - basic_mpp | wumbo // - opt_shutdown_anysegwit - // - + // - onion_messages // - option_channel_type | option_scid_alias // - option_zeroconf assert_eq!(node_features.flags.len(), 7); @@ -976,7 +982,7 @@ mod tests { assert_eq!(node_features.flags[1], 0b01010001); assert_eq!(node_features.flags[2], 0b00001010); assert_eq!(node_features.flags[3], 0b00001000); - assert_eq!(node_features.flags[4], 0b00000000); + assert_eq!(node_features.flags[4], 0b10000000); assert_eq!(node_features.flags[5], 0b10100000); assert_eq!(node_features.flags[6], 0b00001000); } From 90f59060822fceea42841a8a03fed01f2c39eeaa Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 12:29:13 -0400 Subject: [PATCH 6/8] OR InitFeatures and NodeFeatures from onion message handler Similar to how we OR our InitFeaures and NodeFeatures across both our channel and routing message handlers, we also want to OR the features of our onion message handler. --- lightning/src/ln/msgs.rs | 13 +++++++++++++ lightning/src/ln/peer_handler.rs | 13 ++++++++++--- lightning/src/onion_message/messenger.rs | 13 +++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index a6d096bffb9..a43156965cc 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -980,6 +980,19 @@ pub trait OnionMessageHandler : OnionMessageProvider { /// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to /// drop and refuse to forward onion messages to this peer. fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool); + + // Handler information: + /// Gets the node feature flags which this handler itself supports. All available handlers are + /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`] + /// which are broadcasted in our [`NodeAnnouncement`] message. + fn provided_node_features(&self) -> NodeFeatures; + + /// Gets the init feature flags which should be sent to the given peer. All available handlers + /// are queried similarly and their feature flags are OR'd together to form the [`InitFeatures`] + /// which are sent in our [`Init`] message. + /// + /// Note that this method is called before [`Self::peer_connected`]. + fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures; } mod fuzzy_internal_msgs { diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 5e69389933e..838927cb236 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -89,6 +89,10 @@ impl OnionMessageHandler for IgnoringMessageHandler { fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {} fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) {} fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {} + fn provided_node_features(&self) -> NodeFeatures { NodeFeatures::empty() } + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { + InitFeatures::empty() + } } impl Deref for IgnoringMessageHandler { type Target = IgnoringMessageHandler; @@ -1062,7 +1066,8 @@ impl OnionMessageHandler for OnionMessenger NodeFeatures { + let mut features = NodeFeatures::empty(); + features.set_onion_messages_optional(); + features + } + + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { + let mut features = InitFeatures::empty(); + features.set_onion_messages_optional(); + features + } } impl OnionMessageProvider for OnionMessenger From 9c3b6d2edd1dc33ef53a8b79ed27db20fd89135e Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 12:41:23 -0400 Subject: [PATCH 7/8] Don't advertise onion messages in known channel features --- lightning/src/ln/features.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 34dd2833721..642298f56ed 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -559,13 +559,16 @@ impl InitFeatures { Self::known() .clear_initial_routing_sync() .clear_gossip_queries() + .clear_onion_messages() } } impl NodeFeatures { /// Returns the set of known node features that are related to channels. pub fn known_channel_features() -> NodeFeatures { - Self::known().clear_gossip_queries() + Self::known() + .clear_gossip_queries() + .clear_onion_messages() } } @@ -799,6 +802,13 @@ impl Features { } } +impl Features { + pub(crate) fn clear_onion_messages(mut self) -> Self { + ::clear_bits(&mut self.flags); + self + } +} + impl Features { #[cfg(test)] pub(crate) fn clear_shutdown_anysegwit(mut self) -> Self { From 5d9dddd1f6cdded2c8281f91c916ac1d3ce01f21 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 9 Sep 2022 16:01:41 -0400 Subject: [PATCH 8/8] Update ChannelMessageHandler::provided_node_features docs To be uniform with the other handler provided_node_features docs --- lightning/src/ln/msgs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index a43156965cc..747107c0822 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -900,7 +900,7 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { // Handler information: /// Gets the node feature flags which this handler itself supports. All available handlers are /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`] - /// which are broadcasted in our node_announcement message. + /// which are broadcasted in our [`NodeAnnouncement`] message. fn provided_node_features(&self) -> NodeFeatures; /// Gets the init feature flags which should be sent to the given peer. All available handlers