Skip to content

Commit 974d74d

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 ca3f90c commit 974d74d

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
@@ -722,6 +722,32 @@ impl<T: sealed::Context> Features<T> {
722722
}
723723
true
724724
}
725+
726+
/// Sets a custom feature bit. Errors if `bit` is outside the custom range as defined by
727+
/// [bLIP 2] or if it is a known `T` feature.
728+
///
729+
/// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
730+
pub fn set_custom_bit(&mut self, bit: usize) -> Result<(), ()> {
731+
if bit < 256 {
732+
return Err(());
733+
}
734+
735+
let byte_offset = bit / 8;
736+
let mask = 1 << (bit - 8 * byte_offset);
737+
if byte_offset < T::KNOWN_FEATURE_MASK.len() {
738+
if (T::KNOWN_FEATURE_MASK[byte_offset] & mask) != 0 {
739+
return Err(());
740+
}
741+
}
742+
743+
if self.flags.len() <= byte_offset {
744+
self.flags.resize(byte_offset + 1, 0u8);
745+
}
746+
747+
self.flags[byte_offset] |= mask;
748+
749+
Ok(())
750+
}
725751
}
726752

727753
impl<T: sealed::UpfrontShutdownScript> Features<T> {
@@ -923,6 +949,26 @@ mod tests {
923949
assert!(features.supports_payment_secret());
924950
}
925951

952+
#[test]
953+
fn set_custom_bits() {
954+
let mut features = InvoiceFeatures::empty();
955+
features.set_variable_length_onion_optional();
956+
assert_eq!(features.flags[1], 0b00000010);
957+
958+
assert!(features.set_custom_bit(255).is_err());
959+
assert!(features.set_custom_bit(256).is_ok());
960+
assert!(features.set_custom_bit(258).is_ok());
961+
assert_eq!(features.flags[31], 0b00000000);
962+
assert_eq!(features.flags[32], 0b00000101);
963+
964+
let known_bit = <sealed::InvoiceContext as sealed::PaymentSecret>::EVEN_BIT;
965+
let byte_offset = <sealed::InvoiceContext as sealed::PaymentSecret>::BYTE_OFFSET;
966+
assert_eq!(byte_offset, 1);
967+
assert_eq!(features.flags[byte_offset], 0b00000010);
968+
assert!(features.set_custom_bit(known_bit).is_err());
969+
assert_eq!(features.flags[byte_offset], 0b00000010);
970+
}
971+
926972
#[test]
927973
fn feature_difference() {
928974
let mut features1 = InitFeatures::empty();

0 commit comments

Comments
 (0)