//! supports a feature if it advertises the feature (as either required or optional) to its peers.
//! And the implementation can interpret a feature if the feature is known to it.
//!
+//! The following features are currently required in the LDK:
+//! - `VariableLengthOnion` - requires/supports variable-length routing onion payloads
+//! (see [BOLT-4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md) for more information).
+//! - `StaticRemoteKey` - requires/supports static key for remote output
+//! (see [BOLT-3](https://github.com/lightning/bolts/blob/master/03-transactions.md) for more information).
+//!
+//! The following features are currently supported in the LDK:
+//! - `DataLossProtect` - requires/supports that a node which has somehow fallen behind, e.g., has been restored from an old backup,
+//! can detect that it has fallen behind
+//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
+//! - `InitialRoutingSync` - requires/supports that the sending node needs a complete routing information dump
+//! (see [BOLT-7](https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#initial-sync) for more information).
+//! - `UpfrontShutdownScript` - commits to a shutdown scriptpubkey when opening a channel
+//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#the-open_channel-message) for more information).
+//! - `GossipQueries` - requires/supports more sophisticated gossip control
+//! (see [BOLT-7](https://github.com/lightning/bolts/blob/master/07-routing-gossip.md) for more information).
+//! - `PaymentSecret` - requires/supports that a node supports payment_secret field
+//! (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).
+//! - `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
+//! (see [BOLT-2](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md) for more information).
+//! - `Keysend` - send funds to a node without an invoice
+//! (see the [`Keysend` feature assignment proposal](https://github.com/lightning/bolts/issues/605#issuecomment-606679798) for more information).
+//!
//! [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md
//! [messages]: crate::ln::msgs
,
],
optional_features: [
+ // Note that if new "non-channel-related" flags are added here they should be
+ // explicitly cleared in InitFeatures::known_channel_features and
+ // NodeFeatures::known_channel_features.
// Byte 0
DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries,
// Byte 1
// Byte 3
ShutdownAnySegwit,
// Byte 4
- ,
+ OnionMessages,
// Byte 5
ChannelType | SCIDPrivacy,
// Byte 6
// Byte 3
ShutdownAnySegwit,
// Byte 4
- ,
+ OnionMessages,
// Byte 5
ChannelType | SCIDPrivacy,
// Byte 6
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);
+ 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);
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);
mark: PhantomData<T>,
}
+impl <T: sealed::Context> Features<T> {
+ 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<T: sealed::Context> Clone for Features<T> {
fn clone(&self) -> Self {
Self {
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<C>`. Only known `InitFeatures` relevant to context `C`
/// are included in the result.
pub(crate) fn to_context<C: sealed::Context>(&self) -> Features<C> {
self.to_context_internal()
}
+
+ /// Returns the set of known init features that are related to channels. At least some of
+ /// these features are likely required for peers to talk to us.
+ pub fn known_channel_features() -> 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()
+ .clear_onion_messages()
+ }
}
impl InvoiceFeatures {
impl<T: sealed::GossipQueries> Features<T> {
- #[cfg(test)]
pub(crate) fn clear_gossip_queries(mut self) -> Self {
<T as sealed::GossipQueries>::clear_bits(&mut self.flags);
self
}
impl<T: sealed::InitialRoutingSync> Features<T> {
- // We are no longer setting initial_routing_sync now that gossip_queries
- // is enabled. This feature is ignored by a peer when gossip_queries has
- // been negotiated.
- #[cfg(test)]
- pub(crate) fn clear_initial_routing_sync(&mut self) {
- <T as sealed::InitialRoutingSync>::clear_bits(&mut self.flags)
+ // Note that initial_routing_sync is ignored if gossip_queries is set.
+ pub(crate) fn clear_initial_routing_sync(mut self) -> Self {
+ <T as sealed::InitialRoutingSync>::clear_bits(&mut self.flags);
+ self
+ }
+}
+
+impl<T: sealed::OnionMessages> Features<T> {
+ pub(crate) fn clear_onion_messages(mut self) -> Self {
+ <T as sealed::OnionMessages>::clear_bits(&mut self.flags);
+ self
}
}
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());
let mut init_features = InitFeatures::known();
assert!(init_features.initial_routing_sync());
- init_features.clear_initial_routing_sync();
+ init_features = init_features.clear_initial_routing_sync();
assert!(!init_features.initial_routing_sync());
}
// - 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);
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);
}