Skip to content

Commit 94f2cd2

Browse files
committed
Implement set difference for Features
Taking the difference of two sets of Features allows to check if one contains required bits that are unknown to the other.
1 parent d06b490 commit 94f2cd2

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

lightning/src/ln/features.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,22 @@ impl<T: sealed::Context> core::ops::BitOr for Features<T> {
414414
}
415415
}
416416

417+
impl<T: sealed::Context> core::ops::Sub for Features<T> {
418+
type Output = Self;
419+
420+
fn sub(mut self, o: Self) -> Self {
421+
for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
422+
*byte &= !*o_byte;
423+
}
424+
425+
let last_non_zero_byte = self.flags.iter().rposition(|&byte| byte != 0);
426+
let size = if let Some(offset) = last_non_zero_byte { offset + 1 } else { 0 };
427+
self.flags.resize(size, 0u8);
428+
429+
self
430+
}
431+
}
432+
417433
impl<T: sealed::Context> Clone for Features<T> {
418434
fn clone(&self) -> Self {
419435
Self {
@@ -907,6 +923,35 @@ mod tests {
907923
assert!(features.supports_payment_secret());
908924
}
909925

926+
#[test]
927+
fn feature_difference() {
928+
let mut features1 = InitFeatures::empty();
929+
features1.set_data_loss_protect_optional();
930+
features1.set_initial_routing_sync_required();
931+
features1.set_gossip_queries_optional();
932+
features1.set_variable_length_onion_optional();
933+
features1.set_payment_secret_optional();
934+
assert_eq!(features1.flags[0], 0b10000110);
935+
assert_eq!(features1.flags[1], 0b10000010);
936+
937+
let mut features2 = InitFeatures::empty();
938+
features2.set_data_loss_protect_optional();
939+
features2.set_upfront_shutdown_script_optional();
940+
features2.set_gossip_queries_optional();
941+
features2.set_variable_length_onion_optional();
942+
features2.set_static_remote_key_optional();
943+
assert_eq!(features2.flags[0], 0b10100010);
944+
assert_eq!(features2.flags[1], 0b00100010);
945+
946+
let features1_minus2 = features1.clone() - features2.clone();
947+
assert_eq!(features1_minus2.flags[0], 0b00000100);
948+
assert_eq!(features1_minus2.flags[1], 0b10000000);
949+
950+
let features2_minus1 = features2 - features1;
951+
assert_eq!(features2_minus1.flags[0], 0b00100000);
952+
assert_eq!(features2_minus1.flags[1], 0b00100000);
953+
}
954+
910955
#[test]
911956
fn encodes_features_without_length() {
912957
let features = OfferFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);

0 commit comments

Comments
 (0)