@@ -552,22 +552,72 @@ mod tests {
552552	use  crate :: blinded_path:: { BlindedHop ,  BlindedPath ,  IntroductionNode } ; 
553553	use  crate :: ln:: features:: { Bolt12InvoiceFeatures ,  OfferFeatures } ; 
554554	use  crate :: ln:: inbound_payment:: ExpandedKey ; 
555+ 	use  crate :: ln:: msgs:: DecodeError ; 
555556	use  crate :: offers:: invoice:: SIGNATURE_TAG ; 
556557	use  crate :: offers:: merkle; 
557- 	use  crate :: offers:: merkle:: TaggedHash ; 
558- 	use  crate :: offers:: offer:: { Offer ,  OfferBuilder ,  Quantity } ; 
559- 	use  crate :: offers:: parse:: Bolt12SemanticError ; 
558+ 	use  crate :: offers:: merkle:: { SignatureTlvStreamRef ,   TaggedHash } ; 
559+ 	use  crate :: offers:: offer:: { Offer ,  OfferBuilder ,  OfferTlvStreamRef ,   Quantity } ; 
560+ 	use  crate :: offers:: parse:: { Bolt12ParseError ,   Bolt12SemanticError } ; 
560561	use  crate :: offers:: static_invoice:: { 
561562		StaticInvoice ,  StaticInvoiceBuilder ,  DEFAULT_RELATIVE_EXPIRY , 
562563	} ; 
563564	use  crate :: offers:: test_utils:: * ; 
564565	use  crate :: sign:: KeyMaterial ; 
565- 	use  crate :: util:: ser:: Writeable ; 
566+ 	use  crate :: util:: ser:: { BigSize ,   Writeable } ; 
566567	use  bitcoin:: blockdata:: constants:: ChainHash ; 
567568	use  bitcoin:: network:: constants:: Network ; 
568- 	use  bitcoin:: secp256k1:: Secp256k1 ; 
569+ 	use  bitcoin:: secp256k1:: { self ,   Secp256k1 } ; 
569570	use  core:: time:: Duration ; 
570571
572+ 	use  super :: InvoiceTlvStreamRef ; 
573+ 
574+ 	impl  StaticInvoice  { 
575+ 		fn  as_tlv_stream ( & self )  -> ( OfferTlvStreamRef ,  InvoiceTlvStreamRef ,  SignatureTlvStreamRef )  { 
576+ 			( 
577+ 				self . contents . offer . as_tlv_stream ( ) , 
578+ 				self . contents . as_invoice_fields_tlv_stream ( ) , 
579+ 				SignatureTlvStreamRef  {  signature :  Some ( & self . signature )  } , 
580+ 			) 
581+ 		} 
582+ 	} 
583+ 
584+ 	fn  tlv_stream_to_bytes ( 
585+ 		tlv_stream :  & ( OfferTlvStreamRef ,  InvoiceTlvStreamRef ,  SignatureTlvStreamRef ) , 
586+ 	)  -> Vec < u8 >  { 
587+ 		let  mut  buffer = Vec :: new ( ) ; 
588+ 		tlv_stream. 0 . write ( & mut  buffer) . unwrap ( ) ; 
589+ 		tlv_stream. 1 . write ( & mut  buffer) . unwrap ( ) ; 
590+ 		tlv_stream. 2 . write ( & mut  buffer) . unwrap ( ) ; 
591+ 		buffer
592+ 	} 
593+ 
594+ 	fn  invoice ( )  -> StaticInvoice  { 
595+ 		let  node_id = recipient_pubkey ( ) ; 
596+ 		let  payment_paths = payment_paths ( ) ; 
597+ 		let  now = now ( ) ; 
598+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
599+ 		let  entropy = FixedEntropy  { } ; 
600+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
601+ 
602+ 		let  offer =
603+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
604+ 				. path ( blinded_path ( ) ) 
605+ 				. build ( ) 
606+ 				. unwrap ( ) ; 
607+ 
608+ 		let  ( _offer_id,  keys_opt)  = offer. verify ( & expanded_key,  & secp_ctx) . unwrap ( ) ; 
609+ 		StaticInvoiceBuilder :: for_offer_using_keys ( 
610+ 			& offer, 
611+ 			payment_paths. clone ( ) , 
612+ 			vec ! [ blinded_path( ) ] , 
613+ 			now, 
614+ 			keys_opt. unwrap ( ) , 
615+ 		) 
616+ 		. unwrap ( ) 
617+ 		. build_and_sign ( & secp_ctx) 
618+ 		. unwrap ( ) 
619+ 	} 
620+ 
571621	fn  blinded_path ( )  -> BlindedPath  { 
572622		BlindedPath  { 
573623			introduction_node :  IntroductionNode :: NodeId ( pubkey ( 40 ) ) , 
@@ -846,4 +896,233 @@ mod tests {
846896			panic ! ( "expected error" ) 
847897		} 
848898	} 
899+ 
900+ 	#[ test]  
901+ 	fn  parses_invoice_with_relative_expiry ( )  { 
902+ 		let  node_id = recipient_pubkey ( ) ; 
903+ 		let  payment_paths = payment_paths ( ) ; 
904+ 		let  now = now ( ) ; 
905+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
906+ 		let  entropy = FixedEntropy  { } ; 
907+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
908+ 
909+ 		let  offer =
910+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
911+ 				. path ( blinded_path ( ) ) 
912+ 				. build ( ) 
913+ 				. unwrap ( ) ; 
914+ 
915+ 		const  TEST_RELATIVE_EXPIRY :  u32  = 3600 ; 
916+ 		let  ( _offer_id,  keys_opt)  = offer. verify ( & expanded_key,  & secp_ctx) . unwrap ( ) ; 
917+ 		let  invoice = StaticInvoiceBuilder :: for_offer_using_keys ( 
918+ 			& offer, 
919+ 			payment_paths. clone ( ) , 
920+ 			vec ! [ blinded_path( ) ] , 
921+ 			now, 
922+ 			keys_opt. unwrap ( ) , 
923+ 		) 
924+ 		. unwrap ( ) 
925+ 		. relative_expiry ( TEST_RELATIVE_EXPIRY ) 
926+ 		. build_and_sign ( & secp_ctx) 
927+ 		. unwrap ( ) ; 
928+ 
929+ 		let  mut  buffer = Vec :: new ( ) ; 
930+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
931+ 
932+ 		match  StaticInvoice :: try_from ( buffer)  { 
933+ 			Ok ( invoice)  => assert_eq ! ( 
934+ 				invoice. relative_expiry( ) , 
935+ 				Duration :: from_secs( TEST_RELATIVE_EXPIRY  as  u64 ) 
936+ 			) , 
937+ 			Err ( e)  => panic ! ( "error parsing invoice: {:?}" ,  e) , 
938+ 		} 
939+ 	} 
940+ 
941+ 	#[ test]  
942+ 	fn  parses_invoice_with_allow_mpp ( )  { 
943+ 		let  node_id = recipient_pubkey ( ) ; 
944+ 		let  payment_paths = payment_paths ( ) ; 
945+ 		let  now = now ( ) ; 
946+ 		let  expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ;  32 ] ) ) ; 
947+ 		let  entropy = FixedEntropy  { } ; 
948+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
949+ 
950+ 		let  offer =
951+ 			OfferBuilder :: deriving_signing_pubkey ( node_id,  & expanded_key,  & entropy,  & secp_ctx) 
952+ 				. path ( blinded_path ( ) ) 
953+ 				. build ( ) 
954+ 				. unwrap ( ) ; 
955+ 
956+ 		let  ( _offer_id,  keys_opt)  = offer. verify ( & expanded_key,  & secp_ctx) . unwrap ( ) ; 
957+ 		let  invoice = StaticInvoiceBuilder :: for_offer_using_keys ( 
958+ 			& offer, 
959+ 			payment_paths. clone ( ) , 
960+ 			vec ! [ blinded_path( ) ] , 
961+ 			now, 
962+ 			keys_opt. unwrap ( ) , 
963+ 		) 
964+ 		. unwrap ( ) 
965+ 		. allow_mpp ( ) 
966+ 		. build_and_sign ( & secp_ctx) 
967+ 		. unwrap ( ) ; 
968+ 
969+ 		let  mut  buffer = Vec :: new ( ) ; 
970+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
971+ 
972+ 		match  StaticInvoice :: try_from ( buffer)  { 
973+ 			Ok ( invoice)  => { 
974+ 				let  mut  features = Bolt12InvoiceFeatures :: empty ( ) ; 
975+ 				features. set_basic_mpp_optional ( ) ; 
976+ 				assert_eq ! ( invoice. invoice_features( ) ,  & features) ; 
977+ 			} , 
978+ 			Err ( e)  => panic ! ( "error parsing invoice: {:?}" ,  e) , 
979+ 		} 
980+ 	} 
981+ 
982+ 	#[ test]  
983+ 	fn  fails_parse_missing_invoice_fields ( )  { 
984+ 		// Error if `created_at` is missing. 
985+ 		let  missing_created_at_invoice = invoice ( ) ; 
986+ 		let  mut  tlv_stream = missing_created_at_invoice. as_tlv_stream ( ) ; 
987+ 		tlv_stream. 1 . created_at  = None ; 
988+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
989+ 			Ok ( _)  => panic ! ( "expected error" ) , 
990+ 			Err ( e)  => { 
991+ 				assert_eq ! ( 
992+ 					e, 
993+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingCreationTime ) 
994+ 				) ; 
995+ 			} , 
996+ 		} 
997+ 
998+ 		// Error if `node_id` is missing. 
999+ 		let  missing_node_id_invoice = invoice ( ) ; 
1000+ 		let  mut  tlv_stream = missing_node_id_invoice. as_tlv_stream ( ) ; 
1001+ 		tlv_stream. 1 . node_id  = None ; 
1002+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1003+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1004+ 			Err ( e)  => { 
1005+ 				assert_eq ! ( 
1006+ 					e, 
1007+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingSigningPubkey ) 
1008+ 				) ; 
1009+ 			} , 
1010+ 		} 
1011+ 
1012+ 		// Error if message paths are missing. 
1013+ 		let  missing_message_paths_invoice = invoice ( ) ; 
1014+ 		let  mut  tlv_stream = missing_message_paths_invoice. as_tlv_stream ( ) ; 
1015+ 		tlv_stream. 1 . message_paths  = None ; 
1016+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1017+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1018+ 			Err ( e)  => { 
1019+ 				assert_eq ! ( 
1020+ 					e, 
1021+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingPaths ) 
1022+ 				) ; 
1023+ 			} , 
1024+ 		} 
1025+ 
1026+ 		// Error if signature is missing. 
1027+ 		let  invoice = invoice ( ) ; 
1028+ 		let  mut  buffer = Vec :: new ( ) ; 
1029+ 		( invoice. contents . offer . as_tlv_stream ( ) ,  invoice. contents . as_invoice_fields_tlv_stream ( ) ) 
1030+ 			. write ( & mut  buffer) 
1031+ 			. unwrap ( ) ; 
1032+ 		match  StaticInvoice :: try_from ( buffer)  { 
1033+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1034+ 			Err ( e)  => assert_eq ! ( 
1035+ 				e, 
1036+ 				Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingSignature ) 
1037+ 			) , 
1038+ 		} 
1039+ 	} 
1040+ 
1041+ 	#[ test]  
1042+ 	fn  fails_parse_invalid_signing_pubkey ( )  { 
1043+ 		let  invoice = invoice ( ) ; 
1044+ 		let  invalid_pubkey = payer_pubkey ( ) ; 
1045+ 		let  mut  tlv_stream = invoice. as_tlv_stream ( ) ; 
1046+ 		tlv_stream. 1 . node_id  = Some ( & invalid_pubkey) ; 
1047+ 
1048+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1049+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1050+ 			Err ( e)  => { 
1051+ 				assert_eq ! ( 
1052+ 					e, 
1053+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: InvalidSigningPubkey ) 
1054+ 				) ; 
1055+ 			} , 
1056+ 		} 
1057+ 	} 
1058+ 
1059+ 	#[ test]  
1060+ 	fn  fails_parsing_invoice_with_invalid_signature ( )  { 
1061+ 		let  mut  invoice = invoice ( ) ; 
1062+ 		let  last_signature_byte = invoice. bytes . last_mut ( ) . unwrap ( ) ; 
1063+ 		* last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ; 
1064+ 
1065+ 		let  mut  buffer = Vec :: new ( ) ; 
1066+ 		invoice. write ( & mut  buffer) . unwrap ( ) ; 
1067+ 
1068+ 		match  StaticInvoice :: try_from ( buffer)  { 
1069+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1070+ 			Err ( e)  => { 
1071+ 				assert_eq ! ( 
1072+ 					e, 
1073+ 					Bolt12ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) 
1074+ 				) ; 
1075+ 			} , 
1076+ 		} 
1077+ 	} 
1078+ 
1079+ 	#[ test]  
1080+ 	fn  fails_parsing_invoice_with_extra_tlv_records ( )  { 
1081+ 		let  invoice = invoice ( ) ; 
1082+ 		let  mut  encoded_invoice = Vec :: new ( ) ; 
1083+ 		invoice. write ( & mut  encoded_invoice) . unwrap ( ) ; 
1084+ 		BigSize ( 1002 ) . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1085+ 		BigSize ( 32 ) . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1086+ 		[ 42u8 ;  32 ] . write ( & mut  encoded_invoice) . unwrap ( ) ; 
1087+ 
1088+ 		match  StaticInvoice :: try_from ( encoded_invoice)  { 
1089+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1090+ 			Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1091+ 		} 
1092+ 	} 
1093+ 
1094+ 	#[ test]  
1095+ 	fn  fails_parsing_invoice_with_invalid_offer_fields ( )  { 
1096+ 		// Error if the offer is missing paths. 
1097+ 		let  missing_offer_paths_invoice = invoice ( ) ; 
1098+ 		let  mut  tlv_stream = missing_offer_paths_invoice. as_tlv_stream ( ) ; 
1099+ 		tlv_stream. 0 . paths  = None ; 
1100+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1101+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1102+ 			Err ( e)  => { 
1103+ 				assert_eq ! ( 
1104+ 					e, 
1105+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingPaths ) 
1106+ 				) ; 
1107+ 			} , 
1108+ 		} 
1109+ 
1110+ 		// Error if the offer has more than one chain. 
1111+ 		let  invalid_offer_chains_invoice = invoice ( ) ; 
1112+ 		let  mut  tlv_stream = invalid_offer_chains_invoice. as_tlv_stream ( ) ; 
1113+ 		let  invalid_chains = vec ! [ 
1114+ 			ChainHash :: using_genesis_block( Network :: Bitcoin ) , 
1115+ 			ChainHash :: using_genesis_block( Network :: Testnet ) , 
1116+ 		] ; 
1117+ 		tlv_stream. 0 . chains  = Some ( & invalid_chains) ; 
1118+ 		match  StaticInvoice :: try_from ( tlv_stream_to_bytes ( & tlv_stream) )  { 
1119+ 			Ok ( _)  => panic ! ( "expected error" ) , 
1120+ 			Err ( e)  => { 
1121+ 				assert_eq ! ( 
1122+ 					e, 
1123+ 					Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: UnexpectedChain ) 
1124+ 				) ; 
1125+ 			} , 
1126+ 		} 
1127+ 	} 
8491128} 
0 commit comments