@@ -679,6 +679,25 @@ impl<T: sealed::Context> Features<T> {
679
679
self . flags . iter ( ) . any ( |& byte| ( byte & 0b10_10_10_10 ) != 0 )
680
680
}
681
681
682
+ /// Returns true if this `Features` object contains required features unknown by `other`.
683
+ pub fn requires_unknown_bits_from ( & self , other : & Features < T > ) -> bool {
684
+ // Bitwise AND-ing with all even bits set except for known features will select required
685
+ // unknown features.
686
+ self . flags . iter ( ) . enumerate ( ) . any ( |( i, & byte) | {
687
+ const REQUIRED_FEATURES : u8 = 0b01_01_01_01 ;
688
+ const OPTIONAL_FEATURES : u8 = 0b10_10_10_10 ;
689
+ let unknown_features = if i < other. flags . len ( ) {
690
+ // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
691
+ !( other. flags [ i]
692
+ | ( ( other. flags [ i] >> 1 ) & REQUIRED_FEATURES )
693
+ | ( ( other. flags [ i] << 1 ) & OPTIONAL_FEATURES ) )
694
+ } else {
695
+ 0b11_11_11_11
696
+ } ;
697
+ ( byte & ( REQUIRED_FEATURES & unknown_features) ) != 0
698
+ } )
699
+ }
700
+
682
701
/// Returns true if this `Features` object contains unknown feature flags which are set as
683
702
/// "required".
684
703
pub fn requires_unknown_bits ( & self ) -> bool {
@@ -852,6 +871,43 @@ mod tests {
852
871
assert ! ( features. supports_unknown_bits( ) ) ;
853
872
}
854
873
874
+ #[ test]
875
+ fn requires_unknown_bits_from ( ) {
876
+ let mut features1 = InitFeatures :: empty ( ) ;
877
+ let mut features2 = InitFeatures :: empty ( ) ;
878
+ assert ! ( !features1. requires_unknown_bits_from( & features2) ) ;
879
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
880
+
881
+ features1. set_data_loss_protect_required ( ) ;
882
+ assert ! ( features1. requires_unknown_bits_from( & features2) ) ;
883
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
884
+
885
+ features2. set_data_loss_protect_optional ( ) ;
886
+ assert ! ( !features1. requires_unknown_bits_from( & features2) ) ;
887
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
888
+
889
+ features2. set_gossip_queries_required ( ) ;
890
+ assert ! ( !features1. requires_unknown_bits_from( & features2) ) ;
891
+ assert ! ( features2. requires_unknown_bits_from( & features1) ) ;
892
+
893
+ features1. set_gossip_queries_optional ( ) ;
894
+ assert ! ( !features1. requires_unknown_bits_from( & features2) ) ;
895
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
896
+
897
+ features1. set_variable_length_onion_required ( ) ;
898
+ assert ! ( features1. requires_unknown_bits_from( & features2) ) ;
899
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
900
+
901
+ features2. set_variable_length_onion_optional ( ) ;
902
+ assert ! ( !features1. requires_unknown_bits_from( & features2) ) ;
903
+ assert ! ( !features2. requires_unknown_bits_from( & features1) ) ;
904
+
905
+ features1. set_basic_mpp_required ( ) ;
906
+ features2. set_wumbo_required ( ) ;
907
+ assert ! ( features1. requires_unknown_bits_from( & features2) ) ;
908
+ assert ! ( features2. requires_unknown_bits_from( & features1) ) ;
909
+ }
910
+
855
911
#[ test]
856
912
fn convert_to_context_with_relevant_flags ( ) {
857
913
let mut init_features = InitFeatures :: empty ( ) ;
0 commit comments