@@ -218,10 +218,13 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
218218/// * `D`: exactly one [`TaggedField::Description`] or [`TaggedField::DescriptionHash`]
219219/// * `H`: exactly one [`TaggedField::PaymentHash`]
220220/// * `T`: the timestamp is set
221+ /// * `C`: the CLTV expiry is set
222+ /// * `S`: the payment secret is set
223+ /// * `M`: payment metadata is set
221224///
222225/// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters.
223226#[ derive( Eq , PartialEq , Debug , Clone ) ]
224- pub struct InvoiceBuilder < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > {
227+ pub struct InvoiceBuilder < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > {
225228 currency : Currency ,
226229 amount : Option < u64 > ,
227230 si_prefix : Option < SiPrefix > ,
@@ -234,6 +237,7 @@ pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S:
234237 phantom_t : core:: marker:: PhantomData < T > ,
235238 phantom_c : core:: marker:: PhantomData < C > ,
236239 phantom_s : core:: marker:: PhantomData < S > ,
240+ phantom_m : core:: marker:: PhantomData < M > ,
237241}
238242
239243/// Represents a syntactically and semantically correct lightning BOLT11 invoice.
@@ -442,6 +446,7 @@ pub enum TaggedField {
442446 Fallback ( Fallback ) ,
443447 PrivateRoute ( PrivateRoute ) ,
444448 PaymentSecret ( PaymentSecret ) ,
449+ PaymentMetadata ( Vec < u8 > ) ,
445450 Features ( InvoiceFeatures ) ,
446451}
447452
@@ -506,15 +511,16 @@ pub mod constants {
506511 pub const TAG_FALLBACK : u8 = 9 ;
507512 pub const TAG_PRIVATE_ROUTE : u8 = 3 ;
508513 pub const TAG_PAYMENT_SECRET : u8 = 16 ;
514+ pub const TAG_PAYMENT_METADATA : u8 = 27 ;
509515 pub const TAG_FEATURES : u8 = 5 ;
510516}
511517
512- impl InvoiceBuilder < tb:: False , tb:: False , tb:: False , tb:: False , tb:: False > {
518+ impl InvoiceBuilder < tb:: False , tb:: False , tb:: False , tb:: False , tb:: False , tb :: False > {
513519 /// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
514520 /// `InvoiceBuilder::build(self)` becomes available.
515- pub fn new ( currrency : Currency ) -> Self {
521+ pub fn new ( currency : Currency ) -> Self {
516522 InvoiceBuilder {
517- currency : currrency ,
523+ currency,
518524 amount : None ,
519525 si_prefix : None ,
520526 timestamp : None ,
@@ -526,14 +532,15 @@ impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False, tb::False> {
526532 phantom_t : core:: marker:: PhantomData ,
527533 phantom_c : core:: marker:: PhantomData ,
528534 phantom_s : core:: marker:: PhantomData ,
535+ phantom_m : core:: marker:: PhantomData ,
529536 }
530537 }
531538}
532539
533- impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , T , C , S > {
540+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , H , T , C , S , M > {
534541 /// Helper function to set the completeness flags.
535- fn set_flags < DN : tb:: Bool , HN : tb:: Bool , TN : tb:: Bool , CN : tb:: Bool , SN : tb:: Bool > ( self ) -> InvoiceBuilder < DN , HN , TN , CN , SN > {
536- InvoiceBuilder :: < DN , HN , TN , CN , SN > {
542+ fn set_flags < DN : tb:: Bool , HN : tb:: Bool , TN : tb:: Bool , CN : tb:: Bool , SN : tb:: Bool , MN : tb :: Bool > ( self ) -> InvoiceBuilder < DN , HN , TN , CN , SN , MN > {
543+ InvoiceBuilder :: < DN , HN , TN , CN , SN , MN > {
537544 currency : self . currency ,
538545 amount : self . amount ,
539546 si_prefix : self . si_prefix ,
@@ -546,6 +553,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
546553 phantom_t : core:: marker:: PhantomData ,
547554 phantom_c : core:: marker:: PhantomData ,
548555 phantom_s : core:: marker:: PhantomData ,
556+ phantom_m : core:: marker:: PhantomData ,
549557 }
550558 }
551559
@@ -590,7 +598,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
590598 }
591599}
592600
593- impl < D : tb:: Bool , H : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , tb:: True , C , S > {
601+ impl < D : tb:: Bool , H : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , H , tb:: True , C , S , M > {
594602 /// Builds a [`RawInvoice`] if no [`CreationError`] occurred while construction any of the
595603 /// fields.
596604 pub fn build_raw ( self ) -> Result < RawInvoice , CreationError > {
@@ -624,9 +632,9 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
624632 }
625633}
626634
627- impl < H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < tb:: False , H , T , C , S > {
635+ impl < H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < tb:: False , H , T , C , S , M > {
628636 /// Set the description. This function is only available if no description (hash) was set.
629- pub fn description ( mut self , description : String ) -> InvoiceBuilder < tb:: True , H , T , C , S > {
637+ pub fn description ( mut self , description : String ) -> InvoiceBuilder < tb:: True , H , T , C , S , M > {
630638 match Description :: new ( description) {
631639 Ok ( d) => self . tagged_fields . push ( TaggedField :: Description ( d) ) ,
632640 Err ( e) => self . error = Some ( e) ,
@@ -635,13 +643,13 @@ impl<H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<tb::Fals
635643 }
636644
637645 /// Set the description hash. This function is only available if no description (hash) was set.
638- pub fn description_hash ( mut self , description_hash : sha256:: Hash ) -> InvoiceBuilder < tb:: True , H , T , C , S > {
646+ pub fn description_hash ( mut self , description_hash : sha256:: Hash ) -> InvoiceBuilder < tb:: True , H , T , C , S , M > {
639647 self . tagged_fields . push ( TaggedField :: DescriptionHash ( Sha256 ( description_hash) ) ) ;
640648 self . set_flags ( )
641649 }
642650
643651 /// Set the description or description hash. This function is only available if no description (hash) was set.
644- pub fn invoice_description ( self , description : InvoiceDescription ) -> InvoiceBuilder < tb:: True , H , T , C , S > {
652+ pub fn invoice_description ( self , description : InvoiceDescription ) -> InvoiceBuilder < tb:: True , H , T , C , S , M > {
645653 match description {
646654 InvoiceDescription :: Direct ( desc) => {
647655 self . description ( desc. clone ( ) . into_inner ( ) )
@@ -653,18 +661,18 @@ impl<H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<tb::Fals
653661 }
654662}
655663
656- impl < D : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , tb:: False , T , C , S > {
664+ impl < D : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , tb:: False , T , C , S , M > {
657665 /// Set the payment hash. This function is only available if no payment hash was set.
658- pub fn payment_hash ( mut self , hash : sha256:: Hash ) -> InvoiceBuilder < D , tb:: True , T , C , S > {
666+ pub fn payment_hash ( mut self , hash : sha256:: Hash ) -> InvoiceBuilder < D , tb:: True , T , C , S , M > {
659667 self . tagged_fields . push ( TaggedField :: PaymentHash ( Sha256 ( hash) ) ) ;
660668 self . set_flags ( )
661669 }
662670}
663671
664- impl < D : tb:: Bool , H : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , tb:: False , C , S > {
672+ impl < D : tb:: Bool , H : tb:: Bool , C : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , H , tb:: False , C , S , M > {
665673 /// Sets the timestamp to a specific [`SystemTime`].
666674 #[ cfg( feature = "std" ) ]
667- pub fn timestamp ( mut self , time : SystemTime ) -> InvoiceBuilder < D , H , tb:: True , C , S > {
675+ pub fn timestamp ( mut self , time : SystemTime ) -> InvoiceBuilder < D , H , tb:: True , C , S , M > {
668676 match PositiveTimestamp :: from_system_time ( time) {
669677 Ok ( t) => self . timestamp = Some ( t) ,
670678 Err ( e) => self . error = Some ( e) ,
@@ -675,7 +683,7 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
675683
676684 /// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which
677685 /// is not representable in BOLT 11 invoices).
678- pub fn duration_since_epoch ( mut self , time : Duration ) -> InvoiceBuilder < D , H , tb:: True , C , S > {
686+ pub fn duration_since_epoch ( mut self , time : Duration ) -> InvoiceBuilder < D , H , tb:: True , C , S , M > {
679687 match PositiveTimestamp :: from_duration_since_epoch ( time) {
680688 Ok ( t) => self . timestamp = Some ( t) ,
681689 Err ( e) => self . error = Some ( e) ,
@@ -686,34 +694,82 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
686694
687695 /// Sets the timestamp to the current system time.
688696 #[ cfg( feature = "std" ) ]
689- pub fn current_timestamp ( mut self ) -> InvoiceBuilder < D , H , tb:: True , C , S > {
697+ pub fn current_timestamp ( mut self ) -> InvoiceBuilder < D , H , tb:: True , C , S , M > {
690698 let now = PositiveTimestamp :: from_system_time ( SystemTime :: now ( ) ) ;
691699 self . timestamp = Some ( now. expect ( "for the foreseeable future this shouldn't happen" ) ) ;
692700 self . set_flags ( )
693701 }
694702}
695703
696- impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , T , tb:: False , S > {
704+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , S : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , H , T , tb:: False , S , M > {
697705 /// Sets `min_final_cltv_expiry_delta`.
698- pub fn min_final_cltv_expiry_delta ( mut self , min_final_cltv_expiry_delta : u64 ) -> InvoiceBuilder < D , H , T , tb:: True , S > {
706+ pub fn min_final_cltv_expiry_delta ( mut self , min_final_cltv_expiry_delta : u64 ) -> InvoiceBuilder < D , H , T , tb:: True , S , M > {
699707 self . tagged_fields . push ( TaggedField :: MinFinalCltvExpiryDelta ( MinFinalCltvExpiryDelta ( min_final_cltv_expiry_delta) ) ) ;
700708 self . set_flags ( )
701709 }
702710}
703711
704- impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool > InvoiceBuilder < D , H , T , C , tb:: False > {
712+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , M : tb :: Bool > InvoiceBuilder < D , H , T , C , tb:: False , M > {
705713 /// Sets the payment secret and relevant features.
706- pub fn payment_secret ( mut self , payment_secret : PaymentSecret ) -> InvoiceBuilder < D , H , T , C , tb:: True > {
707- let mut features = InvoiceFeatures :: empty ( ) ;
708- features. set_variable_length_onion_required ( ) ;
709- features. set_payment_secret_required ( ) ;
714+ pub fn payment_secret ( mut self , payment_secret : PaymentSecret ) -> InvoiceBuilder < D , H , T , C , tb:: True , M > {
715+ let mut found_features = false ;
716+ for field in self . tagged_fields . iter_mut ( ) {
717+ if let TaggedField :: Features ( f) = field {
718+ found_features = true ;
719+ f. set_variable_length_onion_required ( ) ;
720+ f. set_payment_secret_required ( ) ;
721+ }
722+ }
710723 self . tagged_fields . push ( TaggedField :: PaymentSecret ( payment_secret) ) ;
711- self . tagged_fields . push ( TaggedField :: Features ( features) ) ;
724+ if !found_features {
725+ let mut features = InvoiceFeatures :: empty ( ) ;
726+ features. set_variable_length_onion_required ( ) ;
727+ features. set_payment_secret_required ( ) ;
728+ self . tagged_fields . push ( TaggedField :: Features ( features) ) ;
729+ }
712730 self . set_flags ( )
713731 }
714732}
715733
716- impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool > InvoiceBuilder < D , H , T , C , tb:: True > {
734+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , T , C , S , tb:: False > {
735+ /// Sets the payment metadata.
736+ ///
737+ /// By default features are set to *optionally* allow the sender to include the payment metadata.
738+ /// If you wish to require that the sender include the metadata (and fail to parse the invoice if
739+ /// they don't support payment metadata fields), you need to call
740+ /// [`InvoiceBuilder::require_payment_metadata`] after this.
741+ pub fn payment_metadata ( mut self , payment_metadata : Vec < u8 > ) -> InvoiceBuilder < D , H , T , C , S , tb:: True > {
742+ self . tagged_fields . push ( TaggedField :: PaymentMetadata ( payment_metadata) ) ;
743+ let mut found_features = false ;
744+ for field in self . tagged_fields . iter_mut ( ) {
745+ if let TaggedField :: Features ( f) = field {
746+ found_features = true ;
747+ f. set_payment_metadata_optional ( ) ;
748+ }
749+ }
750+ if !found_features {
751+ let mut features = InvoiceFeatures :: empty ( ) ;
752+ features. set_payment_metadata_optional ( ) ;
753+ self . tagged_fields . push ( TaggedField :: Features ( features) ) ;
754+ }
755+ self . set_flags ( )
756+ }
757+ }
758+
759+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , S : tb:: Bool > InvoiceBuilder < D , H , T , C , S , tb:: True > {
760+ /// Sets forwarding of payment metadata as required. A reader of the invoice which does not
761+ /// support sending payment metadata will fail to read the invoice.
762+ pub fn require_payment_metadata ( mut self ) -> InvoiceBuilder < D , H , T , C , S , tb:: True > {
763+ for field in self . tagged_fields . iter_mut ( ) {
764+ if let TaggedField :: Features ( f) = field {
765+ f. set_payment_metadata_required ( ) ;
766+ }
767+ }
768+ self
769+ }
770+ }
771+
772+ impl < D : tb:: Bool , H : tb:: Bool , T : tb:: Bool , C : tb:: Bool , M : tb:: Bool > InvoiceBuilder < D , H , T , C , tb:: True , M > {
717773 /// Sets the `basic_mpp` feature as optional.
718774 pub fn basic_mpp ( mut self ) -> Self {
719775 for field in self . tagged_fields . iter_mut ( ) {
@@ -725,7 +781,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, T,
725781 }
726782}
727783
728- impl InvoiceBuilder < tb:: True , tb:: True , tb:: True , tb:: True , tb:: True > {
784+ impl < M : tb :: Bool > InvoiceBuilder < tb:: True , tb:: True , tb:: True , tb:: True , tb:: True , M > {
729785 /// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
730786 /// and MUST produce a recoverable signature valid for the given hash and if applicable also for
731787 /// the included payee public key.
@@ -977,6 +1033,10 @@ impl RawInvoice {
9771033 find_extract ! ( self . known_tagged_fields( ) , TaggedField :: PaymentSecret ( ref x) , x)
9781034 }
9791035
1036+ pub fn payment_metadata ( & self ) -> Option < & Vec < u8 > > {
1037+ find_extract ! ( self . known_tagged_fields( ) , TaggedField :: PaymentMetadata ( ref x) , x)
1038+ }
1039+
9801040 pub fn features ( & self ) -> Option < & InvoiceFeatures > {
9811041 find_extract ! ( self . known_tagged_fields( ) , TaggedField :: Features ( ref x) , x)
9821042 }
@@ -1248,6 +1308,11 @@ impl Invoice {
12481308 self . signed_invoice . payment_secret ( ) . expect ( "was checked by constructor" )
12491309 }
12501310
1311+ /// Get the payment metadata blob if one was included in the invoice
1312+ pub fn payment_metadata ( & self ) -> Option < & Vec < u8 > > {
1313+ self . signed_invoice . payment_metadata ( )
1314+ }
1315+
12511316 /// Get the invoice features if they were included in the invoice
12521317 pub fn features ( & self ) -> Option < & InvoiceFeatures > {
12531318 self . signed_invoice . features ( )
@@ -1396,6 +1461,7 @@ impl TaggedField {
13961461 TaggedField :: Fallback ( _) => constants:: TAG_FALLBACK ,
13971462 TaggedField :: PrivateRoute ( _) => constants:: TAG_PRIVATE_ROUTE ,
13981463 TaggedField :: PaymentSecret ( _) => constants:: TAG_PAYMENT_SECRET ,
1464+ TaggedField :: PaymentMetadata ( _) => constants:: TAG_PAYMENT_METADATA ,
13991465 TaggedField :: Features ( _) => constants:: TAG_FEATURES ,
14001466 } ;
14011467
0 commit comments