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