@@ -182,6 +182,12 @@ impl<'a> InvoiceRequestBuilder<'a> {
182
182
let InvoiceRequestBuilder { offer, invoice_request } = self ;
183
183
Ok ( UnsignedInvoiceRequest { offer, invoice_request } )
184
184
}
185
+
186
+ #[ cfg( test) ]
187
+ fn build_unchecked ( self ) -> UnsignedInvoiceRequest < ' a > {
188
+ let InvoiceRequestBuilder { offer, invoice_request } = self ;
189
+ UnsignedInvoiceRequest { offer, invoice_request }
190
+ }
185
191
}
186
192
187
193
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
@@ -468,7 +474,7 @@ mod tests {
468
474
use crate :: ln:: features:: InvoiceRequestFeatures ;
469
475
use crate :: ln:: msgs:: { DecodeError , MAX_VALUE_MSAT } ;
470
476
use crate :: offers:: merkle:: SignError ;
471
- use crate :: offers:: offer:: { OfferBuilder , Quantity } ;
477
+ use crate :: offers:: offer:: { Amount , Offer , OfferBuilder , Quantity } ;
472
478
use crate :: offers:: parse:: { ParseError , SemanticError } ;
473
479
use crate :: util:: ser:: { BigSize , Writeable } ;
474
480
use crate :: util:: string:: PrintableString ;
@@ -872,6 +878,318 @@ mod tests {
872
878
}
873
879
}
874
880
881
+ #[ test]
882
+ fn parses_invoice_request_with_metadata ( ) {
883
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
884
+ . amount_msats ( 1000 )
885
+ . build ( ) . unwrap ( )
886
+ . request_invoice ( payer_pubkey ( ) )
887
+ . metadata ( vec ! [ 42 ; 32 ] )
888
+ . build ( ) . unwrap ( )
889
+ . sign ( payer_sign) . unwrap ( ) ;
890
+
891
+ let mut buffer = Vec :: new ( ) ;
892
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
893
+
894
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
895
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
896
+ }
897
+ }
898
+
899
+ #[ test]
900
+ fn parses_invoice_request_with_chain ( ) {
901
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
902
+ . amount_msats ( 1000 )
903
+ . build ( ) . unwrap ( )
904
+ . request_invoice ( payer_pubkey ( ) )
905
+ . chain ( Network :: Bitcoin )
906
+ . build ( ) . unwrap ( )
907
+ . sign ( payer_sign) . unwrap ( ) ;
908
+
909
+ let mut buffer = Vec :: new ( ) ;
910
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
911
+
912
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
913
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
914
+ }
915
+
916
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
917
+ . amount_msats ( 1000 )
918
+ . build ( ) . unwrap ( )
919
+ . request_invoice ( payer_pubkey ( ) )
920
+ . chain ( Network :: Testnet )
921
+ . build_unchecked ( )
922
+ . sign ( payer_sign) . unwrap ( ) ;
923
+
924
+ let mut buffer = Vec :: new ( ) ;
925
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
926
+
927
+ match InvoiceRequest :: try_from ( buffer) {
928
+ Ok ( _) => panic ! ( "expected error" ) ,
929
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedChain ) ) ,
930
+ }
931
+ }
932
+
933
+ #[ test]
934
+ fn parses_invoice_request_with_amount ( ) {
935
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
936
+ . amount_msats ( 1000 )
937
+ . build ( ) . unwrap ( )
938
+ . request_invoice ( payer_pubkey ( ) )
939
+ . build ( ) . unwrap ( )
940
+ . sign ( payer_sign) . unwrap ( ) ;
941
+
942
+ let mut buffer = Vec :: new ( ) ;
943
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
944
+
945
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
946
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
947
+ }
948
+
949
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
950
+ . build ( ) . unwrap ( )
951
+ . request_invoice ( payer_pubkey ( ) )
952
+ . amount_msats ( 1000 )
953
+ . build ( ) . unwrap ( )
954
+ . sign ( payer_sign) . unwrap ( ) ;
955
+
956
+ let mut buffer = Vec :: new ( ) ;
957
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
958
+
959
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
960
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
961
+ }
962
+
963
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
964
+ . build ( ) . unwrap ( )
965
+ . request_invoice ( payer_pubkey ( ) )
966
+ . build_unchecked ( )
967
+ . sign ( payer_sign) . unwrap ( ) ;
968
+
969
+ let mut buffer = Vec :: new ( ) ;
970
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
971
+
972
+ match InvoiceRequest :: try_from ( buffer) {
973
+ Ok ( _) => panic ! ( "expected error" ) ,
974
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingAmount ) ) ,
975
+ }
976
+
977
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
978
+ . amount_msats ( 1000 )
979
+ . build ( ) . unwrap ( )
980
+ . request_invoice ( payer_pubkey ( ) )
981
+ . amount_msats ( 999 )
982
+ . build_unchecked ( )
983
+ . sign ( payer_sign) . unwrap ( ) ;
984
+
985
+ let mut buffer = Vec :: new ( ) ;
986
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
987
+
988
+ match InvoiceRequest :: try_from ( buffer) {
989
+ Ok ( _) => panic ! ( "expected error" ) ,
990
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InsufficientAmount ) ) ,
991
+ }
992
+
993
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
994
+ . amount ( Amount :: Currency { iso4217_code : * b"USD" , amount : 1000 } )
995
+ . build_unchecked ( )
996
+ . request_invoice ( payer_pubkey ( ) )
997
+ . build_unchecked ( )
998
+ . sign ( payer_sign) . unwrap ( ) ;
999
+
1000
+ let mut buffer = Vec :: new ( ) ;
1001
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1002
+
1003
+ match InvoiceRequest :: try_from ( buffer) {
1004
+ Ok ( _) => panic ! ( "expected error" ) ,
1005
+ Err ( e) => {
1006
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedCurrency ) ) ;
1007
+ } ,
1008
+ }
1009
+ }
1010
+
1011
+ #[ test]
1012
+ fn parses_invoice_request_with_quantity ( ) {
1013
+ let ten = NonZeroU64 :: new ( 10 ) . unwrap ( ) ;
1014
+
1015
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1016
+ . amount_msats ( 1000 )
1017
+ . supported_quantity ( Quantity :: one ( ) )
1018
+ . build ( ) . unwrap ( )
1019
+ . request_invoice ( payer_pubkey ( ) )
1020
+ . build ( ) . unwrap ( )
1021
+ . sign ( payer_sign) . unwrap ( ) ;
1022
+
1023
+ let mut buffer = Vec :: new ( ) ;
1024
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1025
+
1026
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1027
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1028
+ }
1029
+
1030
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1031
+ . amount_msats ( 1000 )
1032
+ . supported_quantity ( Quantity :: one ( ) )
1033
+ . build ( ) . unwrap ( )
1034
+ . request_invoice ( payer_pubkey ( ) )
1035
+ . amount_msats ( 2_000 )
1036
+ . quantity ( 2 )
1037
+ . build_unchecked ( )
1038
+ . sign ( payer_sign) . unwrap ( ) ;
1039
+
1040
+ let mut buffer = Vec :: new ( ) ;
1041
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1042
+
1043
+ match InvoiceRequest :: try_from ( buffer) {
1044
+ Ok ( _) => panic ! ( "expected error" ) ,
1045
+ Err ( e) => {
1046
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnexpectedQuantity ) ) ;
1047
+ } ,
1048
+ }
1049
+
1050
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1051
+ . amount_msats ( 1000 )
1052
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1053
+ . build ( ) . unwrap ( )
1054
+ . request_invoice ( payer_pubkey ( ) )
1055
+ . amount_msats ( 10_000 )
1056
+ . quantity ( 10 )
1057
+ . build ( ) . unwrap ( )
1058
+ . sign ( payer_sign) . unwrap ( ) ;
1059
+
1060
+ let mut buffer = Vec :: new ( ) ;
1061
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1062
+
1063
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1064
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1065
+ }
1066
+
1067
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1068
+ . amount_msats ( 1000 )
1069
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1070
+ . build ( ) . unwrap ( )
1071
+ . request_invoice ( payer_pubkey ( ) )
1072
+ . amount_msats ( 11_000 )
1073
+ . quantity ( 11 )
1074
+ . build_unchecked ( )
1075
+ . sign ( payer_sign) . unwrap ( ) ;
1076
+
1077
+ let mut buffer = Vec :: new ( ) ;
1078
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1079
+
1080
+ match InvoiceRequest :: try_from ( buffer) {
1081
+ Ok ( _) => panic ! ( "expected error" ) ,
1082
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidQuantity ) ) ,
1083
+ }
1084
+
1085
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1086
+ . amount_msats ( 1000 )
1087
+ . supported_quantity ( Quantity :: Unbounded )
1088
+ . build ( ) . unwrap ( )
1089
+ . request_invoice ( payer_pubkey ( ) )
1090
+ . amount_msats ( 2_000 )
1091
+ . quantity ( 2 )
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 :: Unbounded )
1105
+ . build ( ) . unwrap ( )
1106
+ . request_invoice ( payer_pubkey ( ) )
1107
+ . build_unchecked ( )
1108
+ . sign ( payer_sign) . unwrap ( ) ;
1109
+
1110
+ let mut buffer = Vec :: new ( ) ;
1111
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1112
+
1113
+ match InvoiceRequest :: try_from ( buffer) {
1114
+ Ok ( _) => panic ! ( "expected error" ) ,
1115
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingQuantity ) ) ,
1116
+ }
1117
+ }
1118
+
1119
+ #[ test]
1120
+ fn parses_invoice_request_with_payer_id ( ) {
1121
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1122
+ . amount_msats ( 1000 )
1123
+ . build ( ) . unwrap ( )
1124
+ . request_invoice ( payer_pubkey ( ) )
1125
+ . build ( ) . unwrap ( )
1126
+ . sign ( payer_sign) . unwrap ( ) ;
1127
+
1128
+ let mut buffer = Vec :: new ( ) ;
1129
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1130
+
1131
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1132
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1133
+ }
1134
+
1135
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1136
+ . amount_msats ( 1000 )
1137
+ . build ( ) . unwrap ( ) ;
1138
+ let mut unsigned_invoice_request = offer. request_invoice ( payer_pubkey ( ) ) . build ( ) . unwrap ( ) ;
1139
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1140
+ tlv_stream. 2 . payer_id = None ;
1141
+
1142
+ let mut buffer = Vec :: new ( ) ;
1143
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1144
+
1145
+ match InvoiceRequest :: try_from ( buffer) {
1146
+ Ok ( _) => panic ! ( "expected error" ) ,
1147
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPayerId ) ) ,
1148
+ }
1149
+ }
1150
+
1151
+ #[ test]
1152
+ fn fails_parsing_invoice_request_with_missing_node_id ( ) {
1153
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1154
+ . amount_msats ( 1000 )
1155
+ . build ( ) . unwrap ( ) ;
1156
+ let mut unsigned_invoice_request = offer. request_invoice ( payer_pubkey ( ) ) . build ( ) . unwrap ( ) ;
1157
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1158
+ tlv_stream. 1 . node_id = None ;
1159
+
1160
+ let mut buffer = Vec :: new ( ) ;
1161
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1162
+
1163
+ match InvoiceRequest :: try_from ( buffer) {
1164
+ Ok ( _) => panic ! ( "expected error" ) ,
1165
+ Err ( e) => {
1166
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSigningPubkey ) ) ;
1167
+ } ,
1168
+ }
1169
+ }
1170
+
1171
+ #[ test]
1172
+ fn fails_parsing_invoice_request_with_invalid_signature ( ) {
1173
+ let mut invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1174
+ . amount_msats ( 1000 )
1175
+ . build ( ) . unwrap ( )
1176
+ . request_invoice ( payer_pubkey ( ) )
1177
+ . build ( ) . unwrap ( )
1178
+ . sign ( payer_sign) . unwrap ( ) ;
1179
+ let last_signature_byte = invoice_request. bytes . last_mut ( ) . unwrap ( ) ;
1180
+ * last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ;
1181
+
1182
+ let mut buffer = Vec :: new ( ) ;
1183
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1184
+
1185
+ match InvoiceRequest :: try_from ( buffer) {
1186
+ Ok ( _) => panic ! ( "expected error" ) ,
1187
+ Err ( e) => {
1188
+ assert_eq ! ( e, ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) ) ;
1189
+ } ,
1190
+ }
1191
+ }
1192
+
875
1193
#[ test]
876
1194
fn fails_parsing_invoice_request_with_extra_tlv_records ( ) {
877
1195
let secp_ctx = Secp256k1 :: new ( ) ;
0 commit comments