@@ -235,6 +235,24 @@ mod sealed {
235
235
BasicMPP ,
236
236
] ,
237
237
} ) ;
238
+ define_context ! ( OfferContext {
239
+ required_features: [
240
+ // Byte 0
241
+ ,
242
+ // Byte 1
243
+ VariableLengthOnion | PaymentSecret ,
244
+ // Byte 2
245
+ ,
246
+ ] ,
247
+ optional_features: [
248
+ // Byte 0
249
+ ,
250
+ // Byte 1
251
+ ,
252
+ // Byte 2
253
+ BasicMPP ,
254
+ ] ,
255
+ } ) ;
238
256
// This isn't a "real" feature context, and is only used in the channel_type field in an
239
257
// `OpenChannel` message.
240
258
define_context ! ( ChannelTypeContext {
@@ -414,17 +432,17 @@ mod sealed {
414
432
define_feature ! ( 7 , GossipQueries , [ InitContext , NodeContext ] ,
415
433
"Feature flags for `gossip_queries`." , set_gossip_queries_optional, set_gossip_queries_required,
416
434
supports_gossip_queries, requires_gossip_queries) ;
417
- define_feature ! ( 9 , VariableLengthOnion , [ InitContext , NodeContext , InvoiceContext ] ,
435
+ define_feature ! ( 9 , VariableLengthOnion , [ InitContext , NodeContext , InvoiceContext , OfferContext ] ,
418
436
"Feature flags for `var_onion_optin`." , set_variable_length_onion_optional,
419
437
set_variable_length_onion_required, supports_variable_length_onion,
420
438
requires_variable_length_onion) ;
421
439
define_feature ! ( 13 , StaticRemoteKey , [ InitContext , NodeContext , ChannelTypeContext ] ,
422
440
"Feature flags for `option_static_remotekey`." , set_static_remote_key_optional,
423
441
set_static_remote_key_required, supports_static_remote_key, requires_static_remote_key) ;
424
- define_feature ! ( 15 , PaymentSecret , [ InitContext , NodeContext , InvoiceContext ] ,
442
+ define_feature ! ( 15 , PaymentSecret , [ InitContext , NodeContext , InvoiceContext , OfferContext ] ,
425
443
"Feature flags for `payment_secret`." , set_payment_secret_optional, set_payment_secret_required,
426
444
supports_payment_secret, requires_payment_secret) ;
427
- define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext ] ,
445
+ define_feature ! ( 17 , BasicMPP , [ InitContext , NodeContext , InvoiceContext , OfferContext ] ,
428
446
"Feature flags for `basic_mpp`." , set_basic_mpp_optional, set_basic_mpp_required,
429
447
supports_basic_mpp, requires_basic_mpp) ;
430
448
define_feature ! ( 19 , Wumbo , [ InitContext , NodeContext ] ,
@@ -447,7 +465,7 @@ mod sealed {
447
465
supports_keysend, requires_keysend) ;
448
466
449
467
#[ cfg( test) ]
450
- define_feature ! ( 123456789 , UnknownFeature , [ NodeContext , ChannelContext , InvoiceContext ] ,
468
+ define_feature ! ( 123456789 , UnknownFeature , [ NodeContext , ChannelContext , InvoiceContext , OfferContext ] ,
451
469
"Feature flags for an unknown feature used in testing." , set_unknown_feature_optional,
452
470
set_unknown_feature_required, supports_unknown_test_feature, requires_unknown_test_feature) ;
453
471
}
@@ -495,6 +513,8 @@ pub type NodeFeatures = Features<sealed::NodeContext>;
495
513
pub type ChannelFeatures = Features < sealed:: ChannelContext > ;
496
514
/// Features used within an invoice.
497
515
pub type InvoiceFeatures = Features < sealed:: InvoiceContext > ;
516
+ /// Features used within an offer.
517
+ pub type OfferFeatures = Features < sealed:: OfferContext > ;
498
518
499
519
/// Features used within the channel_type field in an OpenChannel message.
500
520
///
@@ -564,6 +584,15 @@ impl InvoiceFeatures {
564
584
}
565
585
}
566
586
587
+ #[ cfg( test) ]
588
+ impl OfferFeatures {
589
+ /// Converts `OfferFeatures` to `Features<C>`. Only known `InvoiceFeatures` relevant to context
590
+ /// `C` are included in the result.
591
+ pub ( crate ) fn to_context < C : sealed:: Context > ( & self ) -> Features < C > {
592
+ self . to_context_internal ( )
593
+ }
594
+ }
595
+
567
596
impl ChannelTypeFeatures {
568
597
/// Constructs the implicit channel type based on the common supported types between us and our
569
598
/// counterparty
@@ -811,24 +840,29 @@ impl_feature_len_prefixed_write!(ChannelFeatures);
811
840
impl_feature_len_prefixed_write ! ( NodeFeatures ) ;
812
841
impl_feature_len_prefixed_write ! ( InvoiceFeatures ) ;
813
842
814
- // Because ChannelTypeFeatures only appears inside of TLVs, it doesn't have a length prefix when
815
- // serialized. Thus, we can't use `impl_feature_len_prefixed_write`, above, and have to write our
816
- // own serialization.
817
- impl Writeable for ChannelTypeFeatures {
818
- fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
819
- self . write_be ( w)
820
- }
821
- }
822
- impl Readable for ChannelTypeFeatures {
823
- fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
824
- let v = io_extras:: read_to_end ( r) ?;
825
- Ok ( Self :: from_be_bytes ( v) )
843
+ // Some features only appear inside of TLVs, so they don't have a length prefix when serialized.
844
+ macro_rules! impl_feature_tlv_value_write {
845
+ ( $features: ident) => {
846
+ impl Writeable for $features {
847
+ fn write<W : Writer >( & self , w: & mut W ) -> Result <( ) , io:: Error > {
848
+ self . write_be( w)
849
+ }
850
+ }
851
+ impl Readable for $features {
852
+ fn read<R : io:: Read >( r: & mut R ) -> Result <Self , DecodeError > {
853
+ let v = io_extras:: read_to_end( r) ?;
854
+ Ok ( Self :: from_be_bytes( v) )
855
+ }
856
+ }
826
857
}
827
858
}
828
859
860
+ impl_feature_tlv_value_write ! ( ChannelTypeFeatures ) ;
861
+ impl_feature_tlv_value_write ! ( OfferFeatures ) ;
862
+
829
863
#[ cfg( test) ]
830
864
mod tests {
831
- use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures } ;
865
+ use super :: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , InvoiceFeatures , NodeFeatures , OfferFeatures } ;
832
866
use bitcoin:: bech32:: { Base32Len , FromBase32 , ToBase32 , u5} ;
833
867
834
868
#[ test]
@@ -1021,6 +1055,12 @@ mod tests {
1021
1055
assert_eq ! ( features, features_deserialized) ;
1022
1056
}
1023
1057
1058
+ #[ test]
1059
+ fn invoice_features_equal_offer_features ( ) {
1060
+ assert_eq ! ( InvoiceFeatures :: known( ) , OfferFeatures :: known( ) . to_context( ) ) ;
1061
+ assert_eq ! ( OfferFeatures :: known( ) , InvoiceFeatures :: known( ) . to_context( ) ) ;
1062
+ }
1063
+
1024
1064
#[ test]
1025
1065
fn test_channel_type_mapping ( ) {
1026
1066
// If we map an InvoiceFeatures with StaticRemoteKey optional, it should map into a
0 commit comments