@@ -634,7 +634,7 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, T,
634
634
}
635
635
}
636
636
637
- impl < S : tb :: Bool > InvoiceBuilder < tb:: True , tb:: True , tb:: True , tb:: True , S > {
637
+ impl InvoiceBuilder < tb:: True , tb:: True , tb:: True , tb:: True , tb :: True > {
638
638
/// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
639
639
/// and MUST produce a recoverable signature valid for the given hash and if applicable also for
640
640
/// the included payee public key.
@@ -1018,6 +1018,17 @@ impl Invoice {
1018
1018
return Err ( SemanticError :: MultipleDescriptions ) ;
1019
1019
}
1020
1020
1021
+ // "A writer MUST include exactly one `s` field."
1022
+ let payment_secret_count = self . tagged_fields ( ) . filter ( |& tf| match * tf {
1023
+ TaggedField :: PaymentSecret ( _) => true ,
1024
+ _ => false ,
1025
+ } ) . count ( ) ;
1026
+ if payment_secret_count < 1 {
1027
+ return Err ( SemanticError :: NoPaymentSecret ) ;
1028
+ } else if payment_secret_count > 1 {
1029
+ return Err ( SemanticError :: MultiplePaymentSecrets ) ;
1030
+ }
1031
+
1021
1032
Ok ( ( ) )
1022
1033
}
1023
1034
@@ -1033,32 +1044,30 @@ impl Invoice {
1033
1044
1034
1045
/// Check that feature bits are set as required
1035
1046
fn check_feature_bits ( & self ) -> Result < ( ) , SemanticError > {
1036
- // "If the payment_secret feature is set, MUST include exactly one s field."
1047
+ // "A writer MUST include exactly one `s` field."
1037
1048
let payment_secret_count = self . tagged_fields ( ) . filter ( |& tf| match * tf {
1038
1049
TaggedField :: PaymentSecret ( _) => true ,
1039
1050
_ => false ,
1040
1051
} ) . count ( ) ;
1041
- if payment_secret_count > 1 {
1052
+ if payment_secret_count < 1 {
1053
+ return Err ( SemanticError :: NoPaymentSecret ) ;
1054
+ } else if payment_secret_count > 1 {
1042
1055
return Err ( SemanticError :: MultiplePaymentSecrets ) ;
1043
1056
}
1044
1057
1045
1058
// "A writer MUST set an s field if and only if the payment_secret feature is set."
1046
- let has_payment_secret = payment_secret_count == 1 ;
1059
+ // (this requirement has been since removed, and we now require the payment secret
1060
+ // feature bit always).
1047
1061
let features = self . tagged_fields ( ) . find ( |& tf| match * tf {
1048
1062
TaggedField :: Features ( _) => true ,
1049
1063
_ => false ,
1050
1064
} ) ;
1051
1065
match features {
1052
- None if has_payment_secret => Err ( SemanticError :: InvalidFeatures ) ,
1053
- None => Ok ( ( ) ) ,
1066
+ None => Err ( SemanticError :: InvalidFeatures ) ,
1054
1067
Some ( TaggedField :: Features ( features) ) => {
1055
1068
if features. requires_unknown_bits ( ) {
1056
1069
Err ( SemanticError :: InvalidFeatures )
1057
- } else if features. supports_payment_secret ( ) && has_payment_secret {
1058
- Ok ( ( ) )
1059
- } else if has_payment_secret {
1060
- Err ( SemanticError :: InvalidFeatures )
1061
- } else if features. supports_payment_secret ( ) {
1070
+ } else if !features. supports_payment_secret ( ) {
1062
1071
Err ( SemanticError :: InvalidFeatures )
1063
1072
} else {
1064
1073
Ok ( ( ) )
@@ -1147,8 +1156,8 @@ impl Invoice {
1147
1156
}
1148
1157
1149
1158
/// Get the payment secret if one was included in the invoice
1150
- pub fn payment_secret ( & self ) -> Option < & PaymentSecret > {
1151
- self . signed_invoice . payment_secret ( )
1159
+ pub fn payment_secret ( & self ) -> & PaymentSecret {
1160
+ self . signed_invoice . payment_secret ( ) . expect ( "was checked by constructor" )
1152
1161
}
1153
1162
1154
1163
/// Get the invoice features if they were included in the invoice
@@ -1405,6 +1414,10 @@ pub enum SemanticError {
1405
1414
/// The invoice contains multiple descriptions and/or description hashes which isn't allowed
1406
1415
MultipleDescriptions ,
1407
1416
1417
+ /// The invoice is missing the mandatory payment secret, which all modern lightning nodes
1418
+ /// should provide.
1419
+ NoPaymentSecret ,
1420
+
1408
1421
/// The invoice contains multiple payment secrets
1409
1422
MultiplePaymentSecrets ,
1410
1423
@@ -1428,6 +1441,7 @@ impl Display for SemanticError {
1428
1441
SemanticError :: MultiplePaymentHashes => f. write_str ( "The invoice has multiple payment hashes which isn't allowed" ) ,
1429
1442
SemanticError :: NoDescription => f. write_str ( "No description or description hash are part of the invoice" ) ,
1430
1443
SemanticError :: MultipleDescriptions => f. write_str ( "The invoice contains multiple descriptions and/or description hashes which isn't allowed" ) ,
1444
+ SemanticError :: NoPaymentSecret => f. write_str ( "The invoice is missing the mandatory payment secret" ) ,
1431
1445
SemanticError :: MultiplePaymentSecrets => f. write_str ( "The invoice contains multiple payment secrets" ) ,
1432
1446
SemanticError :: InvalidFeatures => f. write_str ( "The invoice's features are invalid" ) ,
1433
1447
SemanticError :: InvalidRecoveryId => f. write_str ( "The recovery id doesn't fit the signature/pub key" ) ,
@@ -1644,23 +1658,23 @@ mod test {
1644
1658
let invoice = invoice_template. clone ( ) ;
1645
1659
invoice. sign :: < _ , ( ) > ( |hash| Ok ( Secp256k1 :: new ( ) . sign_recoverable ( hash, & private_key) ) )
1646
1660
} . unwrap ( ) ;
1647
- assert ! ( Invoice :: from_signed( invoice) . is_ok ( ) ) ;
1661
+ assert_eq ! ( Invoice :: from_signed( invoice) , Err ( SemanticError :: NoPaymentSecret ) ) ;
1648
1662
1649
1663
// No payment secret or feature bits
1650
1664
let invoice = {
1651
1665
let mut invoice = invoice_template. clone ( ) ;
1652
1666
invoice. data . tagged_fields . push ( Features ( InvoiceFeatures :: empty ( ) ) . into ( ) ) ;
1653
1667
invoice. sign :: < _ , ( ) > ( |hash| Ok ( Secp256k1 :: new ( ) . sign_recoverable ( hash, & private_key) ) )
1654
1668
} . unwrap ( ) ;
1655
- assert ! ( Invoice :: from_signed( invoice) . is_ok ( ) ) ;
1669
+ assert_eq ! ( Invoice :: from_signed( invoice) , Err ( SemanticError :: NoPaymentSecret ) ) ;
1656
1670
1657
1671
// Missing payment secret
1658
1672
let invoice = {
1659
1673
let mut invoice = invoice_template. clone ( ) ;
1660
1674
invoice. data . tagged_fields . push ( Features ( InvoiceFeatures :: known ( ) ) . into ( ) ) ;
1661
1675
invoice. sign :: < _ , ( ) > ( |hash| Ok ( Secp256k1 :: new ( ) . sign_recoverable ( hash, & private_key) ) )
1662
1676
} . unwrap ( ) ;
1663
- assert_eq ! ( Invoice :: from_signed( invoice) , Err ( SemanticError :: InvalidFeatures ) ) ;
1677
+ assert_eq ! ( Invoice :: from_signed( invoice) , Err ( SemanticError :: NoPaymentSecret ) ) ;
1664
1678
1665
1679
// Multiple payment secrets
1666
1680
let invoice = {
@@ -1746,6 +1760,7 @@ mod test {
1746
1760
1747
1761
let sign_error_res = builder. clone ( )
1748
1762
. description ( "Test" . into ( ) )
1763
+ . payment_secret ( PaymentSecret ( [ 0 ; 32 ] ) )
1749
1764
. try_build_signed ( |_| {
1750
1765
Err ( "ImaginaryError" )
1751
1766
} ) ;
@@ -1858,7 +1873,7 @@ mod test {
1858
1873
InvoiceDescription :: Hash ( & Sha256 ( sha256:: Hash :: from_slice( & [ 3 ; 32 ] [ ..] ) . unwrap( ) ) )
1859
1874
) ;
1860
1875
assert_eq ! ( invoice. payment_hash( ) , & sha256:: Hash :: from_slice( & [ 21 ; 32 ] [ ..] ) . unwrap( ) ) ;
1861
- assert_eq ! ( invoice. payment_secret( ) , Some ( & PaymentSecret ( [ 42 ; 32 ] ) ) ) ;
1876
+ assert_eq ! ( invoice. payment_secret( ) , & PaymentSecret ( [ 42 ; 32 ] ) ) ;
1862
1877
assert_eq ! ( invoice. features( ) , Some ( & InvoiceFeatures :: known( ) ) ) ;
1863
1878
1864
1879
let raw_invoice = builder. build_raw ( ) . unwrap ( ) ;
@@ -1874,6 +1889,7 @@ mod test {
1874
1889
let signed_invoice = InvoiceBuilder :: new ( Currency :: Bitcoin )
1875
1890
. description ( "Test" . into ( ) )
1876
1891
. payment_hash ( sha256:: Hash :: from_slice ( & [ 0 ; 32 ] [ ..] ) . unwrap ( ) )
1892
+ . payment_secret ( PaymentSecret ( [ 0 ; 32 ] ) )
1877
1893
. current_timestamp ( )
1878
1894
. build_raw ( )
1879
1895
. unwrap ( )
0 commit comments