@@ -194,6 +194,12 @@ impl<'a> InvoiceRequestBuilder<'a> {
194
194
let InvoiceRequestBuilder { offer, invoice_request } = self ;
195
195
Ok ( UnsignedInvoiceRequest { offer, invoice_request } )
196
196
}
197
+
198
+ #[ cfg( test) ]
199
+ fn build_unchecked ( self ) -> UnsignedInvoiceRequest < ' a > {
200
+ let InvoiceRequestBuilder { offer, invoice_request } = self ;
201
+ UnsignedInvoiceRequest { offer, invoice_request }
202
+ }
197
203
}
198
204
199
205
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
@@ -483,13 +489,13 @@ mod tests {
483
489
484
490
use bitcoin:: blockdata:: constants:: ChainHash ;
485
491
use bitcoin:: network:: constants:: Network ;
486
- use bitcoin:: secp256k1:: { KeyPair , Message , PublicKey , Secp256k1 , SecretKey } ;
492
+ use bitcoin:: secp256k1:: { KeyPair , Message , PublicKey , Secp256k1 , SecretKey , self } ;
487
493
use bitcoin:: secp256k1:: schnorr:: Signature ;
488
494
use core:: convert:: TryFrom ;
489
495
use core:: num:: NonZeroU64 ;
490
496
use crate :: ln:: features:: InvoiceRequestFeatures ;
491
497
use crate :: ln:: msgs:: DecodeError ;
492
- use crate :: offers:: offer:: { OfferBuilder , Quantity } ;
498
+ use crate :: offers:: offer:: { Amount , Offer , OfferBuilder , Quantity } ;
493
499
use crate :: offers:: parse:: { ParseError , SemanticError } ;
494
500
use crate :: util:: ser:: { BigSize , Writeable } ;
495
501
use crate :: util:: string:: PrintableString ;
@@ -828,6 +834,318 @@ mod tests {
828
834
assert_eq ! ( tlv_stream. payer_note, Some ( & String :: from( "baz" ) ) ) ;
829
835
}
830
836
837
+ #[ test]
838
+ fn parses_invoice_request_with_metadata ( ) {
839
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
840
+ . amount_msats ( 1000 )
841
+ . build ( ) . unwrap ( )
842
+ . request_invoice ( payer_pubkey ( ) )
843
+ . metadata ( vec ! [ 42 ; 32 ] )
844
+ . build ( ) . unwrap ( )
845
+ . sign ( payer_sign) . unwrap ( ) ;
846
+
847
+ let mut buffer = Vec :: new ( ) ;
848
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
849
+
850
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
851
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
852
+ }
853
+ }
854
+
855
+ #[ test]
856
+ fn parses_invoice_request_with_chain ( ) {
857
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
858
+ . amount_msats ( 1000 )
859
+ . build ( ) . unwrap ( )
860
+ . request_invoice ( payer_pubkey ( ) )
861
+ . chain ( Network :: Bitcoin )
862
+ . build ( ) . unwrap ( )
863
+ . sign ( payer_sign) . unwrap ( ) ;
864
+
865
+ let mut buffer = Vec :: new ( ) ;
866
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
867
+
868
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
869
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
870
+ }
871
+
872
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
873
+ . amount_msats ( 1000 )
874
+ . build ( ) . unwrap ( )
875
+ . request_invoice ( payer_pubkey ( ) )
876
+ . chain ( Network :: Testnet )
877
+ . build_unchecked ( )
878
+ . sign ( payer_sign) . unwrap ( ) ;
879
+
880
+ let mut buffer = Vec :: new ( ) ;
881
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
882
+
883
+ match InvoiceRequest :: try_from ( buffer) {
884
+ Ok ( _) => panic ! ( "expected error" ) ,
885
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedChain ) ) ,
886
+ }
887
+ }
888
+
889
+ #[ test]
890
+ fn parses_invoice_request_with_amount ( ) {
891
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
892
+ . amount_msats ( 1000 )
893
+ . build ( ) . unwrap ( )
894
+ . request_invoice ( payer_pubkey ( ) )
895
+ . build ( ) . unwrap ( )
896
+ . sign ( payer_sign) . unwrap ( ) ;
897
+
898
+ let mut buffer = Vec :: new ( ) ;
899
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
900
+
901
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
902
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
903
+ }
904
+
905
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
906
+ . build ( ) . unwrap ( )
907
+ . request_invoice ( payer_pubkey ( ) )
908
+ . amount_msats ( 1000 )
909
+ . build ( ) . unwrap ( )
910
+ . sign ( payer_sign) . unwrap ( ) ;
911
+
912
+ let mut buffer = Vec :: new ( ) ;
913
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
914
+
915
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
916
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
917
+ }
918
+
919
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
920
+ . build ( ) . unwrap ( )
921
+ . request_invoice ( payer_pubkey ( ) )
922
+ . build_unchecked ( )
923
+ . sign ( payer_sign) . unwrap ( ) ;
924
+
925
+ let mut buffer = Vec :: new ( ) ;
926
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
927
+
928
+ match InvoiceRequest :: try_from ( buffer) {
929
+ Ok ( _) => panic ! ( "expected error" ) ,
930
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingAmount ) ) ,
931
+ }
932
+
933
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
934
+ . amount_msats ( 1000 )
935
+ . build ( ) . unwrap ( )
936
+ . request_invoice ( payer_pubkey ( ) )
937
+ . amount_msats ( 999 )
938
+ . build_unchecked ( )
939
+ . sign ( payer_sign) . unwrap ( ) ;
940
+
941
+ let mut buffer = Vec :: new ( ) ;
942
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
943
+
944
+ match InvoiceRequest :: try_from ( buffer) {
945
+ Ok ( _) => panic ! ( "expected error" ) ,
946
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InsufficientAmount ) ) ,
947
+ }
948
+
949
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
950
+ . amount ( Amount :: Currency { iso4217_code : * b"USD" , amount : 1000 } )
951
+ . build_unchecked ( )
952
+ . request_invoice ( payer_pubkey ( ) )
953
+ . build_unchecked ( )
954
+ . sign ( payer_sign) . unwrap ( ) ;
955
+
956
+ let mut buffer = Vec :: new ( ) ;
957
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
958
+
959
+ match InvoiceRequest :: try_from ( buffer) {
960
+ Ok ( _) => panic ! ( "expected error" ) ,
961
+ Err ( e) => {
962
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnsupportedCurrency ) ) ;
963
+ } ,
964
+ }
965
+ }
966
+
967
+ #[ test]
968
+ fn parses_invoice_request_with_quantity ( ) {
969
+ let ten = NonZeroU64 :: new ( 10 ) . unwrap ( ) ;
970
+
971
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
972
+ . amount_msats ( 1000 )
973
+ . supported_quantity ( Quantity :: one ( ) )
974
+ . build ( ) . unwrap ( )
975
+ . request_invoice ( payer_pubkey ( ) )
976
+ . build ( ) . unwrap ( )
977
+ . sign ( payer_sign) . unwrap ( ) ;
978
+
979
+ let mut buffer = Vec :: new ( ) ;
980
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
981
+
982
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
983
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
984
+ }
985
+
986
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
987
+ . amount_msats ( 1000 )
988
+ . supported_quantity ( Quantity :: one ( ) )
989
+ . build ( ) . unwrap ( )
990
+ . request_invoice ( payer_pubkey ( ) )
991
+ . amount_msats ( 2_000 )
992
+ . quantity ( 2 )
993
+ . build_unchecked ( )
994
+ . sign ( payer_sign) . unwrap ( ) ;
995
+
996
+ let mut buffer = Vec :: new ( ) ;
997
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
998
+
999
+ match InvoiceRequest :: try_from ( buffer) {
1000
+ Ok ( _) => panic ! ( "expected error" ) ,
1001
+ Err ( e) => {
1002
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: UnexpectedQuantity ) ) ;
1003
+ } ,
1004
+ }
1005
+
1006
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1007
+ . amount_msats ( 1000 )
1008
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1009
+ . build ( ) . unwrap ( )
1010
+ . request_invoice ( payer_pubkey ( ) )
1011
+ . amount_msats ( 10_000 )
1012
+ . quantity ( 10 )
1013
+ . build ( ) . unwrap ( )
1014
+ . sign ( payer_sign) . unwrap ( ) ;
1015
+
1016
+ let mut buffer = Vec :: new ( ) ;
1017
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1018
+
1019
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1020
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1021
+ }
1022
+
1023
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1024
+ . amount_msats ( 1000 )
1025
+ . supported_quantity ( Quantity :: Bounded ( ten) )
1026
+ . build ( ) . unwrap ( )
1027
+ . request_invoice ( payer_pubkey ( ) )
1028
+ . amount_msats ( 11_000 )
1029
+ . quantity ( 11 )
1030
+ . build_unchecked ( )
1031
+ . sign ( payer_sign) . unwrap ( ) ;
1032
+
1033
+ let mut buffer = Vec :: new ( ) ;
1034
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1035
+
1036
+ match InvoiceRequest :: try_from ( buffer) {
1037
+ Ok ( _) => panic ! ( "expected error" ) ,
1038
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidQuantity ) ) ,
1039
+ }
1040
+
1041
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1042
+ . amount_msats ( 1000 )
1043
+ . supported_quantity ( Quantity :: Unbounded )
1044
+ . build ( ) . unwrap ( )
1045
+ . request_invoice ( payer_pubkey ( ) )
1046
+ . amount_msats ( 2_000 )
1047
+ . quantity ( 2 )
1048
+ . build ( ) . unwrap ( )
1049
+ . sign ( payer_sign) . unwrap ( ) ;
1050
+
1051
+ let mut buffer = Vec :: new ( ) ;
1052
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1053
+
1054
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1055
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1056
+ }
1057
+
1058
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1059
+ . amount_msats ( 1000 )
1060
+ . supported_quantity ( Quantity :: Unbounded )
1061
+ . build ( ) . unwrap ( )
1062
+ . request_invoice ( payer_pubkey ( ) )
1063
+ . build_unchecked ( )
1064
+ . sign ( payer_sign) . unwrap ( ) ;
1065
+
1066
+ let mut buffer = Vec :: new ( ) ;
1067
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1068
+
1069
+ match InvoiceRequest :: try_from ( buffer) {
1070
+ Ok ( _) => panic ! ( "expected error" ) ,
1071
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingQuantity ) ) ,
1072
+ }
1073
+ }
1074
+
1075
+ #[ test]
1076
+ fn parses_invoice_request_with_payer_id ( ) {
1077
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1078
+ . amount_msats ( 1000 )
1079
+ . build ( ) . unwrap ( )
1080
+ . request_invoice ( payer_pubkey ( ) )
1081
+ . build ( ) . unwrap ( )
1082
+ . sign ( payer_sign) . unwrap ( ) ;
1083
+
1084
+ let mut buffer = Vec :: new ( ) ;
1085
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1086
+
1087
+ if let Err ( e) = InvoiceRequest :: try_from ( buffer) {
1088
+ panic ! ( "error parsing invoice_request: {:?}" , e) ;
1089
+ }
1090
+
1091
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1092
+ . amount_msats ( 1000 )
1093
+ . build ( ) . unwrap ( ) ;
1094
+ let mut unsigned_invoice_request = offer. request_invoice ( payer_pubkey ( ) ) . build ( ) . unwrap ( ) ;
1095
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1096
+ tlv_stream. 2 . payer_id = None ;
1097
+
1098
+ let mut buffer = Vec :: new ( ) ;
1099
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1100
+
1101
+ match InvoiceRequest :: try_from ( buffer) {
1102
+ Ok ( _) => panic ! ( "expected error" ) ,
1103
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPayerId ) ) ,
1104
+ }
1105
+ }
1106
+
1107
+ #[ test]
1108
+ fn fails_parsing_invoice_request_with_missing_node_id ( ) {
1109
+ let offer = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1110
+ . amount_msats ( 1000 )
1111
+ . build ( ) . unwrap ( ) ;
1112
+ let mut unsigned_invoice_request = offer. request_invoice ( payer_pubkey ( ) ) . build ( ) . unwrap ( ) ;
1113
+ let mut tlv_stream = unsigned_invoice_request. invoice_request . as_tlv_stream ( ) ;
1114
+ tlv_stream. 1 . node_id = None ;
1115
+
1116
+ let mut buffer = Vec :: new ( ) ;
1117
+ tlv_stream. write ( & mut buffer) . unwrap ( ) ;
1118
+
1119
+ match InvoiceRequest :: try_from ( buffer) {
1120
+ Ok ( _) => panic ! ( "expected error" ) ,
1121
+ Err ( e) => {
1122
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSigningPubkey ) ) ;
1123
+ } ,
1124
+ }
1125
+ }
1126
+
1127
+ #[ test]
1128
+ fn fails_parsing_invoice_request_with_invalid_signature ( ) {
1129
+ let mut invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1130
+ . amount_msats ( 1000 )
1131
+ . build ( ) . unwrap ( )
1132
+ . request_invoice ( payer_pubkey ( ) )
1133
+ . build ( ) . unwrap ( )
1134
+ . sign ( payer_sign) . unwrap ( ) ;
1135
+ let last_signature_byte = invoice_request. bytes . last_mut ( ) . unwrap ( ) ;
1136
+ * last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ;
1137
+
1138
+ let mut buffer = Vec :: new ( ) ;
1139
+ invoice_request. write ( & mut buffer) . unwrap ( ) ;
1140
+
1141
+ match InvoiceRequest :: try_from ( buffer) {
1142
+ Ok ( _) => panic ! ( "expected error" ) ,
1143
+ Err ( e) => {
1144
+ assert_eq ! ( e, ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) ) ;
1145
+ } ,
1146
+ }
1147
+ }
1148
+
831
1149
#[ test]
832
1150
fn fails_parsing_invoice_request_with_extra_tlv_records ( ) {
833
1151
let secp_ctx = Secp256k1 :: new ( ) ;
0 commit comments