@@ -746,6 +746,50 @@ impl<T: sealed::Context> Features<T> {
746
746
}
747
747
true
748
748
}
749
+
750
+ /// Sets a required custom feature bit. Errors if `bit` is outside the custom range as defined
751
+ /// by [bLIP 2] or if it is a known `T` feature.
752
+ ///
753
+ /// Note: Required bits are even. If an odd bit is given, then the corresponding even bit will
754
+ /// be set instead (i.e., `bit - 1`).
755
+ ///
756
+ /// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
757
+ pub fn set_required_custom_bit ( & mut self , bit : usize ) -> Result < ( ) , ( ) > {
758
+ self . set_custom_bit ( bit - ( bit % 2 ) )
759
+ }
760
+
761
+ /// Sets an optional custom feature bit. Errors if `bit` is outside the custom range as defined
762
+ /// by [bLIP 2] or if it is a known `T` feature.
763
+ ///
764
+ /// Note: Optional bits are odd. If an even bit is given, then the corresponding odd bit will be
765
+ /// set instead (i.e., `bit + 1`).
766
+ ///
767
+ /// [bLIP 2]: https://github.com/lightning/blips/blob/master/blip-0002.md#feature-bits
768
+ pub fn set_optional_custom_bit ( & mut self , bit : usize ) -> Result < ( ) , ( ) > {
769
+ self . set_custom_bit ( bit + ( 1 - ( bit % 2 ) ) )
770
+ }
771
+
772
+ fn set_custom_bit ( & mut self , bit : usize ) -> Result < ( ) , ( ) > {
773
+ if bit < 256 {
774
+ return Err ( ( ) ) ;
775
+ }
776
+
777
+ let byte_offset = bit / 8 ;
778
+ let mask = 1 << ( bit - 8 * byte_offset) ;
779
+ if byte_offset < T :: KNOWN_FEATURE_MASK . len ( ) {
780
+ if ( T :: KNOWN_FEATURE_MASK [ byte_offset] & mask) != 0 {
781
+ return Err ( ( ) ) ;
782
+ }
783
+ }
784
+
785
+ if self . flags . len ( ) <= byte_offset {
786
+ self . flags . resize ( byte_offset + 1 , 0u8 ) ;
787
+ }
788
+
789
+ self . flags [ byte_offset] |= mask;
790
+
791
+ Ok ( ( ) )
792
+ }
749
793
}
750
794
751
795
impl < T : sealed:: UpfrontShutdownScript > Features < T > {
@@ -984,6 +1028,36 @@ mod tests {
984
1028
assert ! ( features. supports_payment_secret( ) ) ;
985
1029
}
986
1030
1031
+ #[ test]
1032
+ fn set_custom_bits ( ) {
1033
+ let mut features = InvoiceFeatures :: empty ( ) ;
1034
+ features. set_variable_length_onion_optional ( ) ;
1035
+ assert_eq ! ( features. flags[ 1 ] , 0b00000010 ) ;
1036
+
1037
+ assert ! ( features. set_optional_custom_bit( 255 ) . is_err( ) ) ;
1038
+ assert ! ( features. set_required_custom_bit( 256 ) . is_ok( ) ) ;
1039
+ assert ! ( features. set_required_custom_bit( 258 ) . is_ok( ) ) ;
1040
+ assert_eq ! ( features. flags[ 31 ] , 0b00000000 ) ;
1041
+ assert_eq ! ( features. flags[ 32 ] , 0b00000101 ) ;
1042
+
1043
+ let known_bit = <sealed:: InvoiceContext as sealed:: PaymentSecret >:: EVEN_BIT ;
1044
+ let byte_offset = <sealed:: InvoiceContext as sealed:: PaymentSecret >:: BYTE_OFFSET ;
1045
+ assert_eq ! ( byte_offset, 1 ) ;
1046
+ assert_eq ! ( features. flags[ byte_offset] , 0b00000010 ) ;
1047
+ assert ! ( features. set_required_custom_bit( known_bit) . is_err( ) ) ;
1048
+ assert_eq ! ( features. flags[ byte_offset] , 0b00000010 ) ;
1049
+
1050
+ let mut features = InvoiceFeatures :: empty ( ) ;
1051
+ assert ! ( features. set_optional_custom_bit( 256 ) . is_ok( ) ) ;
1052
+ assert ! ( features. set_optional_custom_bit( 259 ) . is_ok( ) ) ;
1053
+ assert_eq ! ( features. flags[ 32 ] , 0b00001010 ) ;
1054
+
1055
+ let mut features = InvoiceFeatures :: empty ( ) ;
1056
+ assert ! ( features. set_required_custom_bit( 257 ) . is_ok( ) ) ;
1057
+ assert ! ( features. set_required_custom_bit( 258 ) . is_ok( ) ) ;
1058
+ assert_eq ! ( features. flags[ 32 ] , 0b00000101 ) ;
1059
+ }
1060
+
987
1061
#[ test]
988
1062
fn encodes_features_without_length ( ) {
989
1063
let features = OfferFeatures :: from_le_bytes ( vec ! [ 1 , 2 , 3 , 4 , 5 , 42 , 100 , 101 ] ) ;
0 commit comments