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