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