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