@@ -65,7 +65,7 @@ use core::marker::PhantomData;
6565use bitcoin:: bech32;
6666use bitcoin:: bech32:: { Base32Len , FromBase32 , ToBase32 , u5, WriteBase32 } ;
6767use crate :: ln:: msgs:: DecodeError ;
68- use crate :: util:: ser:: { Readable , Writeable , Writer } ;
68+ use crate :: util:: ser:: { Readable , WithoutLength , Writeable , Writer } ;
6969
7070mod sealed {
7171 use crate :: prelude:: * ;
@@ -159,6 +159,15 @@ mod sealed {
159159 ] ) ;
160160 define_context ! ( OfferContext , [ ] ) ;
161161 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 , [ ] ) ;
162171 // This isn't a "real" feature context, and is only used in the channel_type field in an
163172 // `OpenChannel` message.
164173 define_context ! ( ChannelTypeContext , [
@@ -342,7 +351,7 @@ mod sealed {
342351 define_feature ! ( 15 , PaymentSecret , [ InitContext , NodeContext , InvoiceContext ] ,
343352 "Feature flags for `payment_secret`." , set_payment_secret_optional, set_payment_secret_required,
344353 supports_payment_secret, requires_payment_secret) ;
345- define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext ] ,
354+ define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext , Bolt12InvoiceContext ] ,
346355 "Feature flags for `basic_mpp`." , set_basic_mpp_optional, set_basic_mpp_required,
347356 supports_basic_mpp, requires_basic_mpp) ;
348357 define_feature ! ( 19 , Wumbo , [ InitContext , NodeContext ] ,
@@ -369,7 +378,7 @@ mod sealed {
369378
370379 #[ cfg( test) ]
371380 define_feature ! ( 123456789 , UnknownFeature ,
372- [ NodeContext , ChannelContext , InvoiceContext , OfferContext , InvoiceRequestContext ] ,
381+ [ NodeContext , ChannelContext , InvoiceContext , OfferContext , InvoiceRequestContext , Bolt12InvoiceContext , BlindedHopContext ] ,
373382 "Feature flags for an unknown feature used in testing." , set_unknown_feature_optional,
374383 set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature) ;
375384}
@@ -432,6 +441,10 @@ pub type InvoiceFeatures = Features<sealed::InvoiceContext>;
432441pub type OfferFeatures = Features < sealed:: OfferContext > ;
433442/// Features used within an `invoice_request`.
434443pub 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 > ;
435448
436449/// Features used within the channel_type field in an OpenChannel message.
437450///
@@ -719,32 +732,47 @@ impl_feature_len_prefixed_write!(InitFeatures);
719732impl_feature_len_prefixed_write ! ( ChannelFeatures ) ;
720733impl_feature_len_prefixed_write ! ( NodeFeatures ) ;
721734impl_feature_len_prefixed_write ! ( InvoiceFeatures ) ;
735+ impl_feature_len_prefixed_write ! ( BlindedHopFeatures ) ;
722736
723737// Some features only appear inside of TLVs, so they don't have a length prefix when serialized.
724738macro_rules! impl_feature_tlv_write {
725739 ( $features: ident) => {
726740 impl Writeable for $features {
727741 fn write<W : Writer >( & self , w: & mut W ) -> Result <( ) , io:: Error > {
728- self . write_be ( w)
742+ WithoutLength ( self ) . write ( w)
729743 }
730744 }
731745 impl Readable for $features {
732746 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 )
735748 }
736749 }
737750 }
738751}
739752
740753impl_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+ }
743770
744771#[ cfg( test) ]
745772mod tests {
746- use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures , sealed} ;
773+ use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures , OfferFeatures , sealed} ;
747774 use bitcoin:: bech32:: { Base32Len , FromBase32 , ToBase32 , u5} ;
775+ use crate :: util:: ser:: { Readable , WithoutLength , Writeable } ;
748776
749777 #[ test]
750778 fn sanity_test_unknown_bits ( ) {
@@ -838,6 +866,20 @@ mod tests {
838866 assert ! ( features. supports_payment_secret( ) ) ;
839867 }
840868
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+
841883 #[ test]
842884 fn invoice_features_encoding ( ) {
843885 let features_as_u5s = vec ! [
0 commit comments