X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffeatures.rs;h=91922f1a45f26748f9fdaf8c7ba009a068f6d6b9;hb=3a3c931c5a5bc49197c021aaf98bc98b76176de7;hp=07e1a3229443b312aceff86ae7cb270576257eba;hpb=aa5e5f967375eb31d8b0d0ed7f20ef31242693f7;p=rust-lightning diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 07e1a322..91922f1a 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -19,7 +19,36 @@ //! 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. //! -//! [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md +//! 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). +//! - `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 +//! (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 use {io, io_extras}; @@ -126,16 +155,30 @@ mod sealed { , // Byte 3 , + // Byte 4 + , + // Byte 5 + , + // Byte 6 + , ], optional_features: [ + // Note that if new "non-channel-related" flags are added here they should be + // explicitly cleared in InitFeatures::known_channel_features. // Byte 0 DataLossProtect | InitialRoutingSync | UpfrontShutdownScript | GossipQueries, // Byte 1 , // Byte 2 - BasicMPP, + BasicMPP | Wumbo, // Byte 3 ShutdownAnySegwit, + // Byte 4 + , + // Byte 5 + ChannelType | SCIDPrivacy, + // Byte 6 + ZeroConf, ], }); define_context!(NodeContext { @@ -161,15 +204,15 @@ mod sealed { // Byte 1 , // Byte 2 - BasicMPP, + BasicMPP | Wumbo, // Byte 3 ShutdownAnySegwit, // Byte 4 , // Byte 5 - , + ChannelType | SCIDPrivacy, // Byte 6 - Keysend, + ZeroConf | Keysend, ], }); define_context!(ChannelContext { @@ -206,6 +249,12 @@ mod sealed { , // Byte 3 , + // Byte 4 + , + // Byte 5 + SCIDPrivacy, + // Byte 6 + ZeroConf, ], optional_features: [ // Byte 0 @@ -216,6 +265,12 @@ mod sealed { , // Byte 3 , + // Byte 4 + , + // Byte 5 + , + // Byte 6 + , ], }); @@ -228,7 +283,7 @@ mod sealed { /// /// See [BOLT #9] for details. /// - /// [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md + /// [BOLT #9]: https://github.com/lightning/bolts/blob/master/09-features.md pub trait $feature: Context { /// The bit used to signify that the feature is required. const EVEN_BIT: usize = $odd_bit - 1; @@ -310,15 +365,13 @@ mod sealed { impl Features { /// Set this feature as optional. - pub fn $optional_setter(mut self) -> Self { + pub fn $optional_setter(&mut self) { ::set_optional_bit(&mut self.flags); - self } /// Set this feature as required. - pub fn $required_setter(mut self) -> Self { + pub fn $required_setter(&mut self) { ::set_required_bit(&mut self.flags); - self } /// Checks if this feature is supported. @@ -376,9 +429,26 @@ mod sealed { define_feature!(17, BasicMPP, [InitContext, NodeContext, InvoiceContext], "Feature flags for `basic_mpp`.", set_basic_mpp_optional, set_basic_mpp_required, supports_basic_mpp, requires_basic_mpp); + define_feature!(19, Wumbo, [InitContext, NodeContext], + "Feature flags for `option_support_large_channel` (aka wumbo channels).", set_wumbo_optional, set_wumbo_required, + supports_wumbo, requires_wumbo); 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); + 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!(51, ZeroConf, [InitContext, NodeContext, ChannelTypeContext], + "Feature flags for accepting channels with zero confirmations. Called `option_zeroconf` in the BOLTs", + set_zero_conf_optional, set_zero_conf_required, supports_zero_conf, requires_zero_conf); define_feature!(55, Keysend, [NodeContext], "Feature flags for keysend payments.", set_keysend_optional, set_keysend_required, supports_keysend, requires_keysend); @@ -477,6 +547,14 @@ impl InitFeatures { pub(crate) fn to_context(&self) -> Features { 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() + } } impl InvoiceFeatures { @@ -489,13 +567,15 @@ impl InvoiceFeatures { /// Getting a route for a keysend payment to a private node requires providing the payee's /// features (since they were not announced in a node announcement). However, keysend payments /// don't have an invoice to pull the payee's features from, so this method is provided for use in - /// [`Payee::for_keysend`], thus omitting the need for payers to manually construct an + /// [`PaymentParameters::for_keysend`], thus omitting the need for payers to manually construct an /// `InvoiceFeatures` for [`find_route`]. /// - /// [`Payee::for_keysend`]: crate::routing::router::Payee::for_keysend + /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend /// [`find_route`]: crate::routing::router::find_route pub(crate) fn for_keysend() -> InvoiceFeatures { - InvoiceFeatures::empty().set_variable_length_onion_optional() + let mut res = InvoiceFeatures::empty(); + res.set_variable_length_onion_optional(); + res } } @@ -693,7 +773,6 @@ impl Features { impl Features { - #[cfg(test)] pub(crate) fn clear_gossip_queries(mut self) -> Self { ::clear_bits(&mut self.flags); self @@ -701,12 +780,10 @@ impl Features { } impl Features { - // 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) { - ::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 { + ::clear_bits(&mut self.flags); + self } } @@ -717,6 +794,15 @@ impl Features { self } } + +impl Features { + #[cfg(test)] + pub(crate) fn clear_wumbo(mut self) -> Self { + ::clear_bits(&mut self.flags); + self + } +} + macro_rules! impl_feature_len_prefixed_write { ($features: ident) => { impl Writeable for $features { @@ -807,12 +893,36 @@ mod tests { assert!(!NodeFeatures::known().requires_basic_mpp()); assert!(!InvoiceFeatures::known().requires_basic_mpp()); + assert!(InitFeatures::known().supports_channel_type()); + assert!(NodeFeatures::known().supports_channel_type()); + assert!(!InitFeatures::known().requires_channel_type()); + assert!(!NodeFeatures::known().requires_channel_type()); + 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!(ChannelTypeFeatures::known().supports_scid_privacy()); + assert!(!InitFeatures::known().requires_scid_privacy()); + assert!(!NodeFeatures::known().requires_scid_privacy()); + assert!(ChannelTypeFeatures::known().requires_scid_privacy()); + + assert!(InitFeatures::known().supports_wumbo()); + assert!(NodeFeatures::known().supports_wumbo()); + assert!(!InitFeatures::known().requires_wumbo()); + assert!(!NodeFeatures::known().requires_wumbo()); + + assert!(InitFeatures::known().supports_zero_conf()); + assert!(!InitFeatures::known().requires_zero_conf()); + assert!(NodeFeatures::known().supports_zero_conf()); + assert!(!NodeFeatures::known().requires_zero_conf()); + assert!(ChannelTypeFeatures::known().supports_zero_conf()); + assert!(ChannelTypeFeatures::known().requires_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()); } @@ -822,11 +932,13 @@ mod tests { assert!(!features.requires_unknown_bits()); assert!(!features.supports_unknown_bits()); - let features = ChannelFeatures::empty().set_unknown_feature_required(); + let mut features = ChannelFeatures::empty(); + features.set_unknown_feature_required(); assert!(features.requires_unknown_bits()); assert!(features.supports_unknown_bits()); - let features = ChannelFeatures::empty().set_unknown_feature_optional(); + let mut features = ChannelFeatures::empty(); + features.set_unknown_feature_optional(); assert!(!features.requires_unknown_bits()); assert!(features.supports_unknown_bits()); } @@ -843,13 +955,19 @@ mod tests { // Check that the flags are as expected: // - option_data_loss_protect // - var_onion_optin (req) | static_remote_key (req) | payment_secret(req) - // - basic_mpp + // - basic_mpp | wumbo // - opt_shutdown_anysegwit - assert_eq!(node_features.flags.len(), 4); + // - + // - option_channel_type | option_scid_alias + // - option_zeroconf + assert_eq!(node_features.flags.len(), 7); 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[2], 0b00001010); assert_eq!(node_features.flags[3], 0b00001000); + assert_eq!(node_features.flags[4], 0b00000000); + assert_eq!(node_features.flags[5], 0b10100000); + assert_eq!(node_features.flags[6], 0b00001000); } // Check that cleared flags are kept blank when converting back: @@ -866,7 +984,8 @@ mod tests { fn convert_to_context_with_unknown_flags() { // Ensure the `from` context has fewer known feature bytes than the `to` context. assert!(InvoiceFeatures::known().flags.len() < NodeFeatures::known().flags.len()); - let invoice_features = InvoiceFeatures::known().set_unknown_feature_optional(); + let mut invoice_features = InvoiceFeatures::known(); + invoice_features.set_unknown_feature_optional(); assert!(invoice_features.supports_unknown_bits()); let node_features: NodeFeatures = invoice_features.to_context(); assert!(!node_features.supports_unknown_bits()); @@ -874,9 +993,9 @@ mod tests { #[test] fn set_feature_bits() { - let features = InvoiceFeatures::empty() - .set_basic_mpp_optional() - .set_payment_secret_required(); + let mut features = InvoiceFeatures::empty(); + features.set_basic_mpp_optional(); + features.set_payment_secret_required(); assert!(features.supports_basic_mpp()); assert!(!features.requires_basic_mpp()); assert!(features.requires_payment_secret()); @@ -918,7 +1037,8 @@ mod tests { fn test_channel_type_mapping() { // If we map an InvoiceFeatures with StaticRemoteKey optional, it should map into a // required-StaticRemoteKey ChannelTypeFeatures. - let init_features = InitFeatures::empty().set_static_remote_key_optional(); + let mut init_features = InitFeatures::empty(); + init_features.set_static_remote_key_optional(); let converted_features = ChannelTypeFeatures::from_counterparty_init(&init_features); assert_eq!(converted_features, ChannelTypeFeatures::only_static_remote_key()); assert!(!converted_features.supports_any_optional_bits());