X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffeatures.rs;h=259bda85eee7925f8f455058803fa850b3f29259;hb=871f4143672b9d8e616dbc2b6df87366590179d0;hp=488d6d70f5768ffde2d0af6afd80707a595625c9;hpb=c896461319b71ef3356ab72d9e886437d09cf79b;p=rust-lightning diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs index 488d6d70..259bda85 100644 --- a/lightning/src/ln/features.rs +++ b/lightning/src/ln/features.rs @@ -12,8 +12,7 @@ //! Lightning nodes advertise a supported set of operation through feature flags. Features are //! applicable for a specific context as indicated in some [messages]. [`Features`] encapsulates //! behavior for specifying and checking feature flags for a particular context. Each feature is -//! defined internally by a trait specifying the corresponding flags (i.e., even and odd bits). A -//! [`Context`] is used to parameterize [`Features`] and defines which features it can support. +//! defined internally by a trait specifying the corresponding flags (i.e., even and odd bits). //! //! Whether a feature is considered "known" or "unknown" is relative to the implementation, whereas //! the term "supports" is used in reference to a particular set of [`Features`]. That is, a node @@ -21,9 +20,7 @@ //! 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 -//! [messages]: ../msgs/index.html -//! [`Features`]: struct.Features.html -//! [`Context`]: sealed/trait.Context.html +//! [messages]: crate::ln::msgs use std::{cmp, fmt}; use std::marker::PhantomData; @@ -32,10 +29,10 @@ use ln::msgs::DecodeError; use util::ser::{Readable, Writeable, Writer}; mod sealed { + use ln::features::Features; + /// The context in which [`Features`] are applicable. Defines which features are required and /// which are optional for the context. - /// - /// [`Features`]: ../struct.Features.html pub trait Context { /// Features that are known to the implementation, where a required feature is indicated by /// its even bit and an optional feature is indicated by its odd bit. @@ -49,8 +46,6 @@ mod sealed { /// Defines a [`Context`] by stating which features it requires and which are optional. Features /// are specified as a comma-separated list of bytes where each byte is a pipe-delimited list of /// feature identifiers. - /// - /// [`Context`]: trait.Context.html macro_rules! define_context { ($context: ident { required_features: [$( $( $required_feature: ident )|*, )*], @@ -154,10 +149,9 @@ mod sealed { /// Defines a feature with the given bits for the specified [`Context`]s. The generated trait is /// useful for manipulating feature flags. - /// - /// [`Context`]: trait.Context.html macro_rules! define_feature { - ($odd_bit: expr, $feature: ident, [$($context: ty),+], $doc: expr) => { + ($odd_bit: expr, $feature: ident, [$($context: ty),+], $doc: expr, $optional_setter: ident, + $required_setter: ident) => { #[doc = $doc] /// /// See [BOLT #9] for details. @@ -242,6 +236,20 @@ mod sealed { } } + impl Features { + /// Set this feature as optional. + pub fn $optional_setter(mut self) -> Self { + ::set_optional_bit(&mut self.flags); + self + } + + /// Set this feature as required. + pub fn $required_setter(mut self) -> Self { + ::set_required_bit(&mut self.flags); + self + } + } + $( impl $feature for $context { // EVEN_BIT % 2 == 0 @@ -251,28 +259,34 @@ mod sealed { const ASSERT_ODD_BIT_PARITY: usize = (::ODD_BIT % 2) - 1; } )* + } } define_feature!(1, DataLossProtect, [InitContext, NodeContext], - "Feature flags for `option_data_loss_protect`."); + "Feature flags for `option_data_loss_protect`.", set_data_loss_protect_optional, + set_data_loss_protect_required); // NOTE: Per Bolt #9, initial_routing_sync has no even bit. - define_feature!(3, InitialRoutingSync, [InitContext], - "Feature flags for `initial_routing_sync`."); + define_feature!(3, InitialRoutingSync, [InitContext], "Feature flags for `initial_routing_sync`.", + set_initial_routing_sync_optional, set_initial_routing_sync_required); define_feature!(5, UpfrontShutdownScript, [InitContext, NodeContext], - "Feature flags for `option_upfront_shutdown_script`."); + "Feature flags for `option_upfront_shutdown_script`.", set_upfront_shutdown_script_optional, + set_upfront_shutdown_script_required); define_feature!(7, GossipQueries, [InitContext, NodeContext], - "Feature flags for `gossip_queries`."); + "Feature flags for `gossip_queries`.", set_gossip_queries_optional, set_gossip_queries_required); define_feature!(9, VariableLengthOnion, [InitContext, NodeContext, InvoiceContext], - "Feature flags for `var_onion_optin`."); + "Feature flags for `var_onion_optin`.", set_variable_length_onion_optional, + set_variable_length_onion_required); define_feature!(13, StaticRemoteKey, [InitContext, NodeContext], - "Feature flags for `option_static_remotekey`."); + "Feature flags for `option_static_remotekey`.", set_static_remote_key_optional, + set_static_remote_key_required); define_feature!(15, PaymentSecret, [InitContext, NodeContext, InvoiceContext], - "Feature flags for `payment_secret`."); + "Feature flags for `payment_secret`.", set_payment_secret_optional, set_payment_secret_required); define_feature!(17, BasicMPP, [InitContext, NodeContext, InvoiceContext], - "Feature flags for `basic_mpp`."); + "Feature flags for `basic_mpp`.", set_basic_mpp_optional, set_basic_mpp_required); define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext], - "Feature flags for `opt_shutdown_anysegwit`."); + "Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional, + set_shutdown_any_segwit_required); #[cfg(test)] define_context!(TestingContext { @@ -296,7 +310,8 @@ mod sealed { #[cfg(test)] define_feature!(23, UnknownFeature, [TestingContext], - "Feature flags for an unknown feature used in testing."); + "Feature flags for an unknown feature used in testing.", set_unknown_feature_optional, + set_unknown_feature_required); } /// Tracks the set of features which a node implements, templated by the context in which it @@ -389,9 +404,7 @@ impl Features { } } - /// Creates features known by the implementation as defined by [`T::KNOWN_FEATURE_FLAGS`]. - /// - /// [`T::KNOWN_FEATURE_FLAGS`]: sealed/trait.Context.html#associatedconstant.KNOWN_FEATURE_FLAGS + /// Creates a Features with the bits set which are known by the implementation pub fn known() -> Self { Self { flags: T::KNOWN_FEATURE_FLAGS.to_vec(), @@ -614,7 +627,7 @@ impl Readable for Features { #[cfg(test)] mod tests { - use super::{ChannelFeatures, InitFeatures, NodeFeatures}; + use super::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures}; #[test] fn sanity_test_known_features() { @@ -718,4 +731,15 @@ mod tests { assert!(!features.supports_upfront_shutdown_script()); assert!(!init_features.supports_gossip_queries()); } + + #[test] + fn set_feature_bits() { + let features = InvoiceFeatures::empty() + .set_basic_mpp_optional() + .set_payment_secret_required(); + assert!(features.supports_basic_mpp()); + assert!(!features.requires_basic_mpp()); + assert!(features.requires_payment_secret()); + assert!(features.supports_payment_secret()); + } }