@@ -746,6 +746,32 @@ impl<T: sealed::Context> Features<T> {
746
746
}
747
747
true
748
748
}
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
+ }
749
775
}
750
776
751
777
impl < T : sealed:: UpfrontShutdownScript > Features < T > {
@@ -984,6 +1010,26 @@ mod tests {
984
1010
assert ! ( features. supports_payment_secret( ) ) ;
985
1011
}
986
1012
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
+
987
1033
#[ test]
988
1034
fn encodes_features_without_length ( ) {
989
1035
let features = OfferFeatures :: from_le_bytes ( vec ! [ 1 , 2 , 3 , 4 , 5 , 42 , 100 , 101 ] ) ;
0 commit comments