@@ -65,7 +65,7 @@ use core::marker::PhantomData;
65
65
use bitcoin:: bech32;
66
66
use bitcoin:: bech32:: { Base32Len , FromBase32 , ToBase32 , u5, WriteBase32 } ;
67
67
use crate :: ln:: msgs:: DecodeError ;
68
- use crate :: util:: ser:: { Readable , Writeable , Writer } ;
68
+ use crate :: util:: ser:: { Readable , WithoutLength , Writeable , Writer } ;
69
69
70
70
mod sealed {
71
71
use crate :: prelude:: * ;
@@ -159,6 +159,15 @@ mod sealed {
159
159
] ) ;
160
160
define_context ! ( OfferContext , [ ] ) ;
161
161
define_context ! ( InvoiceRequestContext , [ ] ) ;
162
+ define_context ! ( Bolt12InvoiceContext , [
163
+ // Byte 0
164
+ ,
165
+ // Byte 1
166
+ ,
167
+ // Byte 2
168
+ BasicMPP ,
169
+ ] ) ;
170
+ define_context ! ( BlindedHopContext , [ ] ) ;
162
171
// This isn't a "real" feature context, and is only used in the channel_type field in an
163
172
// `OpenChannel` message.
164
173
define_context ! ( ChannelTypeContext , [
@@ -342,7 +351,7 @@ mod sealed {
342
351
define_feature ! ( 15 , PaymentSecret , [ InitContext , NodeContext , InvoiceContext ] ,
343
352
"Feature flags for `payment_secret`." , set_payment_secret_optional, set_payment_secret_required,
344
353
supports_payment_secret, requires_payment_secret) ;
345
- define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext ] ,
354
+ define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext , Bolt12InvoiceContext ] ,
346
355
"Feature flags for `basic_mpp`." , set_basic_mpp_optional, set_basic_mpp_required,
347
356
supports_basic_mpp, requires_basic_mpp) ;
348
357
define_feature ! ( 19 , Wumbo , [ InitContext , NodeContext ] ,
@@ -369,7 +378,7 @@ mod sealed {
369
378
370
379
#[ cfg( test) ]
371
380
define_feature ! ( 123456789 , UnknownFeature ,
372
- [ NodeContext , ChannelContext , InvoiceContext , OfferContext , InvoiceRequestContext ] ,
381
+ [ NodeContext , ChannelContext , InvoiceContext , OfferContext , InvoiceRequestContext , Bolt12InvoiceContext , BlindedHopContext ] ,
373
382
"Feature flags for an unknown feature used in testing." , set_unknown_feature_optional,
374
383
set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature) ;
375
384
}
@@ -432,6 +441,10 @@ pub type InvoiceFeatures = Features<sealed::InvoiceContext>;
432
441
pub type OfferFeatures = Features < sealed:: OfferContext > ;
433
442
/// Features used within an `invoice_request`.
434
443
pub type InvoiceRequestFeatures = Features < sealed:: InvoiceRequestContext > ;
444
+ /// Features used within an `invoice`.
445
+ pub type Bolt12InvoiceFeatures = Features < sealed:: Bolt12InvoiceContext > ;
446
+ /// Features used within BOLT 4 encrypted_data_tlv and BOLT 12 blinded_payinfo
447
+ pub type BlindedHopFeatures = Features < sealed:: BlindedHopContext > ;
435
448
436
449
/// Features used within the channel_type field in an OpenChannel message.
437
450
///
@@ -719,32 +732,47 @@ impl_feature_len_prefixed_write!(InitFeatures);
719
732
impl_feature_len_prefixed_write ! ( ChannelFeatures ) ;
720
733
impl_feature_len_prefixed_write ! ( NodeFeatures ) ;
721
734
impl_feature_len_prefixed_write ! ( InvoiceFeatures ) ;
735
+ impl_feature_len_prefixed_write ! ( BlindedHopFeatures ) ;
722
736
723
737
// Some features only appear inside of TLVs, so they don't have a length prefix when serialized.
724
738
macro_rules! impl_feature_tlv_write {
725
739
( $features: ident) => {
726
740
impl Writeable for $features {
727
741
fn write<W : Writer >( & self , w: & mut W ) -> Result <( ) , io:: Error > {
728
- self . write_be ( w)
742
+ WithoutLength ( self ) . write ( w)
729
743
}
730
744
}
731
745
impl Readable for $features {
732
746
fn read<R : io:: Read >( r: & mut R ) -> Result <Self , DecodeError > {
733
- let v = io_extras:: read_to_end( r) ?;
734
- Ok ( Self :: from_be_bytes( v) )
747
+ Ok ( WithoutLength :: <Self >:: read( r) ?. 0 )
735
748
}
736
749
}
737
750
}
738
751
}
739
752
740
753
impl_feature_tlv_write ! ( ChannelTypeFeatures ) ;
741
- impl_feature_tlv_write ! ( OfferFeatures ) ;
742
- impl_feature_tlv_write ! ( InvoiceRequestFeatures ) ;
754
+
755
+ // Some features may appear both in a TLV record and as part of a TLV subtype sequence. The latter
756
+ // requires a length but the former does not.
757
+
758
+ impl < T : sealed:: Context > Writeable for WithoutLength < & Features < T > > {
759
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
760
+ self . 0 . write_be ( w)
761
+ }
762
+ }
763
+
764
+ impl < T : sealed:: Context > Readable for WithoutLength < Features < T > > {
765
+ fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
766
+ let v = io_extras:: read_to_end ( r) ?;
767
+ Ok ( WithoutLength ( Features :: < T > :: from_be_bytes ( v) ) )
768
+ }
769
+ }
743
770
744
771
#[ cfg( test) ]
745
772
mod tests {
746
- use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures , sealed} ;
773
+ use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures , OfferFeatures , sealed} ;
747
774
use bitcoin:: bech32:: { Base32Len , FromBase32 , ToBase32 , u5} ;
775
+ use crate :: util:: ser:: { Readable , WithoutLength , Writeable } ;
748
776
749
777
#[ test]
750
778
fn sanity_test_unknown_bits ( ) {
@@ -838,6 +866,20 @@ mod tests {
838
866
assert ! ( features. supports_payment_secret( ) ) ;
839
867
}
840
868
869
+ #[ test]
870
+ fn encodes_features_without_length ( ) {
871
+ let features = OfferFeatures :: from_le_bytes ( vec ! [ 1 , 2 , 3 , 4 , 5 , 42 , 100 , 101 ] ) ;
872
+ assert_eq ! ( features. flags. len( ) , 8 ) ;
873
+
874
+ let mut serialized_features = Vec :: new ( ) ;
875
+ WithoutLength ( & features) . write ( & mut serialized_features) . unwrap ( ) ;
876
+ assert_eq ! ( serialized_features. len( ) , 8 ) ;
877
+
878
+ let deserialized_features =
879
+ WithoutLength :: < OfferFeatures > :: read ( & mut & serialized_features[ ..] ) . unwrap ( ) . 0 ;
880
+ assert_eq ! ( features, deserialized_features) ;
881
+ }
882
+
841
883
#[ test]
842
884
fn invoice_features_encoding ( ) {
843
885
let features_as_u5s = vec ! [
0 commit comments