@@ -503,3 +503,83 @@ impl TryFrom<(OfferTlvStream, InvoiceTlvStream)> for InvoiceContents {
503
503
} )
504
504
}
505
505
}
506
+
507
+ #[ cfg( test) ]
508
+ mod tests {
509
+ use super :: { StaticInvoiceBuilder , DEFAULT_RELATIVE_EXPIRY } ;
510
+
511
+ use crate :: blinded_path:: { BlindedHop , BlindedPath , IntroductionNode } ;
512
+ use crate :: ln:: features:: { Bolt12InvoiceFeatures , OfferFeatures } ;
513
+ use crate :: ln:: inbound_payment:: ExpandedKey ;
514
+ use crate :: offers:: invoice:: SIGNATURE_TAG ;
515
+ use crate :: offers:: merkle;
516
+ use crate :: offers:: merkle:: TaggedHash ;
517
+ use crate :: offers:: offer:: { OfferBuilder , Quantity } ;
518
+ use crate :: offers:: test_utils:: * ;
519
+ use crate :: sign:: KeyMaterial ;
520
+ use crate :: util:: ser:: Writeable ;
521
+ use bitcoin:: blockdata:: constants:: ChainHash ;
522
+ use bitcoin:: network:: constants:: Network ;
523
+ use bitcoin:: secp256k1:: Secp256k1 ;
524
+
525
+ #[ test]
526
+ fn builds_invoice_for_offer_with_defaults ( ) {
527
+ let node_id = recipient_pubkey ( ) ;
528
+ let payment_paths = payment_paths ( ) ;
529
+ let now = now ( ) ;
530
+ let expanded_key = ExpandedKey :: new ( & KeyMaterial ( [ 42 ; 32 ] ) ) ;
531
+ let entropy = FixedEntropy { } ;
532
+ let secp_ctx = Secp256k1 :: new ( ) ;
533
+
534
+ let blinded_path = BlindedPath {
535
+ introduction_node : IntroductionNode :: NodeId ( pubkey ( 40 ) ) ,
536
+ blinding_point : pubkey ( 41 ) ,
537
+ blinded_hops : vec ! [
538
+ BlindedHop { blinded_node_id: pubkey( 42 ) , encrypted_payload: vec![ 0 ; 43 ] } ,
539
+ BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![ 0 ; 44 ] } ,
540
+ ] ,
541
+ } ;
542
+
543
+ let offer =
544
+ OfferBuilder :: deriving_signing_pubkey ( node_id, & expanded_key, & entropy, & secp_ctx)
545
+ . path ( blinded_path. clone ( ) )
546
+ . build ( )
547
+ . unwrap ( ) ;
548
+
549
+ let ( _offer_id, keys_opt) = offer. verify ( & expanded_key, & secp_ctx) . unwrap ( ) ;
550
+ let invoice = StaticInvoiceBuilder :: for_offer_using_keys (
551
+ & offer,
552
+ payment_paths. clone ( ) ,
553
+ now,
554
+ keys_opt. unwrap ( ) ,
555
+ )
556
+ . unwrap ( )
557
+ . build_and_sign ( & secp_ctx)
558
+ . unwrap ( ) ;
559
+
560
+ let mut buffer = Vec :: new ( ) ;
561
+ invoice. write ( & mut buffer) . unwrap ( ) ;
562
+
563
+ assert_eq ! ( invoice. bytes, buffer. as_slice( ) ) ;
564
+ assert ! ( invoice. metadata( ) . is_some( ) ) ;
565
+ assert_eq ! ( invoice. amount( ) , None ) ;
566
+ assert_eq ! ( invoice. description( ) , None ) ;
567
+ assert_eq ! ( invoice. offer_features( ) , & OfferFeatures :: empty( ) ) ;
568
+ assert_eq ! ( invoice. absolute_expiry( ) , None ) ;
569
+ assert_eq ! ( invoice. message_paths( ) , & [ blinded_path] ) ;
570
+ assert_eq ! ( invoice. issuer( ) , None ) ;
571
+ assert_eq ! ( invoice. supported_quantity( ) , Quantity :: One ) ;
572
+ assert_ne ! ( invoice. signing_pubkey( ) , recipient_pubkey( ) ) ;
573
+ assert_eq ! ( invoice. chain( ) , ChainHash :: using_genesis_block( Network :: Bitcoin ) ) ;
574
+ assert_eq ! ( invoice. payment_paths( ) , payment_paths. as_slice( ) ) ;
575
+ assert_eq ! ( invoice. created_at( ) , now) ;
576
+ assert_eq ! ( invoice. relative_expiry( ) , DEFAULT_RELATIVE_EXPIRY ) ;
577
+ #[ cfg( feature = "std" ) ]
578
+ assert ! ( !invoice. is_expired( ) ) ;
579
+ assert_eq ! ( invoice. fallbacks( ) , vec![ ] ) ;
580
+ assert_eq ! ( invoice. invoice_features( ) , & Bolt12InvoiceFeatures :: empty( ) ) ;
581
+
582
+ let message = TaggedHash :: from_valid_tlv_stream_bytes ( SIGNATURE_TAG , & invoice. bytes ) ;
583
+ assert ! ( merkle:: verify_signature( & invoice. signature, & message, recipient_pubkey( ) ) . is_ok( ) ) ;
584
+ }
585
+ }
0 commit comments