@@ -218,10 +218,13 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
218
218
/// * `D`: exactly one [`TaggedField::Description`] or [`TaggedField::DescriptionHash`]
219
219
/// * `H`: exactly one [`TaggedField::PaymentHash`]
220
220
/// * `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
221
224
///
222
225
/// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters.
223
226
#[ 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 > {
225
228
currency : Currency ,
226
229
amount : Option < u64 > ,
227
230
si_prefix : Option < SiPrefix > ,
@@ -234,6 +237,7 @@ pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S:
234
237
phantom_t : core:: marker:: PhantomData < T > ,
235
238
phantom_c : core:: marker:: PhantomData < C > ,
236
239
phantom_s : core:: marker:: PhantomData < S > ,
240
+ phantom_m : core:: marker:: PhantomData < M > ,
237
241
}
238
242
239
243
/// Represents a syntactically and semantically correct lightning BOLT11 invoice.
@@ -442,6 +446,7 @@ pub enum TaggedField {
442
446
Fallback ( Fallback ) ,
443
447
PrivateRoute ( PrivateRoute ) ,
444
448
PaymentSecret ( PaymentSecret ) ,
449
+ PaymentMetadata ( Vec < u8 > ) ,
445
450
Features ( InvoiceFeatures ) ,
446
451
}
447
452
@@ -506,15 +511,16 @@ pub mod constants {
506
511
pub const TAG_FALLBACK : u8 = 9 ;
507
512
pub const TAG_PRIVATE_ROUTE : u8 = 3 ;
508
513
pub const TAG_PAYMENT_SECRET : u8 = 16 ;
514
+ pub const TAG_PAYMENT_METADATA : u8 = 27 ;
509
515
pub const TAG_FEATURES : u8 = 5 ;
510
516
}
511
517
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 > {
513
519
/// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
514
520
/// `InvoiceBuilder::build(self)` becomes available.
515
- pub fn new ( currrency : Currency ) -> Self {
521
+ pub fn new ( currency : Currency ) -> Self {
516
522
InvoiceBuilder {
517
- currency : currrency ,
523
+ currency,
518
524
amount : None ,
519
525
si_prefix : None ,
520
526
timestamp : None ,
@@ -526,14 +532,15 @@ impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False, tb::False> {
526
532
phantom_t : core:: marker:: PhantomData ,
527
533
phantom_c : core:: marker:: PhantomData ,
528
534
phantom_s : core:: marker:: PhantomData ,
535
+ phantom_m : core:: marker:: PhantomData ,
529
536
}
530
537
}
531
538
}
532
539
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 > {
534
541
/// 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 > {
537
544
currency : self . currency ,
538
545
amount : self . amount ,
539
546
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
546
553
phantom_t : core:: marker:: PhantomData ,
547
554
phantom_c : core:: marker:: PhantomData ,
548
555
phantom_s : core:: marker:: PhantomData ,
556
+ phantom_m : core:: marker:: PhantomData ,
549
557
}
550
558
}
551
559
@@ -590,7 +598,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
590
598
}
591
599
}
592
600
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 > {
594
602
/// Builds a [`RawInvoice`] if no [`CreationError`] occurred while construction any of the
595
603
/// fields.
596
604
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
624
632
}
625
633
}
626
634
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 > {
628
636
/// 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 > {
630
638
match Description :: new ( description) {
631
639
Ok ( d) => self . tagged_fields . push ( TaggedField :: Description ( d) ) ,
632
640
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
635
643
}
636
644
637
645
/// 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 > {
639
647
self . tagged_fields . push ( TaggedField :: DescriptionHash ( Sha256 ( description_hash) ) ) ;
640
648
self . set_flags ( )
641
649
}
642
650
643
651
/// 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 > {
645
653
match description {
646
654
InvoiceDescription :: Direct ( desc) => {
647
655
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
653
661
}
654
662
}
655
663
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 > {
657
665
/// 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 > {
659
667
self . tagged_fields . push ( TaggedField :: PaymentHash ( Sha256 ( hash) ) ) ;
660
668
self . set_flags ( )
661
669
}
662
670
}
663
671
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 > {
665
673
/// Sets the timestamp to a specific [`SystemTime`].
666
674
#[ 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 > {
668
676
match PositiveTimestamp :: from_system_time ( time) {
669
677
Ok ( t) => self . timestamp = Some ( t) ,
670
678
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
675
683
676
684
/// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which
677
685
/// 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 > {
679
687
match PositiveTimestamp :: from_duration_since_epoch ( time) {
680
688
Ok ( t) => self . timestamp = Some ( t) ,
681
689
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
686
694
687
695
/// Sets the timestamp to the current system time.
688
696
#[ 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 > {
690
698
let now = PositiveTimestamp :: from_system_time ( SystemTime :: now ( ) ) ;
691
699
self . timestamp = Some ( now. expect ( "for the foreseeable future this shouldn't happen" ) ) ;
692
700
self . set_flags ( )
693
701
}
694
702
}
695
703
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 > {
697
705
/// 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 > {
699
707
self . tagged_fields . push ( TaggedField :: MinFinalCltvExpiryDelta ( MinFinalCltvExpiryDelta ( min_final_cltv_expiry_delta) ) ) ;
700
708
self . set_flags ( )
701
709
}
702
710
}
703
711
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 > {
705
713
/// 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
+ }
710
723
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
+ }
712
730
self . set_flags ( )
713
731
}
714
732
}
715
733
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 > {
717
773
/// Sets the `basic_mpp` feature as optional.
718
774
pub fn basic_mpp ( mut self ) -> Self {
719
775
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,
725
781
}
726
782
}
727
783
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 > {
729
785
/// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
730
786
/// and MUST produce a recoverable signature valid for the given hash and if applicable also for
731
787
/// the included payee public key.
@@ -977,6 +1033,10 @@ impl RawInvoice {
977
1033
find_extract ! ( self . known_tagged_fields( ) , TaggedField :: PaymentSecret ( ref x) , x)
978
1034
}
979
1035
1036
+ pub fn payment_metadata ( & self ) -> Option < & Vec < u8 > > {
1037
+ find_extract ! ( self . known_tagged_fields( ) , TaggedField :: PaymentMetadata ( ref x) , x)
1038
+ }
1039
+
980
1040
pub fn features ( & self ) -> Option < & InvoiceFeatures > {
981
1041
find_extract ! ( self . known_tagged_fields( ) , TaggedField :: Features ( ref x) , x)
982
1042
}
@@ -1248,6 +1308,11 @@ impl Invoice {
1248
1308
self . signed_invoice . payment_secret ( ) . expect ( "was checked by constructor" )
1249
1309
}
1250
1310
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
+
1251
1316
/// Get the invoice features if they were included in the invoice
1252
1317
pub fn features ( & self ) -> Option < & InvoiceFeatures > {
1253
1318
self . signed_invoice . features ( )
@@ -1396,6 +1461,7 @@ impl TaggedField {
1396
1461
TaggedField :: Fallback ( _) => constants:: TAG_FALLBACK ,
1397
1462
TaggedField :: PrivateRoute ( _) => constants:: TAG_PRIVATE_ROUTE ,
1398
1463
TaggedField :: PaymentSecret ( _) => constants:: TAG_PAYMENT_SECRET ,
1464
+ TaggedField :: PaymentMetadata ( _) => constants:: TAG_PAYMENT_METADATA ,
1399
1465
TaggedField :: Features ( _) => constants:: TAG_FEATURES ,
1400
1466
} ;
1401
1467
0 commit comments