@@ -677,6 +677,54 @@ pub enum ProbeSendFailure {
677677 DuplicateProbe ,
678678}
679679
680+ /// A validated, sorted set of custom TLVs for payment recipient onion fields.
681+ #[ derive( Clone ) ]
682+ pub struct RecipientCustomTlvs ( Vec < ( u64 , Vec < u8 > ) > ) ;
683+
684+ impl RecipientCustomTlvs {
685+ /// Each TLV is provided as a `(u64, Vec<u8>)` for the type number and
686+ /// serialized value respectively. TLV type numbers must be unique and
687+ /// within the range reserved for custom types, i.e. >= 2^16, otherwise
688+ /// this method will return `Err(())`.
689+ ///
690+ /// This method will also error for TLV types in the experimental range
691+ /// which have since been standardized within the protocol. This currently
692+ /// includes 5482373484 (keysend) and 77_777 (invoice requests for async
693+ /// payments).
694+ pub fn new ( mut tlvs : Vec < ( u64 , Vec < u8 > ) > ) -> Result < Self , ( ) > {
695+ tlvs. sort_unstable_by_key ( |( typ, _) | * typ) ;
696+ let mut prev_type = None ;
697+ for ( typ, _) in tlvs. iter ( ) {
698+ if * typ < 1 << 16 {
699+ return Err ( ( ) ) ;
700+ }
701+ if * typ == 5482373484 {
702+ return Err ( ( ) ) ;
703+ } // keysend
704+ if * typ == 77_777 {
705+ return Err ( ( ) ) ;
706+ } // invoice requests for async payments
707+ match prev_type {
708+ Some ( prev) if prev >= * typ => return Err ( ( ) ) ,
709+ _ => { } ,
710+ }
711+ prev_type = Some ( * typ) ;
712+ }
713+
714+ Ok ( Self ( tlvs) )
715+ }
716+
717+ /// Returns the inner TLV list.
718+ pub ( super ) fn into_inner ( self ) -> Vec < ( u64 , Vec < u8 > ) > {
719+ self . 0
720+ }
721+
722+ /// Borrow the inner TLV list.
723+ pub fn as_slice ( & self ) -> & [ ( u64 , Vec < u8 > ) ] {
724+ & self . 0
725+ }
726+ }
727+
680728/// Information which is provided, encrypted, to the payment recipient when sending HTLCs.
681729///
682730/// This should generally be constructed with data communicated to us from the recipient (via a
@@ -739,31 +787,13 @@ impl RecipientOnionFields {
739787 Self { payment_secret : None , payment_metadata : None , custom_tlvs : Vec :: new ( ) }
740788 }
741789
742- /// Creates a new [`RecipientOnionFields`] from an existing one, adding custom TLVs. Each
743- /// TLV is provided as a `(u64, Vec<u8>)` for the type number and serialized value
744- /// respectively. TLV type numbers must be unique and within the range
745- /// reserved for custom types, i.e. >= 2^16, otherwise this method will return `Err(())`.
746- ///
747- /// This method will also error for types in the experimental range which have been
748- /// standardized within the protocol, which only includes 5482373484 (keysend) for now.
790+ /// Creates a new [`RecipientOnionFields`] from an existing one, adding validated custom TLVs.
749791 ///
750792 /// See [`Self::custom_tlvs`] for more info.
751793 #[ rustfmt:: skip]
752- pub fn with_custom_tlvs ( mut self , mut custom_tlvs : Vec < ( u64 , Vec < u8 > ) > ) -> Result < Self , ( ) > {
753- custom_tlvs. sort_unstable_by_key ( |( typ, _) | * typ) ;
754- let mut prev_type = None ;
755- for ( typ, _) in custom_tlvs. iter ( ) {
756- if * typ < 1 << 16 { return Err ( ( ) ) ; }
757- if * typ == 5482373484 { return Err ( ( ) ) ; } // keysend
758- if * typ == 77_777 { return Err ( ( ) ) ; } // invoice requests for async payments
759- match prev_type {
760- Some ( prev) if prev >= * typ => return Err ( ( ) ) ,
761- _ => { } ,
762- }
763- prev_type = Some ( * typ) ;
764- }
765- self . custom_tlvs = custom_tlvs;
766- Ok ( self )
794+ pub fn with_custom_tlvs ( mut self , custom_tlvs : RecipientCustomTlvs ) -> Self {
795+ self . custom_tlvs = custom_tlvs. into_inner ( ) ;
796+ self
767797 }
768798
769799 /// Gets the custom TLVs that will be sent or have been received.
@@ -2815,8 +2845,8 @@ mod tests {
28152845 use crate :: ln:: channelmanager:: { PaymentId , RecipientOnionFields } ;
28162846 use crate :: ln:: inbound_payment:: ExpandedKey ;
28172847 use crate :: ln:: outbound_payment:: {
2818- Bolt12PaymentError , OutboundPayments , PendingOutboundPayment , Retry , RetryableSendFailure ,
2819- StaleExpiration ,
2848+ Bolt12PaymentError , OutboundPayments , PendingOutboundPayment , RecipientCustomTlvs , Retry ,
2849+ RetryableSendFailure , StaleExpiration ,
28202850 } ;
28212851 #[ cfg( feature = "std" ) ]
28222852 use crate :: offers:: invoice:: DEFAULT_RELATIVE_EXPIRY ;
@@ -2843,22 +2873,23 @@ mod tests {
28432873 fn test_recipient_onion_fields_with_custom_tlvs ( ) {
28442874 let onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
28452875
2846- let bad_type_range_tlvs = vec ! [
2876+ let bad_type_range_tlvs = RecipientCustomTlvs :: new ( vec ! [
28472877 ( 0 , vec![ 42 ] ) ,
28482878 ( 1 , vec![ 42 ; 32 ] ) ,
2849- ] ;
2850- assert ! ( onion_fields . clone ( ) . with_custom_tlvs ( bad_type_range_tlvs) . is_err( ) ) ;
2879+ ] ) ;
2880+ assert ! ( bad_type_range_tlvs. is_err( ) ) ;
28512881
2852- let keysend_tlv = vec ! [
2882+ let keysend_tlv = RecipientCustomTlvs :: new ( vec ! [
28532883 ( 5482373484 , vec![ 42 ; 32 ] ) ,
2854- ] ;
2855- assert ! ( onion_fields . clone ( ) . with_custom_tlvs ( keysend_tlv) . is_err( ) ) ;
2884+ ] ) ;
2885+ assert ! ( keysend_tlv. is_err( ) ) ;
28562886
2857- let good_tlvs = vec ! [
2887+ let good_tlvs = RecipientCustomTlvs :: new ( vec ! [
28582888 ( ( 1 << 16 ) + 1 , vec![ 42 ] ) ,
28592889 ( ( 1 << 16 ) + 3 , vec![ 42 ; 32 ] ) ,
2860- ] ;
2861- assert ! ( onion_fields. with_custom_tlvs( good_tlvs) . is_ok( ) ) ;
2890+ ] ) ;
2891+ assert ! ( good_tlvs. is_ok( ) ) ;
2892+ onion_fields. with_custom_tlvs ( good_tlvs. unwrap ( ) ) ;
28622893 }
28632894
28642895 #[ test]
0 commit comments