Skip to content

Commit c9de650

Browse files
authored
Merge pull request #2947 from tnull/2024-03-log-features-if-mismatch
2 parents bd16a1e + 44cf692 commit c9de650

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

lightning/src/ln/features.rs

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ mod sealed {
442442
set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature);
443443
}
444444

445+
const ANY_REQUIRED_FEATURES_MASK: u8 = 0b01_01_01_01;
446+
const ANY_OPTIONAL_FEATURES_MASK: u8 = 0b10_10_10_10;
447+
445448
/// Tracks the set of features which a node implements, templated by the context in which it
446449
/// appears.
447450
///
@@ -615,8 +618,8 @@ impl ChannelTypeFeatures {
615618
// ChannelTypeFeatures must only contain required bits, so we OR the required forms of all
616619
// optional bits and then AND out the optional ones.
617620
for byte in ret.flags.iter_mut() {
618-
*byte |= (*byte & 0b10_10_10_10) >> 1;
619-
*byte &= 0b01_01_01_01;
621+
*byte |= (*byte & ANY_OPTIONAL_FEATURES_MASK) >> 1;
622+
*byte &= ANY_REQUIRED_FEATURES_MASK;
620623
}
621624
ret
622625
}
@@ -761,42 +764,51 @@ impl<T: sealed::Context> Features<T> {
761764
}
762765

763766
pub(crate) fn supports_any_optional_bits(&self) -> bool {
764-
self.flags.iter().any(|&byte| (byte & 0b10_10_10_10) != 0)
767+
self.flags.iter().any(|&byte| (byte & ANY_OPTIONAL_FEATURES_MASK) != 0)
765768
}
766769

767770
/// Returns true if this `Features` object contains required features unknown by `other`.
768771
pub fn requires_unknown_bits_from(&self, other: &Self) -> bool {
769772
// Bitwise AND-ing with all even bits set except for known features will select required
770773
// unknown features.
771774
self.flags.iter().enumerate().any(|(i, &byte)| {
772-
const REQUIRED_FEATURES: u8 = 0b01_01_01_01;
773-
const OPTIONAL_FEATURES: u8 = 0b10_10_10_10;
774-
let unknown_features = if i < other.flags.len() {
775-
// Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
776-
!(other.flags[i]
777-
| ((other.flags[i] >> 1) & REQUIRED_FEATURES)
778-
| ((other.flags[i] << 1) & OPTIONAL_FEATURES))
779-
} else {
780-
0b11_11_11_11
781-
};
782-
(byte & (REQUIRED_FEATURES & unknown_features)) != 0
775+
let unknown_features = unset_features_mask_at_position(other, i);
776+
(byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
783777
})
784778
}
785779

780+
pub(crate) fn required_unknown_bits_from(&self, other: &Self) -> Vec<usize> {
781+
let mut unknown_bits = Vec::new();
782+
783+
// Bitwise AND-ing with all even bits set except for known features will select required
784+
// unknown features.
785+
self.flags.iter().enumerate().for_each(|(i, &byte)| {
786+
let unknown_features = unset_features_mask_at_position(other, i);
787+
if byte & unknown_features != 0 {
788+
for bit in (0..8).step_by(2) {
789+
if ((byte & unknown_features) >> bit) & 1 == 1 {
790+
unknown_bits.push(i * 8 + bit);
791+
}
792+
}
793+
}
794+
});
795+
796+
unknown_bits
797+
}
798+
786799
/// Returns true if this `Features` object contains unknown feature flags which are set as
787800
/// "required".
788801
pub fn requires_unknown_bits(&self) -> bool {
789802
// Bitwise AND-ing with all even bits set except for known features will select required
790803
// unknown features.
791804
let byte_count = T::KNOWN_FEATURE_MASK.len();
792805
self.flags.iter().enumerate().any(|(i, &byte)| {
793-
let required_features = 0b01_01_01_01;
794806
let unknown_features = if i < byte_count {
795807
!T::KNOWN_FEATURE_MASK[i]
796808
} else {
797809
0b11_11_11_11
798810
};
799-
(byte & (required_features & unknown_features)) != 0
811+
(byte & (ANY_REQUIRED_FEATURES_MASK & unknown_features)) != 0
800812
})
801813
}
802814

@@ -1017,6 +1029,17 @@ impl<T: sealed::Context> Readable for WithoutLength<Features<T>> {
10171029
}
10181030
}
10191031

1032+
pub(crate) fn unset_features_mask_at_position<T: sealed::Context>(other: &Features<T>, index: usize) -> u8 {
1033+
if index < other.flags.len() {
1034+
// Form a mask similar to !T::KNOWN_FEATURE_MASK only for `other`
1035+
!(other.flags[index]
1036+
| ((other.flags[index] >> 1) & ANY_REQUIRED_FEATURES_MASK)
1037+
| ((other.flags[index] << 1) & ANY_OPTIONAL_FEATURES_MASK))
1038+
} else {
1039+
0b11_11_11_11
1040+
}
1041+
}
1042+
10201043
#[cfg(test)]
10211044
mod tests {
10221045
use super::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, Bolt11InvoiceFeatures, NodeFeatures, OfferFeatures, sealed};
@@ -1033,11 +1056,24 @@ mod tests {
10331056
features.set_unknown_feature_required();
10341057
assert!(features.requires_unknown_bits());
10351058
assert!(features.supports_unknown_bits());
1059+
assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456788]);
10361060

10371061
let mut features = ChannelFeatures::empty();
10381062
features.set_unknown_feature_optional();
10391063
assert!(!features.requires_unknown_bits());
10401064
assert!(features.supports_unknown_bits());
1065+
assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![]);
1066+
1067+
let mut features = ChannelFeatures::empty();
1068+
features.set_unknown_feature_required();
1069+
features.set_custom_bit(123456786).unwrap();
1070+
assert!(features.requires_unknown_bits());
1071+
assert!(features.supports_unknown_bits());
1072+
assert_eq!(features.required_unknown_bits_from(&ChannelFeatures::empty()), vec![123456786, 123456788]);
1073+
1074+
let mut limiter = ChannelFeatures::empty();
1075+
limiter.set_unknown_feature_optional();
1076+
assert_eq!(features.required_unknown_bits_from(&limiter), vec![123456786]);
10411077
}
10421078

10431079
#[test]

lightning/src/ln/peer_handler.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,12 +1654,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
16541654

16551655
let our_features = self.init_features(&their_node_id);
16561656
if msg.features.requires_unknown_bits_from(&our_features) {
1657-
log_debug!(logger, "Peer requires features unknown to us");
1657+
log_debug!(logger, "Peer {} requires features unknown to us: {:?}",
1658+
log_pubkey!(their_node_id), msg.features.required_unknown_bits_from(&our_features));
16581659
return Err(PeerHandleError { }.into());
16591660
}
16601661

16611662
if our_features.requires_unknown_bits_from(&msg.features) {
1662-
log_debug!(logger, "We require features unknown to our peer");
1663+
log_debug!(logger, "We require features unknown to our peer {}: {:?}",
1664+
log_pubkey!(their_node_id), our_features.required_unknown_bits_from(&msg.features));
16631665
return Err(PeerHandleError { }.into());
16641666
}
16651667

0 commit comments

Comments
 (0)