})
}
+ pub(crate) fn required_unknown_bits_from(&self, other: &Self) -> Vec<usize> {
+ let mut unknown_bits = Vec::new();
+
+ // Bitwise AND-ing with all even bits set except for known features will select required
+ // unknown features.
+ self.flags.iter().enumerate().for_each(|(i, &byte)| {
+ const REQUIRED_FEATURES: u8 = 0b01_01_01_01;
+ const OPTIONAL_FEATURES: u8 = 0b10_10_10_10;
+ let unknown_features = if i < other.flags.len() {
+ // Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
+ !(other.flags[i]
+ | ((other.flags[i] >> 1) & REQUIRED_FEATURES)
+ | ((other.flags[i] << 1) & OPTIONAL_FEATURES))
+ } else {
+ 0b11_11_11_11
+ };
+
+ if byte & unknown_features != 0 {
+ for bit in (0..8).step_by(2) {
+ if ((byte & unknown_features) >> bit) & 1 == 1 {
+ unknown_bits.push(i * 8 + bit);
+ }
+ }
+ }
+ });
+
+ unknown_bits
+ }
+
/// Returns true if this `Features` object contains unknown feature flags which are set as
/// "required".
pub fn requires_unknown_bits(&self) -> bool {
features.set_unknown_feature_required();
assert!(features.requires_unknown_bits());
assert!(features.supports_unknown_bits());
+ assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456788]);
let mut features = ChannelFeatures::empty();
features.set_unknown_feature_optional();
assert!(!features.requires_unknown_bits());
assert!(features.supports_unknown_bits());
+ assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![]);
+
+ let mut features = ChannelFeatures::empty();
+ features.set_unknown_feature_required();
+ features.set_custom_bit(123456786).unwrap();
+ assert!(features.requires_unknown_bits());
+ assert!(features.supports_unknown_bits());
+ assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456786, 123456788]);
+
+ let mut limiter = ChannelFeatures::empty();
+ limiter.set_unknown_feature_optional();
+ assert_eq!(features.required_unknown_bits_from(&limiter), vec![123456786]);
}
#[test]
let our_features = self.init_features(&their_node_id);
if msg.features.requires_unknown_bits_from(&our_features) {
- log_debug!(logger, "Peer requires features unknown to us");
+ log_debug!(logger, "Peer {} requires features unknown to us: {:?}",
+ log_pubkey!(their_node_id), msg.features.required_unknown_bits_from(&our_features));
return Err(PeerHandleError { }.into());
}
if our_features.requires_unknown_bits_from(&msg.features) {
- log_debug!(logger, "We require features unknown to our peer");
+ log_debug!(logger, "We require features unknown to our peer {}: {:?}",
+ log_pubkey!(their_node_id), our_features.required_unknown_bits_from(&msg.features));
return Err(PeerHandleError { }.into());
}