@@ -282,6 +282,12 @@ impl InitFeatures {
282
282
}
283
283
self
284
284
}
285
+
286
+ /// Converts `InitFeatures` to `Features<C>`. Only known `InitFeatures` relevant to context `C`
287
+ /// are included in the result.
288
+ pub ( crate ) fn to_context < C : sealed:: Context > ( & self ) -> Features < C > {
289
+ self . to_context_internal ( )
290
+ }
285
291
}
286
292
287
293
impl < T : sealed:: Context > Features < T > {
@@ -303,18 +309,19 @@ impl<T: sealed::Context> Features<T> {
303
309
}
304
310
}
305
311
306
- /// Takes the flags that we know how to interpret in an init-context features that are also
307
- /// relevant in a node-context features and creates a node-context features from them.
308
- /// Be sure to blank out features that are unknown to us.
309
- pub ( crate ) fn with_known_relevant_init_flags ( init_ctx : & InitFeatures ) -> Self {
310
- let byte_count = T :: KNOWN_FEATURE_MASK . len ( ) ;
312
+ /// Converts `Features<T>` to `Features<C>`. Only known `T` features relevant to context `C` are
313
+ /// included in the result.
314
+ fn to_context_internal < C : sealed:: Context > ( & self ) -> Features < C > {
315
+ let byte_count = C :: KNOWN_FEATURE_MASK . len ( ) ;
311
316
let mut flags = Vec :: new ( ) ;
312
- for ( i, feature_byte ) in init_ctx . flags . iter ( ) . enumerate ( ) {
317
+ for ( i, byte ) in self . flags . iter ( ) . enumerate ( ) {
313
318
if i < byte_count {
314
- flags. push ( feature_byte & T :: KNOWN_FEATURE_MASK [ i] ) ;
319
+ let known_source_features = T :: KNOWN_FEATURE_MASK [ i] ;
320
+ let known_target_features = C :: KNOWN_FEATURE_MASK [ i] ;
321
+ flags. push ( byte & known_source_features & known_target_features) ;
315
322
}
316
323
}
317
- Self { flags, mark : PhantomData , }
324
+ Features :: < C > { flags, mark : PhantomData , }
318
325
}
319
326
320
327
#[ cfg( test) ]
@@ -399,8 +406,9 @@ impl<T: sealed::UpfrontShutdownScript> Features<T> {
399
406
<T as sealed:: UpfrontShutdownScript >:: supports_feature ( & self . flags )
400
407
}
401
408
#[ cfg( test) ]
402
- pub ( crate ) fn unset_upfront_shutdown_script ( & mut self ) {
403
- <T as sealed:: UpfrontShutdownScript >:: clear_bits ( & mut self . flags )
409
+ pub ( crate ) fn clear_upfront_shutdown_script ( mut self ) -> Self {
410
+ <T as sealed:: UpfrontShutdownScript >:: clear_bits ( & mut self . flags ) ;
411
+ self
404
412
}
405
413
}
406
414
@@ -461,7 +469,7 @@ impl<T: sealed::Context> Readable for Features<T> {
461
469
462
470
#[ cfg( test) ]
463
471
mod tests {
464
- use super :: { ChannelFeatures , InitFeatures , NodeFeatures , Features } ;
472
+ use super :: { ChannelFeatures , InitFeatures , NodeFeatures } ;
465
473
466
474
#[ test]
467
475
fn sanity_test_our_features ( ) {
@@ -503,26 +511,28 @@ mod tests {
503
511
}
504
512
505
513
#[ test]
506
- fn test_node_with_known_relevant_init_flags ( ) {
507
- // Create an InitFeatures with initial_routing_sync supported.
508
- let init_features = InitFeatures :: known ( ) ;
514
+ fn convert_to_context_with_relevant_flags ( ) {
515
+ let init_features = InitFeatures :: known ( ) . clear_upfront_shutdown_script ( ) ;
509
516
assert ! ( init_features. initial_routing_sync( ) ) ;
517
+ assert ! ( !init_features. supports_upfront_shutdown_script( ) ) ;
510
518
511
- // Attempt to pull out non-node-context feature flags from these InitFeatures.
512
- let res = NodeFeatures :: with_known_relevant_init_flags ( & init_features) ;
513
-
519
+ let node_features: NodeFeatures = init_features. to_context ( ) ;
514
520
{
515
- // Check that the flags are as expected: optional_data_loss_protect,
516
- // option_upfront_shutdown_script, var_onion_optin, payment_secret, and
517
- // basic_mpp.
518
- assert_eq ! ( res. flags. len( ) , 3 ) ;
519
- assert_eq ! ( res. flags[ 0 ] , 0b00100010 ) ;
520
- assert_eq ! ( res. flags[ 1 ] , 0b10000010 ) ;
521
- assert_eq ! ( res. flags[ 2 ] , 0b00000010 ) ;
521
+ // Check that the flags are as expected:
522
+ // - option_data_loss_protect
523
+ // - var_onion_optin | payment_secret
524
+ // - basic_mpp
525
+ assert_eq ! ( node_features. flags. len( ) , 3 ) ;
526
+ assert_eq ! ( node_features. flags[ 0 ] , 0b00000010 ) ;
527
+ assert_eq ! ( node_features. flags[ 1 ] , 0b10000010 ) ;
528
+ assert_eq ! ( node_features. flags[ 2 ] , 0b00000010 ) ;
522
529
}
523
530
524
- // Check that the initial_routing_sync feature was correctly blanked out.
525
- let new_features: InitFeatures = Features :: from_le_bytes ( res. flags ) ;
526
- assert ! ( !new_features. initial_routing_sync( ) ) ;
531
+ // Check that cleared flags are kept blank when converting back:
532
+ // - initial_routing_sync was not applicable to NodeContext
533
+ // - upfront_shutdown_script was cleared before converting
534
+ let features: InitFeatures = node_features. to_context_internal ( ) ;
535
+ assert ! ( !features. initial_routing_sync( ) ) ;
536
+ assert ! ( !features. supports_upfront_shutdown_script( ) ) ;
527
537
}
528
538
}
0 commit comments