@@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
16
16
use crate :: blinded_path:: { BlindedHop , BlindedPath } ;
17
17
use crate :: ln:: PaymentHash ;
18
18
use crate :: ln:: channelmanager:: { ChannelDetails , PaymentId } ;
19
- use crate :: ln:: features:: { ChannelFeatures , InvoiceFeatures , NodeFeatures } ;
19
+ use crate :: ln:: features:: { Bolt12InvoiceFeatures , ChannelFeatures , InvoiceFeatures , NodeFeatures } ;
20
20
use crate :: ln:: msgs:: { DecodeError , ErrorAction , LightningError , MAX_VALUE_MSAT } ;
21
21
use crate :: offers:: invoice:: BlindedPayInfo ;
22
22
use crate :: routing:: gossip:: { DirectedChannelInfo , EffectiveCapacity , ReadOnlyNetworkGraph , NetworkGraph , NodeId , RoutingFees } ;
@@ -537,12 +537,12 @@ impl Writeable for PaymentParameters {
537
537
let mut blinded_hints = & vec ! [ ] ;
538
538
match & self . payee {
539
539
Payee :: Clear { route_hints, .. } => clear_hints = route_hints,
540
- Payee :: Blinded { route_hints } => blinded_hints = route_hints,
540
+ Payee :: Blinded { route_hints, .. } => blinded_hints = route_hints,
541
541
}
542
542
write_tlv_fields ! ( writer, {
543
543
( 0 , self . payee. node_id( ) , option) ,
544
544
( 1 , self . max_total_cltv_expiry_delta, required) ,
545
- ( 2 , if let Payee :: Clear { features , .. } = & self . payee { features } else { & None } , option) ,
545
+ ( 2 , self . payee. features( ) , option) ,
546
546
( 3 , self . max_path_count, required) ,
547
547
( 4 , * clear_hints, vec_type) ,
548
548
( 5 , self . max_channel_saturation_power_of_half, required) ,
@@ -560,7 +560,7 @@ impl ReadableArgs<u32> for PaymentParameters {
560
560
_init_and_read_tlv_fields ! ( reader, {
561
561
( 0 , payee_pubkey, option) ,
562
562
( 1 , max_total_cltv_expiry_delta, ( default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA ) ) ,
563
- ( 2 , features, option) ,
563
+ ( 2 , features, ( option: ReadableArgs , payee_pubkey . is_some ( ) ) ) ,
564
564
( 3 , max_path_count, ( default_value, DEFAULT_MAX_PATH_COUNT ) ) ,
565
565
( 4 , route_hints, vec_type) ,
566
566
( 5 , max_channel_saturation_power_of_half, ( default_value, 2 ) ) ,
@@ -573,12 +573,15 @@ impl ReadableArgs<u32> for PaymentParameters {
573
573
let blinded_route_hints = blinded_route_hints. unwrap_or ( vec ! [ ] ) ;
574
574
let payee = if blinded_route_hints. len ( ) != 0 {
575
575
if clear_route_hints. len ( ) != 0 || payee_pubkey. is_some ( ) { return Err ( DecodeError :: InvalidValue ) }
576
- Payee :: Blinded { route_hints : blinded_route_hints }
576
+ Payee :: Blinded {
577
+ route_hints : blinded_route_hints,
578
+ features : features. map ( |f : Features | f. bolt12 ( ) ) . flatten ( ) ,
579
+ }
577
580
} else {
578
581
Payee :: Clear {
579
582
route_hints : clear_route_hints,
580
583
node_id : payee_pubkey. ok_or ( DecodeError :: InvalidValue ) ?,
581
- features,
584
+ features : features . map ( |f| f . bolt11 ( ) ) . flatten ( ) ,
582
585
}
583
586
} ;
584
587
Ok ( Self {
@@ -682,6 +685,11 @@ pub enum Payee {
682
685
/// Aggregated routing info and blinded paths, for routing to the payee without knowing their
683
686
/// node id.
684
687
route_hints : Vec < ( BlindedPayInfo , BlindedPath ) > ,
688
+ /// Features supported by the payee.
689
+ ///
690
+ /// May be set from the payee's invoice. May be `None` if the invoice does not contain any
691
+ /// features.
692
+ features : Option < Bolt12InvoiceFeatures > ,
685
693
} ,
686
694
/// The recipient included these route hints in their BOLT11 invoice.
687
695
Clear {
@@ -718,6 +726,52 @@ impl Payee {
718
726
_ => false ,
719
727
}
720
728
}
729
+ fn features ( & self ) -> Option < FeaturesRef > {
730
+ match self {
731
+ Self :: Clear { features, .. } => features. as_ref ( ) . map ( |f| FeaturesRef :: Bolt11 ( f) ) ,
732
+ Self :: Blinded { features, .. } => features. as_ref ( ) . map ( |f| FeaturesRef :: Bolt12 ( f) ) ,
733
+ }
734
+ }
735
+ }
736
+
737
+ enum FeaturesRef < ' a > {
738
+ Bolt11 ( & ' a InvoiceFeatures ) ,
739
+ Bolt12 ( & ' a Bolt12InvoiceFeatures ) ,
740
+ }
741
+ enum Features {
742
+ Bolt11 ( InvoiceFeatures ) ,
743
+ Bolt12 ( Bolt12InvoiceFeatures ) ,
744
+ }
745
+
746
+ impl Features {
747
+ fn bolt12 ( self ) -> Option < Bolt12InvoiceFeatures > {
748
+ match self {
749
+ Self :: Bolt12 ( f) => Some ( f) ,
750
+ _ => None ,
751
+ }
752
+ }
753
+ fn bolt11 ( self ) -> Option < InvoiceFeatures > {
754
+ match self {
755
+ Self :: Bolt11 ( f) => Some ( f) ,
756
+ _ => None ,
757
+ }
758
+ }
759
+ }
760
+
761
+ impl < ' a > Writeable for FeaturesRef < ' a > {
762
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
763
+ match self {
764
+ Self :: Bolt11 ( f) => Ok ( f. write ( w) ?) ,
765
+ Self :: Bolt12 ( f) => Ok ( f. write ( w) ?) ,
766
+ }
767
+ }
768
+ }
769
+
770
+ impl ReadableArgs < bool > for Features {
771
+ fn read < R : io:: Read > ( reader : & mut R , bolt11 : bool ) -> Result < Self , DecodeError > {
772
+ if bolt11 { return Ok ( Self :: Bolt11 ( Readable :: read ( reader) ?) ) }
773
+ Ok ( Self :: Bolt12 ( Readable :: read ( reader) ?) )
774
+ }
721
775
}
722
776
723
777
/// A list of hops along a payment path terminating with a channel to the recipient.
0 commit comments