@@ -32,6 +32,8 @@ use ln::msgs::DecodeError;
3232use util:: ser:: { Readable , Writeable , Writer } ;
3333
3434mod sealed {
35+ use ln:: features:: Features ;
36+
3537 /// The context in which [`Features`] are applicable. Defines which features are required and
3638 /// which are optional for the context.
3739 ///
@@ -157,7 +159,8 @@ mod sealed {
157159 ///
158160 /// [`Context`]: trait.Context.html
159161 macro_rules! define_feature {
160- ( $odd_bit: expr, $feature: ident, [ $( $context: ty) ,+] , $doc: expr) => {
162+ ( $odd_bit: expr, $feature: ident, [ $( $context: ty) ,+] , $doc: expr, $optional_setter: ident,
163+ $required_setter: ident) => {
161164 #[ doc = $doc]
162165 ///
163166 /// See [BOLT #9] for details.
@@ -242,6 +245,20 @@ mod sealed {
242245 }
243246 }
244247
248+ impl <T : $feature> Features <T > {
249+ /// Set this feature as optional.
250+ pub fn $optional_setter( mut self ) -> Self {
251+ <T as $feature>:: set_optional_bit( & mut self . flags) ;
252+ self
253+ }
254+
255+ /// Set this feature as required.
256+ pub fn $required_setter( mut self ) -> Self {
257+ <T as $feature>:: set_required_bit( & mut self . flags) ;
258+ self
259+ }
260+ }
261+
245262 $(
246263 impl $feature for $context {
247264 // EVEN_BIT % 2 == 0
@@ -251,28 +268,34 @@ mod sealed {
251268 const ASSERT_ODD_BIT_PARITY : usize = ( <Self as $feature>:: ODD_BIT % 2 ) - 1 ;
252269 }
253270 ) *
271+
254272 }
255273 }
256274
257275 define_feature ! ( 1 , DataLossProtect , [ InitContext , NodeContext ] ,
258- "Feature flags for `option_data_loss_protect`." ) ;
276+ "Feature flags for `option_data_loss_protect`." , set_data_loss_protect_optional,
277+ set_data_loss_protect_required) ;
259278 // NOTE: Per Bolt #9, initial_routing_sync has no even bit.
260- define_feature ! ( 3 , InitialRoutingSync , [ InitContext ] ,
261- "Feature flags for `initial_routing_sync`." ) ;
279+ define_feature ! ( 3 , InitialRoutingSync , [ InitContext ] , "Feature flags for `initial_routing_sync`." ,
280+ set_initial_routing_sync_optional , set_initial_routing_sync_required ) ;
262281 define_feature ! ( 5 , UpfrontShutdownScript , [ InitContext , NodeContext ] ,
263- "Feature flags for `option_upfront_shutdown_script`." ) ;
282+ "Feature flags for `option_upfront_shutdown_script`." , set_upfront_shutdown_script_optional,
283+ set_upfront_shutdown_script_required) ;
264284 define_feature ! ( 7 , GossipQueries , [ InitContext , NodeContext ] ,
265- "Feature flags for `gossip_queries`." ) ;
285+ "Feature flags for `gossip_queries`." , set_gossip_queries_optional , set_gossip_queries_required ) ;
266286 define_feature ! ( 9 , VariableLengthOnion , [ InitContext , NodeContext , InvoiceContext ] ,
267- "Feature flags for `var_onion_optin`." ) ;
287+ "Feature flags for `var_onion_optin`." , set_variable_length_onion_optional,
288+ set_variable_length_onion_required) ;
268289 define_feature ! ( 13 , StaticRemoteKey , [ InitContext , NodeContext ] ,
269- "Feature flags for `option_static_remotekey`." ) ;
290+ "Feature flags for `option_static_remotekey`." , set_static_remote_key_optional,
291+ set_static_remote_key_required) ;
270292 define_feature ! ( 15 , PaymentSecret , [ InitContext , NodeContext , InvoiceContext ] ,
271- "Feature flags for `payment_secret`." ) ;
293+ "Feature flags for `payment_secret`." , set_payment_secret_optional , set_payment_secret_required ) ;
272294 define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext ] ,
273- "Feature flags for `basic_mpp`." ) ;
295+ "Feature flags for `basic_mpp`." , set_basic_mpp_optional , set_basic_mpp_required ) ;
274296 define_feature ! ( 27 , ShutdownAnySegwit , [ InitContext , NodeContext ] ,
275- "Feature flags for `opt_shutdown_anysegwit`." ) ;
297+ "Feature flags for `opt_shutdown_anysegwit`." , set_shutdown_any_segwit_optional,
298+ set_shutdown_any_segwit_required) ;
276299
277300 #[ cfg( test) ]
278301 define_context ! ( TestingContext {
@@ -296,7 +319,8 @@ mod sealed {
296319
297320 #[ cfg( test) ]
298321 define_feature ! ( 23 , UnknownFeature , [ TestingContext ] ,
299- "Feature flags for an unknown feature used in testing." ) ;
322+ "Feature flags for an unknown feature used in testing." , set_unknown_feature_optional,
323+ set_unknown_feature_required) ;
300324}
301325
302326/// Tracks the set of features which a node implements, templated by the context in which it
@@ -614,7 +638,7 @@ impl<T: sealed::Context> Readable for Features<T> {
614638
615639#[ cfg( test) ]
616640mod tests {
617- use super :: { ChannelFeatures , InitFeatures , NodeFeatures } ;
641+ use super :: { ChannelFeatures , InitFeatures , InvoiceFeatures , NodeFeatures } ;
618642
619643 #[ test]
620644 fn sanity_test_known_features ( ) {
@@ -718,4 +742,15 @@ mod tests {
718742 assert ! ( !features. supports_upfront_shutdown_script( ) ) ;
719743 assert ! ( !init_features. supports_gossip_queries( ) ) ;
720744 }
745+
746+ #[ test]
747+ fn set_feature_bits ( ) {
748+ let features = InvoiceFeatures :: empty ( )
749+ . set_basic_mpp_optional ( )
750+ . set_payment_secret_required ( ) ;
751+ assert ! ( features. supports_basic_mpp( ) ) ;
752+ assert ! ( !features. requires_basic_mpp( ) ) ;
753+ assert ! ( features. requires_payment_secret( ) ) ;
754+ assert ! ( features. supports_payment_secret( ) ) ;
755+ }
721756}
0 commit comments