Skip to content

Commit 0f70f8a

Browse files
committed
Add Features::set_custom_bit
Custom message handlers may need to set feature bits that are unknown to LDK. Provide a Features::set_custom_bit to allow for this.
1 parent f753a3d commit 0f70f8a

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

lightning/src/ln/features.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,32 @@ impl<T: sealed::Context> Features<T> {
746746
}
747747
true
748748
}
749+
750+
/// Sets a custom feature bit. Errors if `bit` is outside the custom range as defined by
751+
/// [bLIP 2] or if it is a known `T` feature.
752+
///
753+
/// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
754+
pub fn set_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
755+
if bit < 256 {
756+
return Err(());
757+
}
758+
759+
let byte_offset = bit / 8;
760+
let mask = 1 << (bit - 8 * byte_offset);
761+
if byte_offset < T::KNOWN_FEATURE_MASK.len() {
762+
if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
763+
return Err(());
764+
}
765+
}
766+
767+
if self.flags.len() <= byte_offset {
768+
self.flags.resize(byte_offset + 1, 0u8);
769+
}
770+
771+
self.flags[byte_offset] |= mask;
772+
773+
Ok(())
774+
}
749775
}
750776

751777
impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -984,6 +1010,26 @@ mod tests {
9841010
assert!(features.supports_payment_secret());
9851011
}
9861012

1013+
#[test]
1014+
fn set_custom_bits() {
1015+
let mut features = InvoiceFeatures::empty();
1016+
features.set_variable_length_onion_optional();
1017+
assert_eq!(features.flags[1], 0b00000010);
1018+
1019+
assert!(features.set_custom_bit(255).is_err());
1020+
assert!(features.set_custom_bit(256).is_ok());
1021+
assert!(features.set_custom_bit(258).is_ok());
1022+
assert_eq!(features.flags[31], 0b00000000);
1023+
assert_eq!(features.flags[32], 0b00000101);
1024+
1025+
let known_bit = <sealed::InvoiceContext as sealed::PaymentSecret>::EVEN_BIT;
1026+
let byte_offset = <sealed::InvoiceContext as sealed::PaymentSecret>::BYTE_OFFSET;
1027+
assert_eq!(byte_offset, 1);
1028+
assert_eq!(features.flags[byte_offset], 0b00000010);
1029+
assert!(features.set_custom_bit(known_bit).is_err());
1030+
assert_eq!(features.flags[byte_offset], 0b00000010);
1031+
}
1032+
9871033
#[test]
9881034
fn encodes_features_without_length() {
9891035
let features = OfferFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);

0 commit comments

Comments
 (0)