@@ -180,6 +180,30 @@ impl<'a> InvoiceRequestBuilder<'a> {
180
180
}
181
181
}
182
182
183
+ #[ cfg( test) ]
184
+ impl < ' a > InvoiceRequestBuilder < ' a > {
185
+ fn chain_unchecked ( mut self , network : Network ) -> Self {
186
+ let chain = ChainHash :: using_genesis_block ( network) ;
187
+ self . invoice_request . chain = Some ( chain) ;
188
+ self
189
+ }
190
+
191
+ fn amount_msats_unchecked ( mut self , amount_msats : u64 ) -> Self {
192
+ self . invoice_request . amount_msats = Some ( amount_msats) ;
193
+ self
194
+ }
195
+
196
+ fn quantity_unchecked ( mut self , quantity : u64 ) -> Self {
197
+ self . invoice_request . quantity = Some ( quantity) ;
198
+ self
199
+ }
200
+
201
+ fn build_unchecked ( self ) -> UnsignedInvoiceRequest < ' a > {
202
+ let InvoiceRequestBuilder { offer, invoice_request } = self ;
203
+ UnsignedInvoiceRequest { offer, invoice_request }
204
+ }
205
+ }
206
+
183
207
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
184
208
pub struct UnsignedInvoiceRequest < ' a > {
185
209
offer : & ' a Offer ,
@@ -464,7 +488,7 @@ mod tests {
464
488
use crate :: ln:: features:: InvoiceRequestFeatures ;
465
489
use crate :: ln:: msgs:: { DecodeError , MAX_VALUE_MSAT } ;
466
490
use crate :: offers:: merkle:: SignError ;
467
- use crate :: offers:: offer:: { OfferBuilder , Quantity } ;
491
+ use crate :: offers:: offer:: { Amount , OfferBuilder , Quantity } ;
468
492
use crate :: offers:: parse:: { ParseError , SemanticError } ;
469
493
use crate :: util:: ser:: { BigSize , Writeable } ;
470
494
use crate :: util:: string:: PrintableString ;
@@ -894,6 +918,342 @@ mod tests {
894
918
}
895
919
}
896
920
921
+ #[ test]
922
+ fn parses_invoice_request_with_metadata ( ) {
923
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
924
+ . amount_msats ( 1000 )
925
+ . build ( ) . unwrap ( )
926
+ . request_invoice ( vec ! [ 42 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
927
+ . build ( ) . unwrap ( )
928
+ . sign ( payer_sign) . unwrap ( ) ;
929
+
930
+ let mut buffer = Vec :: new ( ) ;
931
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
932
+
933
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
934
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
935
+ }
936
+ }
937
+
938
+ #[ test]
939
+ fn parses_invoice_request_with_chain ( ) {
940
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
941
+ . amount_msats ( 1000 )
942
+ . build ( ) . unwrap ( )
943
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
944
+ . chain ( Network :: Bitcoin ) . unwrap ( )
945
+ . build ( ) . unwrap ( )
946
+ . sign ( payer_sign) . unwrap ( ) ;
947
+
948
+ let mut buffer = Vec :: new ( ) ;
949
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
950
+
951
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
952
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
953
+ }
954
+
955
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
956
+ . amount_msats ( 1000 )
957
+ . build ( ) . unwrap ( )
958
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
959
+ . chain_unchecked ( Network :: Testnet )
960
+ . build_unchecked ( )
961
+ . sign ( payer_sign) . unwrap ( ) ;
962
+
963
+ let mut buffer = Vec :: new ( ) ;
964
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
965
+
966
+ match InvoiceRequest :: try_from ( buffer) {
967
+ Ok ( _) => panic ! ( "expected error" ) ,
968
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedChain ) ) ,
969
+ }
970
+ }
971
+
972
+ #[ test]
973
+ fn parses_invoice_request_with_amount ( ) {
974
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
975
+ . amount_msats ( 1000 )
976
+ . build ( ) . unwrap ( )
977
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
978
+ . build ( ) . unwrap ( )
979
+ . sign ( payer_sign) . unwrap ( ) ;
980
+
981
+ let mut buffer = Vec :: new ( ) ;
982
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
983
+
984
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
985
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
986
+ }
987
+
988
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
989
+ . build ( ) . unwrap ( )
990
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
991
+ . amount_msats ( 1000 ) . unwrap ( )
992
+ . build ( ) . unwrap ( )
993
+ . sign ( payer_sign) . unwrap ( ) ;
994
+
995
+ let mut buffer = Vec :: new ( ) ;
996
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
997
+
998
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
999
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1000
+ }
1001
+
1002
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1003
+ . build ( ) . unwrap ( )
1004
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1005
+ . build_unchecked ( )
1006
+ . sign ( payer_sign) . unwrap ( ) ;
1007
+
1008
+ let mut buffer = Vec :: new ( ) ;
1009
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1010
+
1011
+ match InvoiceRequest :: try_from ( buffer) {
1012
+ Ok ( _) => panic ! ( "expected error" ) ,
1013
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingAmount ) ) ,
1014
+ }
1015
+
1016
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1017
+ . amount_msats ( 1000 )
1018
+ . build ( ) . unwrap ( )
1019
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1020
+ . amount_msats_unchecked ( 999 )
1021
+ . build_unchecked ( )
1022
+ . sign ( payer_sign) . unwrap ( ) ;
1023
+
1024
+ let mut buffer = Vec :: new ( ) ;
1025
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1026
+
1027
+ match InvoiceRequest :: try_from ( buffer) {
1028
+ Ok ( _) => panic ! ( "expected error" ) ,
1029
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InsufficientAmount ) ) ,
1030
+ }
1031
+
1032
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1033
+ . amount ( Amount :: Currency { iso4217_code : * b"USD" , amount : 1000 } )
1034
+ . build_unchecked ( )
1035
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1036
+ . build_unchecked ( )
1037
+ . sign ( payer_sign) . unwrap ( ) ;
1038
+
1039
+ let mut buffer = Vec :: new ( ) ;
1040
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1041
+
1042
+ match InvoiceRequest :: try_from ( buffer) {
1043
+ Ok ( _) => panic ! ( "expected error" ) ,
1044
+ Err ( e) => {
1045
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedCurrency ) ) ;
1046
+ } ,
1047
+ }
1048
+ }
1049
+
1050
+ #[ test]
1051
+ fn parses_invoice_request_with_quantity ( ) {
1052
+ let ten = NonZeroU64 :: new ( 10 ) . unwrap ( ) ;
1053
+
1054
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1055
+ . amount_msats ( 1000 )
1056
+ . supported_quantity ( Quantity :: one ( ) )
1057
+ . build ( ) . unwrap ( )
1058
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1059
+ . build ( ) . unwrap ( )
1060
+ . sign ( payer_sign) . unwrap ( ) ;
1061
+
1062
+ let mut buffer = Vec :: new ( ) ;
1063
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1064
+
1065
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1066
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1067
+ }
1068
+
1069
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1070
+ . amount_msats ( 1000 )
1071
+ . supported_quantity ( Quantity :: one ( ) )
1072
+ . build ( ) . unwrap ( )
1073
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1074
+ . amount_msats ( 2_000 ) . unwrap ( )
1075
+ . quantity_unchecked ( 2 )
1076
+ . build_unchecked ( )
1077
+ . sign ( payer_sign) . unwrap ( ) ;
1078
+
1079
+ let mut buffer = Vec :: new ( ) ;
1080
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1081
+
1082
+ match InvoiceRequest :: try_from ( buffer) {
1083
+ Ok ( _) => panic ! ( "expected error" ) ,
1084
+ Err ( e) => {
1085
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnexpectedQuantity ) ) ;
1086
+ } ,
1087
+ }
1088
+
1089
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1090
+ . amount_msats ( 1000 )
1091
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1092
+ . build ( ) . unwrap ( )
1093
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1094
+ . amount_msats ( 10_000 ) . unwrap ( )
1095
+ . quantity ( 10 ) . unwrap ( )
1096
+ . build ( ) . unwrap ( )
1097
+ . sign ( payer_sign) . unwrap ( ) ;
1098
+
1099
+ let mut buffer = Vec :: new ( ) ;
1100
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1101
+
1102
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1103
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1104
+ }
1105
+
1106
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1107
+ . amount_msats ( 1000 )
1108
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1109
+ . build ( ) . unwrap ( )
1110
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1111
+ . amount_msats ( 11_000 ) . unwrap ( )
1112
+ . quantity_unchecked ( 11 )
1113
+ . build_unchecked ( )
1114
+ . sign ( payer_sign) . unwrap ( ) ;
1115
+
1116
+ let mut buffer = Vec :: new ( ) ;
1117
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1118
+
1119
+ match InvoiceRequest :: try_from ( buffer) {
1120
+ Ok ( _) => panic ! ( "expected error" ) ,
1121
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidQuantity ) ) ,
1122
+ }
1123
+
1124
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1125
+ . amount_msats ( 1000 )
1126
+ . supported_quantity ( Quantity :: Unbounded )
1127
+ . build ( ) . unwrap ( )
1128
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1129
+ . amount_msats ( 2_000 ) . unwrap ( )
1130
+ . quantity ( 2 ) . unwrap ( )
1131
+ . build ( ) . unwrap ( )
1132
+ . sign ( payer_sign) . unwrap ( ) ;
1133
+
1134
+ let mut buffer = Vec :: new ( ) ;
1135
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1136
+
1137
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1138
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1139
+ }
1140
+
1141
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1142
+ . amount_msats ( 1000 )
1143
+ . supported_quantity ( Quantity :: Unbounded )
1144
+ . build ( ) . unwrap ( )
1145
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1146
+ . build_unchecked ( )
1147
+ . sign ( payer_sign) . unwrap ( ) ;
1148
+
1149
+ let mut buffer = Vec :: new ( ) ;
1150
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1151
+
1152
+ match InvoiceRequest :: try_from ( buffer) {
1153
+ Ok ( _) => panic ! ( "expected error" ) ,
1154
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingQuantity ) ) ,
1155
+ }
1156
+ }
1157
+
1158
+ #[ test]
1159
+ fn fails_parsing_invoice_request_without_metadata ( ) {
1160
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1161
+ . amount_msats ( 1000 )
1162
+ . build ( ) . unwrap ( ) ;
1163
+ let unsigned_invoice_request = offer. request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1164
+ . build ( ) . unwrap ( ) ;
1165
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1166
+ tlv_stream. 0 . metadata = None ;
1167
+
1168
+ let mut buffer = Vec :: new ( ) ;
1169
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1170
+
1171
+ match InvoiceRequest :: try_from ( buffer) {
1172
+ Ok ( _) => panic ! ( "expected error" ) ,
1173
+ Err ( e) => {
1174
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPayerMetadata ) ) ;
1175
+ } ,
1176
+ }
1177
+ }
1178
+
1179
+ #[ test]
1180
+ fn fails_parsing_invoice_request_without_payer_id ( ) {
1181
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1182
+ . amount_msats ( 1000 )
1183
+ . build ( ) . unwrap ( ) ;
1184
+ let unsigned_invoice_request = offer. request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1185
+ . build ( ) . unwrap ( ) ;
1186
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1187
+ tlv_stream. 2 . payer_id = None ;
1188
+
1189
+ let mut buffer = Vec :: new ( ) ;
1190
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1191
+
1192
+ match InvoiceRequest :: try_from ( buffer) {
1193
+ Ok ( _) => panic ! ( "expected error" ) ,
1194
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPayerId ) ) ,
1195
+ }
1196
+ }
1197
+
1198
+ #[ test]
1199
+ fn fails_parsing_invoice_request_without_node_id ( ) {
1200
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1201
+ . amount_msats ( 1000 )
1202
+ . build ( ) . unwrap ( ) ;
1203
+ let unsigned_invoice_request = offer. request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1204
+ . build ( ) . unwrap ( ) ;
1205
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1206
+ tlv_stream. 1 . node_id = None ;
1207
+
1208
+ let mut buffer = Vec :: new ( ) ;
1209
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1210
+
1211
+ match InvoiceRequest :: try_from ( buffer) {
1212
+ Ok ( _) => panic ! ( "expected error" ) ,
1213
+ Err ( e) => {
1214
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSigningPubkey ) ) ;
1215
+ } ,
1216
+ }
1217
+ }
1218
+
1219
+ #[ test]
1220
+ fn parses_invoice_request_without_signature ( ) {
1221
+ let mut buffer = Vec :: new ( ) ;
1222
+ OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1223
+ . amount_msats ( 1000 )
1224
+ . build ( ) . unwrap ( )
1225
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1226
+ . build ( ) . unwrap ( )
1227
+ . invoice_request
1228
+ . write ( & mut buffer) . unwrap ( ) ;
1229
+
1230
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1231
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1232
+ }
1233
+ }
1234
+
1235
+ #[ test]
1236
+ fn fails_parsing_invoice_request_with_invalid_signature ( ) {
1237
+ let mut invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1238
+ . amount_msats ( 1000 )
1239
+ . build ( ) . unwrap ( )
1240
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1241
+ . build ( ) . unwrap ( )
1242
+ . sign ( payer_sign) . unwrap ( ) ;
1243
+ let last_signature_byte = invoice_request. bytes . last_mut ( ) . unwrap ( ) ;
1244
+ * last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ;
1245
+
1246
+ let mut buffer = Vec :: new ( ) ;
1247
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1248
+
1249
+ match InvoiceRequest :: try_from ( buffer) {
1250
+ Ok ( _) => panic ! ( "expected error" ) ,
1251
+ Err ( e) => {
1252
+ assert_eq ! ( e, ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) ) ;
1253
+ } ,
1254
+ }
1255
+ }
1256
+
897
1257
#[ test]
898
1258
fn fails_parsing_invoice_request_with_extra_tlv_records ( ) {
899
1259
let secp_ctx = Secp256k1 :: new ( ) ;
0 commit comments