Skip to content

Commit 2a2b20a

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 09728cc commit 2a2b20a

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
@@ -435,6 +435,22 @@ impl<T: sealed::Context> core::ops::BitOr for Features<T> {
435435
}
436436
}
437437

438+
impl<T: sealed::Context> core::ops::Sub for Features<T> {
439+
type Output = Self;
440+
441+
fn sub(mut self, o: Self) -> Self {
442+
for (byte, o_byte) in self.flags.iter_mut().zip(o.flags.iter()) {
443+
*byte &= !*o_byte;
444+
}
445+
446+
let last_non_zero_byte = self.flags.iter().rposition(|&byte| byte != 0);
447+
let size = if let Some(offset) = last_non_zero_byte { offset + 1 } else { 0 };
448+
self.flags.resize(size, 0u8);
449+
450+
self
451+
}
452+
}
453+
438454
impl<T: sealed::Context> Clone for Features<T> {
439455
fn clone(&self) -> Self {
440456
Self {
@@ -928,6 +944,35 @@ mod tests {
928944
assert!(features.supports_payment_secret());
929945
}
930946

947+
#[test]
948+
fn feature_difference() {
949+
let mut features1 = InitFeatures::empty();
950+
features1.set_data_loss_protect_optional();
951+
features1.set_initial_routing_sync_required();
952+
features1.set_gossip_queries_optional();
953+
features1.set_variable_length_onion_optional();
954+
features1.set_payment_secret_optional();
955+
assert_eq!(features1.flags[0], 0b10000110);
956+
assert_eq!(features1.flags[1], 0b10000010);
957+
958+
let mut features2 = InitFeatures::empty();
959+
features2.set_data_loss_protect_optional();
960+
features2.set_upfront_shutdown_script_optional();
961+
features2.set_gossip_queries_optional();
962+
features2.set_variable_length_onion_optional();
963+
features2.set_static_remote_key_optional();
964+
assert_eq!(features2.flags[0], 0b10100010);
965+
assert_eq!(features2.flags[1], 0b00100010);
966+
967+
let features1_minus2 = features1.clone() - features2.clone();
968+
assert_eq!(features1_minus2.flags[0], 0b00000100);
969+
assert_eq!(features1_minus2.flags[1], 0b10000000);
970+
971+
let features2_minus1 = features2 - features1;
972+
assert_eq!(features2_minus1.flags[0], 0b00100000);
973+
assert_eq!(features2_minus1.flags[1], 0b00100000);
974+
}
975+
931976
#[test]
932977
fn encodes_features_without_length() {
933978
let features = OfferFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);

0 commit comments

Comments
 (0)