@@ -189,6 +189,12 @@ impl<'a> InvoiceRequestBuilder<'a> {
189189 let InvoiceRequestBuilder { offer, invoice_request } = self ;
190190 Ok ( UnsignedInvoiceRequest { offer, invoice_request } )
191191 }
192+
193+ #[ cfg( test) ]
194+ fn build_unchecked ( self ) -> UnsignedInvoiceRequest < ' a > {
195+ let InvoiceRequestBuilder { offer, invoice_request } = self ;
196+ UnsignedInvoiceRequest { offer, invoice_request }
197+ }
192198}
193199
194200/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
@@ -478,13 +484,13 @@ mod tests {
478484
479485 use bitcoin:: blockdata:: constants:: ChainHash ;
480486 use bitcoin:: network:: constants:: Network ;
481- use bitcoin:: secp256k1:: { KeyPair , Message , PublicKey , Secp256k1 , SecretKey } ;
487+ use bitcoin:: secp256k1:: { KeyPair , Message , PublicKey , Secp256k1 , SecretKey , self } ;
482488 use bitcoin:: secp256k1:: schnorr:: Signature ;
483489 use core:: convert:: TryFrom ;
484490 use core:: num:: NonZeroU64 ;
485491 use crate :: ln:: features:: InvoiceRequestFeatures ;
486492 use crate :: ln:: msgs:: DecodeError ;
487- use crate :: offers:: offer:: { OfferBuilder , Quantity } ;
493+ use crate :: offers:: offer:: { Amount , Offer , OfferBuilder , Quantity } ;
488494 use crate :: offers:: parse:: { ParseError , SemanticError } ;
489495 use crate :: util:: ser:: { BigSize , Writeable } ;
490496 use crate :: util:: string:: PrintableString ;
@@ -823,6 +829,318 @@ mod tests {
823829 assert_eq ! ( tlv_stream. payer_note, Some ( & String :: from( "baz" ) ) ) ;
824830 }
825831
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+
8261144 #[ test]
8271145 fn fails_parsing_invoice_request_with_extra_tlv_records ( ) {
8281146 let secp_ctx = Secp256k1 :: new ( ) ;
0 commit comments