@@ -286,6 +286,11 @@ impl Refund {
286286 	pub  fn  payer_note ( & self )  -> Option < PrintableString >  { 
287287		self . contents . payer_note . as_ref ( ) . map ( |payer_note| PrintableString ( payer_note. as_str ( ) ) ) 
288288	} 
289+ 
290+ 	#[ cfg( test) ]  
291+ 	fn  as_tlv_stream ( & self )  -> RefundTlvStreamRef  { 
292+ 		self . contents . as_tlv_stream ( ) 
293+ 	} 
289294} 
290295
291296impl  AsRef < [ u8 ] >  for  Refund  { 
@@ -472,3 +477,227 @@ impl core::fmt::Display for Refund {
472477		self . fmt_bech32_str ( f) 
473478	} 
474479} 
480+ 
481+ #[ cfg( test) ]  
482+ mod  tests { 
483+ 	use  super :: { Refund ,  RefundBuilder } ; 
484+ 
485+ 	use  bitcoin:: blockdata:: constants:: ChainHash ; 
486+ 	use  bitcoin:: network:: constants:: Network ; 
487+ 	use  bitcoin:: secp256k1:: { KeyPair ,  PublicKey ,  Secp256k1 ,  SecretKey } ; 
488+ 	use  core:: convert:: TryFrom ; 
489+ 	use  core:: time:: Duration ; 
490+ 	use  crate :: ln:: features:: InvoiceRequestFeatures ; 
491+ 	use  crate :: ln:: msgs:: MAX_VALUE_MSAT ; 
492+ 	use  crate :: offers:: invoice_request:: InvoiceRequestTlvStreamRef ; 
493+ 	use  crate :: offers:: offer:: OfferTlvStreamRef ; 
494+ 	use  crate :: offers:: parse:: SemanticError ; 
495+ 	use  crate :: offers:: payer:: PayerTlvStreamRef ; 
496+ 	use  crate :: onion_message:: { BlindedHop ,  BlindedPath } ; 
497+ 	use  crate :: util:: ser:: Writeable ; 
498+ 	use  crate :: util:: string:: PrintableString ; 
499+ 
500+ 	fn  payer_pubkey ( )  -> PublicKey  { 
501+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
502+ 		KeyPair :: from_secret_key ( & secp_ctx,  & SecretKey :: from_slice ( & [ 42 ;  32 ] ) . unwrap ( ) ) . public_key ( ) 
503+ 	} 
504+ 
505+ 	fn  pubkey ( byte :  u8 )  -> PublicKey  { 
506+ 		let  secp_ctx = Secp256k1 :: new ( ) ; 
507+ 		PublicKey :: from_secret_key ( & secp_ctx,  & privkey ( byte) ) 
508+ 	} 
509+ 
510+ 	fn  privkey ( byte :  u8 )  -> SecretKey  { 
511+ 		SecretKey :: from_slice ( & [ byte;  32 ] ) . unwrap ( ) 
512+ 	} 
513+ 
514+ 	#[ test]  
515+ 	fn  builds_refund_with_defaults ( )  { 
516+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
517+ 			. build ( ) . unwrap ( ) ; 
518+ 
519+ 		let  mut  buffer = Vec :: new ( ) ; 
520+ 		refund. write ( & mut  buffer) . unwrap ( ) ; 
521+ 
522+ 		assert_eq ! ( refund. bytes,  buffer. as_slice( ) ) ; 
523+ 		assert_eq ! ( refund. metadata( ) ,  & [ 1 ;  32 ] ) ; 
524+ 		assert_eq ! ( refund. description( ) ,  PrintableString ( "foo" ) ) ; 
525+ 		assert_eq ! ( refund. absolute_expiry( ) ,  None ) ; 
526+ 		#[ cfg( feature = "std" ) ]  
527+ 		assert ! ( !refund. is_expired( ) ) ; 
528+ 		assert_eq ! ( refund. paths( ) ,  & [ ] ) ; 
529+ 		assert_eq ! ( refund. issuer( ) ,  None ) ; 
530+ 		assert_eq ! ( refund. chain( ) ,  ChainHash :: using_genesis_block( Network :: Bitcoin ) ) ; 
531+ 		assert_eq ! ( refund. amount_msats( ) ,  1000 ) ; 
532+ 		assert_eq ! ( refund. features( ) ,  & InvoiceRequestFeatures :: empty( ) ) ; 
533+ 		assert_eq ! ( refund. payer_id( ) ,  payer_pubkey( ) ) ; 
534+ 		assert_eq ! ( refund. payer_note( ) ,  None ) ; 
535+ 
536+ 		assert_eq ! ( 
537+ 			refund. as_tlv_stream( ) , 
538+ 			( 
539+ 				PayerTlvStreamRef  {  metadata:  Some ( & vec![ 1 ;  32 ] )  } , 
540+ 				OfferTlvStreamRef  { 
541+ 					chains:  None , 
542+ 					metadata:  None , 
543+ 					currency:  None , 
544+ 					amount:  None , 
545+ 					description:  Some ( & String :: from( "foo" ) ) , 
546+ 					features:  None , 
547+ 					absolute_expiry:  None , 
548+ 					paths:  None , 
549+ 					issuer:  None , 
550+ 					quantity_max:  None , 
551+ 					node_id:  None , 
552+ 				} , 
553+ 				InvoiceRequestTlvStreamRef  { 
554+ 					chain:  None , 
555+ 					amount:  Some ( 1000 ) , 
556+ 					features:  None , 
557+ 					quantity:  None , 
558+ 					payer_id:  Some ( & payer_pubkey( ) ) , 
559+ 					payer_note:  None , 
560+ 				} , 
561+ 			) , 
562+ 		) ; 
563+ 
564+ 		if  let  Err ( e)  = Refund :: try_from ( buffer)  { 
565+ 			panic ! ( "error parsing refund: {:?}" ,  e) ; 
566+ 		} 
567+ 	} 
568+ 
569+ 	#[ test]  
570+ 	fn  fails_building_refund_with_invalid_amount ( )  { 
571+ 		match  RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  MAX_VALUE_MSAT  + 1 )  { 
572+ 			Ok ( _)  => panic ! ( "expected error" ) , 
573+ 			Err ( e)  => assert_eq ! ( e,  SemanticError :: InvalidAmount ) , 
574+ 		} 
575+ 	} 
576+ 
577+ 	#[ test]  
578+ 	fn  builds_refund_with_absolute_expiry ( )  { 
579+ 		let  future_expiry = Duration :: from_secs ( u64:: max_value ( ) ) ; 
580+ 		let  past_expiry = Duration :: from_secs ( 0 ) ; 
581+ 
582+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
583+ 			. absolute_expiry ( future_expiry) 
584+ 			. build ( ) 
585+ 			. unwrap ( ) ; 
586+ 		let  ( _,  tlv_stream,  _)  = refund. as_tlv_stream ( ) ; 
587+ 		#[ cfg( feature = "std" ) ]  
588+ 		assert ! ( !refund. is_expired( ) ) ; 
589+ 		assert_eq ! ( refund. absolute_expiry( ) ,  Some ( future_expiry) ) ; 
590+ 		assert_eq ! ( tlv_stream. absolute_expiry,  Some ( future_expiry. as_secs( ) ) ) ; 
591+ 
592+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
593+ 			. absolute_expiry ( future_expiry) 
594+ 			. absolute_expiry ( past_expiry) 
595+ 			. build ( ) 
596+ 			. unwrap ( ) ; 
597+ 		let  ( _,  tlv_stream,  _)  = refund. as_tlv_stream ( ) ; 
598+ 		#[ cfg( feature = "std" ) ]  
599+ 		assert ! ( refund. is_expired( ) ) ; 
600+ 		assert_eq ! ( refund. absolute_expiry( ) ,  Some ( past_expiry) ) ; 
601+ 		assert_eq ! ( tlv_stream. absolute_expiry,  Some ( past_expiry. as_secs( ) ) ) ; 
602+ 	} 
603+ 
604+ 	#[ test]  
605+ 	fn  builds_refund_with_paths ( )  { 
606+ 		let  paths = vec ! [ 
607+ 			BlindedPath  { 
608+ 				introduction_node_id:  pubkey( 40 ) , 
609+ 				blinding_point:  pubkey( 41 ) , 
610+ 				blinded_hops:  vec![ 
611+ 					BlindedHop  {  blinded_node_id:  pubkey( 43 ) ,  encrypted_payload:  vec![ 0 ;  43 ]  } , 
612+ 					BlindedHop  {  blinded_node_id:  pubkey( 44 ) ,  encrypted_payload:  vec![ 0 ;  44 ]  } , 
613+ 				] , 
614+ 			} , 
615+ 			BlindedPath  { 
616+ 				introduction_node_id:  pubkey( 40 ) , 
617+ 				blinding_point:  pubkey( 41 ) , 
618+ 				blinded_hops:  vec![ 
619+ 					BlindedHop  {  blinded_node_id:  pubkey( 45 ) ,  encrypted_payload:  vec![ 0 ;  45 ]  } , 
620+ 					BlindedHop  {  blinded_node_id:  pubkey( 46 ) ,  encrypted_payload:  vec![ 0 ;  46 ]  } , 
621+ 				] , 
622+ 			} , 
623+ 		] ; 
624+ 
625+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
626+ 			. path ( paths[ 0 ] . clone ( ) ) 
627+ 			. path ( paths[ 1 ] . clone ( ) ) 
628+ 			. build ( ) 
629+ 			. unwrap ( ) ; 
630+ 		let  ( _,  offer_tlv_stream,  invoice_request_tlv_stream)  = refund. as_tlv_stream ( ) ; 
631+ 		assert_eq ! ( refund. paths( ) ,  paths. as_slice( ) ) ; 
632+ 		assert_eq ! ( refund. payer_id( ) ,  pubkey( 42 ) ) ; 
633+ 		assert_ne ! ( pubkey( 42 ) ,  pubkey( 44 ) ) ; 
634+ 		assert_eq ! ( offer_tlv_stream. paths,  Some ( & paths) ) ; 
635+ 		assert_eq ! ( invoice_request_tlv_stream. payer_id,  Some ( & pubkey( 42 ) ) ) ; 
636+ 	} 
637+ 
638+ 	#[ test]  
639+ 	fn  builds_refund_with_issuer ( )  { 
640+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
641+ 			. issuer ( "bar" . into ( ) ) 
642+ 			. build ( ) 
643+ 			. unwrap ( ) ; 
644+ 		let  ( _,  tlv_stream,  _)  = refund. as_tlv_stream ( ) ; 
645+ 		assert_eq ! ( refund. issuer( ) ,  Some ( PrintableString ( "bar" ) ) ) ; 
646+ 		assert_eq ! ( tlv_stream. issuer,  Some ( & String :: from( "bar" ) ) ) ; 
647+ 
648+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
649+ 			. issuer ( "bar" . into ( ) ) 
650+ 			. issuer ( "baz" . into ( ) ) 
651+ 			. build ( ) 
652+ 			. unwrap ( ) ; 
653+ 		let  ( _,  tlv_stream,  _)  = refund. as_tlv_stream ( ) ; 
654+ 		assert_eq ! ( refund. issuer( ) ,  Some ( PrintableString ( "baz" ) ) ) ; 
655+ 		assert_eq ! ( tlv_stream. issuer,  Some ( & String :: from( "baz" ) ) ) ; 
656+ 	} 
657+ 
658+ 	#[ test]  
659+ 	fn  builds_refund_with_chain ( )  { 
660+ 		let  mainnet = ChainHash :: using_genesis_block ( Network :: Bitcoin ) ; 
661+ 		let  testnet = ChainHash :: using_genesis_block ( Network :: Testnet ) ; 
662+ 
663+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
664+ 			. chain ( Network :: Bitcoin ) 
665+ 			. build ( ) . unwrap ( ) ; 
666+ 		let  ( _,  _,  tlv_stream)  = refund. as_tlv_stream ( ) ; 
667+ 		assert_eq ! ( refund. chain( ) ,  mainnet) ; 
668+ 		assert_eq ! ( tlv_stream. chain,  None ) ; 
669+ 
670+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
671+ 			. chain ( Network :: Testnet ) 
672+ 			. build ( ) . unwrap ( ) ; 
673+ 		let  ( _,  _,  tlv_stream)  = refund. as_tlv_stream ( ) ; 
674+ 		assert_eq ! ( refund. chain( ) ,  testnet) ; 
675+ 		assert_eq ! ( tlv_stream. chain,  Some ( & testnet) ) ; 
676+ 
677+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
678+ 			. chain ( Network :: Regtest ) 
679+ 			. chain ( Network :: Testnet ) 
680+ 			. build ( ) . unwrap ( ) ; 
681+ 		let  ( _,  _,  tlv_stream)  = refund. as_tlv_stream ( ) ; 
682+ 		assert_eq ! ( refund. chain( ) ,  testnet) ; 
683+ 		assert_eq ! ( tlv_stream. chain,  Some ( & testnet) ) ; 
684+ 	} 
685+ 
686+ 	#[ test]  
687+ 	fn  builds_refund_with_payer_note ( )  { 
688+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
689+ 			. payer_note ( "bar" . into ( ) ) 
690+ 			. build ( ) . unwrap ( ) ; 
691+ 		let  ( _,  _,  tlv_stream)  = refund. as_tlv_stream ( ) ; 
692+ 		assert_eq ! ( refund. payer_note( ) ,  Some ( PrintableString ( "bar" ) ) ) ; 
693+ 		assert_eq ! ( tlv_stream. payer_note,  Some ( & String :: from( "bar" ) ) ) ; 
694+ 
695+ 		let  refund = RefundBuilder :: new ( "foo" . into ( ) ,  vec ! [ 1 ;  32 ] ,  payer_pubkey ( ) ,  1000 ) . unwrap ( ) 
696+ 			. payer_note ( "bar" . into ( ) ) 
697+ 			. payer_note ( "baz" . into ( ) ) 
698+ 			. build ( ) . unwrap ( ) ; 
699+ 		let  ( _,  _,  tlv_stream)  = refund. as_tlv_stream ( ) ; 
700+ 		assert_eq ! ( refund. payer_note( ) ,  Some ( PrintableString ( "baz" ) ) ) ; 
701+ 		assert_eq ! ( tlv_stream. payer_note,  Some ( & String :: from( "baz" ) ) ) ; 
702+ 	} 
703+ } 
0 commit comments