Skip to content

Commit 55ce1be

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 f80cabc commit 55ce1be

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
@@ -743,6 +743,32 @@ impl<T: sealed::Context> Features<T> {
743743
}
744744
true
745745
}
746+
747+
/// Sets a custom feature bit. Errors if `bit` is outside the custom range as defined by
748+
/// [bLIP 2] or if it is a known `T` feature.
749+
///
750+
/// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
751+
pub fn set_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
752+
if bit < 256 {
753+
return Err(());
754+
}
755+
756+
let byte_offset = bit / 8;
757+
let mask = 1 << (bit - 8 * byte_offset);
758+
if byte_offset < T::KNOWN_FEATURE_MASK.len() {
759+
if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
760+
return Err(());
761+
}
762+
}
763+
764+
if self.flags.len() <= byte_offset {
765+
self.flags.resize(byte_offset + 1, 0u8);
766+
}
767+
768+
self.flags[byte_offset] |= mask;
769+
770+
Ok(())
771+
}
746772
}
747773

748774
impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -944,6 +970,26 @@ mod tests {
944970
assert!(features.supports_payment_secret());
945971
}
946972

973+
#[test]
974+
fn set_custom_bits() {
975+
let mut features = InvoiceFeatures::empty();
976+
features.set_variable_length_onion_optional();
977+
assert_eq!(features.flags[1], 0b00000010);
978+
979+
assert!(features.set_custom_bit(255).is_err());
980+
assert!(features.set_custom_bit(256).is_ok());
981+
assert!(features.set_custom_bit(258).is_ok());
982+
assert_eq!(features.flags[31], 0b00000000);
983+
assert_eq!(features.flags[32], 0b00000101);
984+
985+
let known_bit = <sealed::InvoiceContext as sealed::PaymentSecret>::EVEN_BIT;
986+
let byte_offset = <sealed::InvoiceContext as sealed::PaymentSecret>::BYTE_OFFSET;
987+
assert_eq!(byte_offset, 1);
988+
assert_eq!(features.flags[byte_offset], 0b00000010);
989+
assert!(features.set_custom_bit(known_bit).is_err());
990+
assert_eq!(features.flags[byte_offset], 0b00000010);
991+
}
992+
947993
#[test]
948994
fn feature_difference() {
949995
let mut features1 = InitFeatures::empty();

0 commit comments

Comments
 (0)