Skip to content

Commit 58e7897

Browse files
committed
Add Features::requires_unknown_bits_from
When checking features, rather than checking against which features LDK knows about, it is more useful to check against a peer's features. Add Features::requires_unknown_bits_from such that the given features are used instead.
1 parent 137c132 commit 58e7897

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

lightning/src/ln/features.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,26 @@ impl<T: sealed::Context> Features<T> {
695695
self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
696696
}
697697

698+
/// Returns true if this `Features` object contains required features unknown by `other`.
699+
pub fn requires_unknown_bits_from(&self, other: &Features<T>) -> bool {
700+
// Bitwise AND-ing with all even bits set except for known features will select required
701+
// unknown features.
702+
let byte_count = other.flags.len();
703+
self.flags.iter().enumerate().any(|(i, &byte)| {
704+
let required_features = 0b01_01_01_01;
705+
let optional_features = 0b10_10_10_10;
706+
let unknown_features = if i < byte_count {
707+
// Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
708+
!(other.flags[i]
709+
| ((other.flags[i] >> 1) & required_features)
710+
| ((other.flags[i] << 1) & optional_features))
711+
} else {
712+
0b11_11_11_11
713+
};
714+
(byte & (required_features & unknown_features)) != 0
715+
})
716+
}
717+
698718
/// Returns true if this `Features` object contains unknown feature flags which are set as
699719
/// "required".
700720
pub fn requires_unknown_bits(&self) -> bool {
@@ -868,6 +888,43 @@ mod tests {
868888
assert!(features.supports_unknown_bits());
869889
}
870890

891+
#[test]
892+
fn requires_unknown_bits_from() {
893+
let mut features1 = InitFeatures::empty();
894+
let mut features2 = InitFeatures::empty();
895+
assert!(!features1.requires_unknown_bits_from(&features2));
896+
assert!(!features2.requires_unknown_bits_from(&features1));
897+
898+
features1.set_data_loss_protect_required();
899+
assert!(features1.requires_unknown_bits_from(&features2));
900+
assert!(!features2.requires_unknown_bits_from(&features1));
901+
902+
features2.set_data_loss_protect_optional();
903+
assert!(!features1.requires_unknown_bits_from(&features2));
904+
assert!(!features2.requires_unknown_bits_from(&features1));
905+
906+
features2.set_gossip_queries_required();
907+
assert!(!features1.requires_unknown_bits_from(&features2));
908+
assert!(features2.requires_unknown_bits_from(&features1));
909+
910+
features1.set_gossip_queries_optional();
911+
assert!(!features1.requires_unknown_bits_from(&features2));
912+
assert!(!features2.requires_unknown_bits_from(&features1));
913+
914+
features1.set_variable_length_onion_required();
915+
assert!(features1.requires_unknown_bits_from(&features2));
916+
assert!(!features2.requires_unknown_bits_from(&features1));
917+
918+
features2.set_variable_length_onion_optional();
919+
assert!(!features1.requires_unknown_bits_from(&features2));
920+
assert!(!features2.requires_unknown_bits_from(&features1));
921+
922+
features1.set_basic_mpp_required();
923+
features2.set_wumbo_required();
924+
assert!(features1.requires_unknown_bits_from(&features2));
925+
assert!(features2.requires_unknown_bits_from(&features1));
926+
}
927+
871928
#[test]
872929
fn convert_to_context_with_relevant_flags() {
873930
let mut init_features = InitFeatures::empty();

0 commit comments

Comments
 (0)