Skip to content

Commit 3313abb

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 21708b5 commit 3313abb

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

lightning/src/ln/features.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,25 @@ impl<T: sealed::Context> Features<T> {
679679
self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
680680
}
681681

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+
682701
/// Returns true if this `Features` object contains unknown feature flags which are set as
683702
/// "required".
684703
pub fn requires_unknown_bits(&self) -> bool {
@@ -852,6 +871,43 @@ mod tests {
852871
assert!(features.supports_unknown_bits());
853872
}
854873

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+
855911
#[test]
856912
fn convert_to_context_with_relevant_flags() {
857913
let mut init_features = InitFeatures::empty();

0 commit comments

Comments
 (0)