@@ -565,19 +565,20 @@ mod tests {
565565	use  crate :: blinded_path:: { BlindedHop ,  BlindedPath ,  IntroductionNode } ; 
566566	use  crate :: ln:: features:: { Bolt12InvoiceFeatures ,  OfferFeatures } ; 
567567	use  crate :: ln:: inbound_payment:: ExpandedKey ; 
568+ 	use  crate :: ln:: msgs:: DecodeError ; 
568569	use  crate :: offers:: invoice:: { InvoiceTlvStreamRef ,  SIGNATURE_TAG } ; 
569570	use  crate :: offers:: merkle; 
570571	use  crate :: offers:: merkle:: { SignatureTlvStreamRef ,  TaggedHash } ; 
571572	use  crate :: offers:: offer:: { Offer ,  OfferBuilder ,  OfferTlvStreamRef ,  Quantity } ; 
572- 	use  crate :: offers:: parse:: Bolt12SemanticError ; 
573+ 	use  crate :: offers:: parse:: { Bolt12ParseError ,   Bolt12SemanticError } ; 
573574	use  crate :: offers:: static_invoice:: { 
574575		StaticInvoice ,  StaticInvoiceBuilder ,  DEFAULT_RELATIVE_EXPIRY , 
575576	} ; 
576577	use  crate :: offers:: test_utils:: * ; 
577578	use  crate :: sign:: KeyMaterial ; 
578- 	use  crate :: util:: ser:: { Iterable ,  Writeable } ; 
579+ 	use  crate :: util:: ser:: { BigSize ,   Iterable ,  Writeable } ; 
579580	use  bitcoin:: blockdata:: constants:: ChainHash ; 
580- 	use  bitcoin:: secp256k1:: Secp256k1 ; 
581+ 	use  bitcoin:: secp256k1:: { self ,   Secp256k1 } ; 
581582	use  bitcoin:: Network ; 
582583	use  core:: time:: Duration ; 
583584
@@ -595,6 +596,43 @@ mod tests {
595596		} 
596597	} 
597598
599+ 	fn  tlv_stream_to_bytes ( 
600+ 		tlv_stream :  & ( OfferTlvStreamRef ,  InvoiceTlvStreamRef ,  SignatureTlvStreamRef ) , 
601+ 	)  -> Vec < u8 >  { 
602+ 		let  mut  buffer = Vec :: new ( ) ; 
603+ 		tlv_stream. 0 . write ( & mut  buffer) . unwrap ( ) ; 
604+ 		tlv_stream. 1 . write ( & mut  buffer) . unwrap ( ) ; 
605+ 		tlv_stream. 2 . write ( & mut  buffer) . unwrap ( ) ; 
606+ 		buffer
607+ 	} 
608+ 
609+ 	fn  invoice ( )  -> StaticInvoice  { 
610+ 		let  node_id = recipient_pubkey ( ) ; 
611+ 		let  payment_paths = payment_paths ( ) ; 
612+ 		let  now = now ( ) ; 
613+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
614+ 		let  entropy = FixedEntropy  { } ; 
615+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
616+ 
617+ 		let  offer =
618+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
619+ 				. path ( blinded_path ( ) ) 
620+ 				. build ( ) 
621+ 				. unwrap ( ) ; 
622+ 
623+ 		StaticInvoiceBuilder :: for_offer_using_derived_keys ( 
624+ 			& offer, 
625+ 			payment_paths. clone ( ) , 
626+ 			vec ! [ blinded_path( ) ] , 
627+ 			now, 
628+ 			& expanded_key, 
629+ 			& secp_ctx, 
630+ 		) 
631+ 		. unwrap ( ) 
632+ 		. build_and_sign ( & secp_ctx) 
633+ 		. unwrap ( ) 
634+ 	} 
635+ 
598636	fn  blinded_path ( )  -> BlindedPath  { 
599637		BlindedPath  { 
600638			introduction_node :  IntroductionNode :: NodeId ( pubkey ( 40 ) ) , 
@@ -905,4 +943,231 @@ mod tests {
905943			panic ! ( "expected error" ) 
906944		} 
907945	} 
946+ 
947+ 	#[ test]  
948+ 	fn  parses_invoice_with_relative_expiry ( )  { 
949+ 		let  node_id = recipient_pubkey ( ) ; 
950+ 		let  payment_paths = payment_paths ( ) ; 
951+ 		let  now = now ( ) ; 
952+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
953+ 		let  entropy = FixedEntropy  { } ; 
954+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
955+ 
956+ 		let  offer =
957+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
958+ 				. path ( blinded_path ( ) ) 
959+ 				. build ( ) 
960+ 				. unwrap ( ) ; 
961+ 
962+ 		const  TEST_RELATIVE_EXPIRY :  u32  = 3600 ; 
963+ 		let  invoice = StaticInvoiceBuilder :: for_offer_using_derived_keys ( 
964+ 			& offer, 
965+ 			payment_paths. clone ( ) , 
966+ 			vec ! [ blinded_path( ) ] , 
967+ 			now, 
968+ 			& expanded_key, 
969+ 			& secp_ctx, 
970+ 		) 
971+ 		. unwrap ( ) 
972+ 		. relative_expiry ( TEST_RELATIVE_EXPIRY ) 
973+ 		. build_and_sign ( & secp_ctx) 
974+ 		. unwrap ( ) ; 
975+ 
976+ 		let  mut  buffer = Vec :: new ( ) ; 
977+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
978+ 
979+ 		match  StaticInvoice :: try_from ( buffer)  { 
980+ 			Ok ( invoice)  => assert_eq ! ( 
981+ 				invoice. relative_expiry( ) , 
982+ 				Duration :: from_secs( TEST_RELATIVE_EXPIRY  as  u64 ) 
983+ 			) , 
984+ 			Err ( e)  => panic ! ( "error parsing invoice: {:?}" ,  e) , 
985+ 		} 
986+ 	} 
987+ 
988+ 	#[ test]  
989+ 	fn  parses_invoice_with_allow_mpp ( )  { 
990+ 		let  node_id = recipient_pubkey ( ) ; 
991+ 		let  payment_paths = payment_paths ( ) ; 
992+ 		let  now = now ( ) ; 
993+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
994+ 		let  entropy = FixedEntropy  { } ; 
995+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
996+ 
997+ 		let  offer =
998+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
999+ 				. path ( blinded_path ( ) ) 
1000+ 				. build ( ) 
1001+ 				. unwrap ( ) ; 
1002+ 
1003+ 		let  invoice = StaticInvoiceBuilder :: for_offer_using_derived_keys ( 
1004+ 			& offer, 
1005+ 			payment_paths. clone ( ) , 
1006+ 			vec ! [ blinded_path( ) ] , 
1007+ 			now, 
1008+ 			& expanded_key, 
1009+ 			& secp_ctx, 
1010+ 		) 
1011+ 		. unwrap ( ) 
1012+ 		. allow_mpp ( ) 
1013+ 		. build_and_sign ( & secp_ctx) 
1014+ 		. unwrap ( ) ; 
1015+ 
1016+ 		let  mut  buffer = Vec :: new ( ) ; 
1017+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
1018+ 
1019+ 		match  StaticInvoice :: try_from ( buffer)  { 
1020+ 			Ok ( invoice)  => { 
1021+ 				let  mut  features = Bolt12InvoiceFeatures :: empty ( ) ; 
1022+ 				features. set_basic_mpp_optional ( ) ; 
1023+ 				assert_eq ! ( invoice. invoice_features( ) ,  & features) ; 
1024+ 			} , 
1025+ 			Err ( e)  => panic ! ( "error parsing invoice: {:?}" ,  e) , 
1026+ 		} 
1027+ 	} 
1028+ 
1029+ 	#[ test]  
1030+ 	fn  fails_parsing_missing_invoice_fields ( )  { 
1031+ 		// Error if `created_at` is missing. 
1032+ 		let  missing_created_at_invoice = invoice ( ) ; 
1033+ 		let  mut  tlv_stream = missing_created_at_invoice. as_tlv_stream ( ) ; 
1034+ 		tlv_stream. 1 . created_at  = None ; 
1035+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1036+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1037+ 			Err ( e)  => { 
1038+ 				assert_eq ! ( 
1039+ 					e, 
1040+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingCreationTime ) 
1041+ 				) ; 
1042+ 			} , 
1043+ 		} 
1044+ 
1045+ 		// Error if `node_id` is missing. 
1046+ 		let  missing_node_id_invoice = invoice ( ) ; 
1047+ 		let  mut  tlv_stream = missing_node_id_invoice. as_tlv_stream ( ) ; 
1048+ 		tlv_stream. 1 . node_id  = None ; 
1049+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1050+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1051+ 			Err ( e)  => { 
1052+ 				assert_eq ! ( 
1053+ 					e, 
1054+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingSigningPubkey ) 
1055+ 				) ; 
1056+ 			} , 
1057+ 		} 
1058+ 
1059+ 		// Error if message paths are missing. 
1060+ 		let  missing_message_paths_invoice = invoice ( ) ; 
1061+ 		let  mut  tlv_stream = missing_message_paths_invoice. as_tlv_stream ( ) ; 
1062+ 		tlv_stream. 1 . message_paths  = None ; 
1063+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1064+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1065+ 			Err ( e)  => { 
1066+ 				assert_eq ! ( 
1067+ 					e, 
1068+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingPaths ) 
1069+ 				) ; 
1070+ 			} , 
1071+ 		} 
1072+ 
1073+ 		// Error if signature is missing. 
1074+ 		let  invoice = invoice ( ) ; 
1075+ 		let  mut  buffer = Vec :: new ( ) ; 
1076+ 		invoice. contents . as_tlv_stream ( ) . write ( & mut  buffer) . unwrap ( ) ; 
1077+ 		match  StaticInvoice :: try_from ( buffer)  { 
1078+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1079+ 			Err ( e)  => assert_eq ! ( 
1080+ 				e, 
1081+ 				Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingSignature ) 
1082+ 			) , 
1083+ 		} 
1084+ 	} 
1085+ 
1086+ 	#[ test]  
1087+ 	fn  fails_parsing_invalid_signing_pubkey ( )  { 
1088+ 		let  invoice = invoice ( ) ; 
1089+ 		let  invalid_pubkey = payer_pubkey ( ) ; 
1090+ 		let  mut  tlv_stream = invoice. as_tlv_stream ( ) ; 
1091+ 		tlv_stream. 1 . node_id  = Some ( & invalid_pubkey) ; 
1092+ 
1093+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1094+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1095+ 			Err ( e)  => { 
1096+ 				assert_eq ! ( 
1097+ 					e, 
1098+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: InvalidSigningPubkey ) 
1099+ 				) ; 
1100+ 			} , 
1101+ 		} 
1102+ 	} 
1103+ 
1104+ 	#[ test]  
1105+ 	fn  fails_parsing_invoice_with_invalid_signature ( )  { 
1106+ 		let  mut  invoice = invoice ( ) ; 
1107+ 		let  last_signature_byte = invoice. bytes . last_mut ( ) . unwrap ( ) ; 
1108+ 		* last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ; 
1109+ 
1110+ 		let  mut  buffer = Vec :: new ( ) ; 
1111+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
1112+ 
1113+ 		match  StaticInvoice :: try_from ( buffer)  { 
1114+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1115+ 			Err ( e)  => { 
1116+ 				assert_eq ! ( 
1117+ 					e, 
1118+ 					Bolt12ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) 
1119+ 				) ; 
1120+ 			} , 
1121+ 		} 
1122+ 	} 
1123+ 
1124+ 	#[ test]  
1125+ 	fn  fails_parsing_invoice_with_extra_tlv_records ( )  { 
1126+ 		let  invoice = invoice ( ) ; 
1127+ 		let  mut  encoded_invoice = Vec :: new ( ) ; 
1128+ 		invoice. write ( & mut  encoded_invoice) . unwrap ( ) ; 
1129+ 		BigSize ( 1002 ) . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1130+ 		BigSize ( 32 ) . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1131+ 		[ 42u8 ;  32 ] . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1132+ 
1133+ 		match  StaticInvoice :: try_from ( encoded_invoice)  { 
1134+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1135+ 			Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1136+ 		} 
1137+ 	} 
1138+ 
1139+ 	#[ test]  
1140+ 	fn  fails_parsing_invoice_with_invalid_offer_fields ( )  { 
1141+ 		// Error if the offer is missing paths. 
1142+ 		let  missing_offer_paths_invoice = invoice ( ) ; 
1143+ 		let  mut  tlv_stream = missing_offer_paths_invoice. as_tlv_stream ( ) ; 
1144+ 		tlv_stream. 0 . paths  = None ; 
1145+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1146+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1147+ 			Err ( e)  => { 
1148+ 				assert_eq ! ( 
1149+ 					e, 
1150+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingPaths ) 
1151+ 				) ; 
1152+ 			} , 
1153+ 		} 
1154+ 
1155+ 		// Error if the offer has more than one chain. 
1156+ 		let  invalid_offer_chains_invoice = invoice ( ) ; 
1157+ 		let  mut  tlv_stream = invalid_offer_chains_invoice. as_tlv_stream ( ) ; 
1158+ 		let  invalid_chains = vec ! [ 
1159+ 			ChainHash :: using_genesis_block( Network :: Bitcoin ) , 
1160+ 			ChainHash :: using_genesis_block( Network :: Testnet ) , 
1161+ 		] ; 
1162+ 		tlv_stream. 0 . chains  = Some ( & invalid_chains) ; 
1163+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1164+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1165+ 			Err ( e)  => { 
1166+ 				assert_eq ! ( 
1167+ 					e, 
1168+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: UnexpectedChain ) 
1169+ 				) ; 
1170+ 			} , 
1171+ 		} 
1172+ 	} 
9081173} 
0 commit comments