@@ -1361,7 +1361,7 @@ impl Readable for InvoiceRequestFields {
13611361
13621362#[ cfg( test) ]
13631363mod tests {
1364- use super :: { ExperimentalInvoiceRequestTlvStreamRef , INVOICE_REQUEST_TYPES , InvoiceRequest , InvoiceRequestFields , InvoiceRequestTlvStreamRef , PAYER_NOTE_LIMIT , SIGNATURE_TAG , UnsignedInvoiceRequest } ;
1364+ use super :: { EXPERIMENTAL_INVOICE_REQUEST_TYPES , ExperimentalInvoiceRequestTlvStreamRef , INVOICE_REQUEST_TYPES , InvoiceRequest , InvoiceRequestFields , InvoiceRequestTlvStreamRef , PAYER_NOTE_LIMIT , SIGNATURE_TAG , UnsignedInvoiceRequest } ;
13651365
13661366 use bitcoin:: constants:: ChainHash ;
13671367 use bitcoin:: network:: Network ;
@@ -1375,7 +1375,7 @@ mod tests {
13751375 use crate :: ln:: inbound_payment:: ExpandedKey ;
13761376 use crate :: ln:: msgs:: { DecodeError , MAX_VALUE_MSAT } ;
13771377 use crate :: offers:: invoice:: { Bolt12Invoice , SIGNATURE_TAG as INVOICE_SIGNATURE_TAG } ;
1378- use crate :: offers:: merkle:: { SignError , SignatureTlvStreamRef , TaggedHash , self } ;
1378+ use crate :: offers:: merkle:: { SignError , SignatureTlvStreamRef , TaggedHash , TlvStream , self } ;
13791379 use crate :: offers:: nonce:: Nonce ;
13801380 use crate :: offers:: offer:: { Amount , ExperimentalOfferTlvStreamRef , OfferTlvStreamRef , Quantity } ;
13811381 #[ cfg( not( c_bindings) ) ]
@@ -2525,10 +2525,118 @@ mod tests {
25252525 }
25262526 }
25272527
2528+ #[ test]
2529+ fn parses_invoice_request_with_experimental_tlv_records ( ) {
2530+ const UNKNOWN_ODD_TYPE : u64 = EXPERIMENTAL_INVOICE_REQUEST_TYPES . start + 1 ;
2531+ assert ! ( UNKNOWN_ODD_TYPE % 2 == 1 ) ;
2532+
2533+ let secp_ctx = Secp256k1 :: new ( ) ;
2534+ let keys = Keypair :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
2535+ let mut unsigned_invoice_request = OfferBuilder :: new ( keys. public_key ( ) )
2536+ . amount_msats ( 1000 )
2537+ . build ( ) . unwrap ( )
2538+ . request_invoice ( vec ! [ 1 ; 32 ] , keys. public_key ( ) ) . unwrap ( )
2539+ . build ( ) . unwrap ( ) ;
2540+
2541+ let mut unknown_bytes = Vec :: new ( ) ;
2542+ BigSize ( UNKNOWN_ODD_TYPE ) . write ( & mut unknown_bytes) . unwrap ( ) ;
2543+ BigSize ( 32 ) . write ( & mut unknown_bytes) . unwrap ( ) ;
2544+ [ 42u8 ; 32 ] . write ( & mut unknown_bytes) . unwrap ( ) ;
2545+
2546+ unsigned_invoice_request. bytes . reserve_exact (
2547+ unsigned_invoice_request. bytes . capacity ( )
2548+ - unsigned_invoice_request. bytes . len ( )
2549+ + unknown_bytes. len ( ) ,
2550+ ) ;
2551+ unsigned_invoice_request. experimental_bytes . extend_from_slice ( & unknown_bytes) ;
2552+
2553+ let tlv_stream = TlvStream :: new ( & unsigned_invoice_request. bytes )
2554+ . chain ( TlvStream :: new ( & unsigned_invoice_request. experimental_bytes ) ) ;
2555+ unsigned_invoice_request. tagged_hash =
2556+ TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
2557+
2558+ let invoice_request = unsigned_invoice_request
2559+ . sign ( |message : & UnsignedInvoiceRequest |
2560+ Ok ( secp_ctx. sign_schnorr_no_aux_rand ( message. as_ref ( ) . as_digest ( ) , & keys) )
2561+ )
2562+ . unwrap ( ) ;
2563+
2564+ let mut encoded_invoice_request = Vec :: new ( ) ;
2565+ invoice_request. write ( & mut encoded_invoice_request) . unwrap ( ) ;
2566+
2567+ match InvoiceRequest :: try_from ( encoded_invoice_request. clone ( ) ) {
2568+ Ok ( invoice_request) => assert_eq ! ( invoice_request. bytes, encoded_invoice_request) ,
2569+ Err ( e) => panic ! ( "error parsing invoice_request: {:?}" , e) ,
2570+ }
2571+
2572+ const UNKNOWN_EVEN_TYPE : u64 = EXPERIMENTAL_INVOICE_REQUEST_TYPES . start ;
2573+ assert ! ( UNKNOWN_EVEN_TYPE % 2 == 0 ) ;
2574+
2575+ let mut unsigned_invoice_request = OfferBuilder :: new ( keys. public_key ( ) )
2576+ . amount_msats ( 1000 )
2577+ . build ( ) . unwrap ( )
2578+ . request_invoice ( vec ! [ 1 ; 32 ] , keys. public_key ( ) ) . unwrap ( )
2579+ . build ( ) . unwrap ( ) ;
2580+
2581+ let mut unknown_bytes = Vec :: new ( ) ;
2582+ BigSize ( UNKNOWN_EVEN_TYPE ) . write ( & mut unknown_bytes) . unwrap ( ) ;
2583+ BigSize ( 32 ) . write ( & mut unknown_bytes) . unwrap ( ) ;
2584+ [ 42u8 ; 32 ] . write ( & mut unknown_bytes) . unwrap ( ) ;
2585+
2586+ unsigned_invoice_request. bytes . reserve_exact (
2587+ unsigned_invoice_request. bytes . capacity ( )
2588+ - unsigned_invoice_request. bytes . len ( )
2589+ + unknown_bytes. len ( ) ,
2590+ ) ;
2591+ unsigned_invoice_request. experimental_bytes . extend_from_slice ( & unknown_bytes) ;
2592+
2593+ let tlv_stream = TlvStream :: new ( & unsigned_invoice_request. bytes )
2594+ . chain ( TlvStream :: new ( & unsigned_invoice_request. experimental_bytes ) ) ;
2595+ unsigned_invoice_request. tagged_hash =
2596+ TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
2597+
2598+ let invoice_request = unsigned_invoice_request
2599+ . sign ( |message : & UnsignedInvoiceRequest |
2600+ Ok ( secp_ctx. sign_schnorr_no_aux_rand ( message. as_ref ( ) . as_digest ( ) , & keys) )
2601+ )
2602+ . unwrap ( ) ;
2603+
2604+ let mut encoded_invoice_request = Vec :: new ( ) ;
2605+ invoice_request. write ( & mut encoded_invoice_request) . unwrap ( ) ;
2606+
2607+ match InvoiceRequest :: try_from ( encoded_invoice_request) {
2608+ Ok ( _) => panic ! ( "expected error" ) ,
2609+ Err ( e) => assert_eq ! ( e, Bolt12ParseError :: Decode ( DecodeError :: UnknownRequiredFeature ) ) ,
2610+ }
2611+
2612+ let invoice_request = OfferBuilder :: new ( keys. public_key ( ) )
2613+ . amount_msats ( 1000 )
2614+ . build ( ) . unwrap ( )
2615+ . request_invoice ( vec ! [ 1 ; 32 ] , keys. public_key ( ) ) . unwrap ( )
2616+ . build ( ) . unwrap ( )
2617+ . sign ( |message : & UnsignedInvoiceRequest |
2618+ Ok ( secp_ctx. sign_schnorr_no_aux_rand ( message. as_ref ( ) . as_digest ( ) , & keys) )
2619+ )
2620+ . unwrap ( ) ;
2621+
2622+ let mut encoded_invoice_request = Vec :: new ( ) ;
2623+ invoice_request. write ( & mut encoded_invoice_request) . unwrap ( ) ;
2624+
2625+ BigSize ( UNKNOWN_ODD_TYPE ) . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2626+ BigSize ( 32 ) . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2627+ [ 42u8 ; 32 ] . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2628+
2629+ match InvoiceRequest :: try_from ( encoded_invoice_request) {
2630+ Ok ( _) => panic ! ( "expected error" ) ,
2631+ Err ( e) => assert_eq ! ( e, Bolt12ParseError :: InvalidSignature ( secp256k1:: Error :: IncorrectSignature ) ) ,
2632+ }
2633+ }
2634+
25282635 #[ test]
25292636 fn fails_parsing_invoice_request_with_out_of_range_tlv_records ( ) {
25302637 let secp_ctx = Secp256k1 :: new ( ) ;
25312638 let keys = Keypair :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
2639+
25322640 let invoice_request = OfferBuilder :: new ( keys. public_key ( ) )
25332641 . amount_msats ( 1000 )
25342642 . build ( ) . unwrap ( )
@@ -2549,6 +2657,17 @@ mod tests {
25492657 Ok ( _) => panic ! ( "expected error" ) ,
25502658 Err ( e) => assert_eq ! ( e, Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) ,
25512659 }
2660+
2661+ let mut encoded_invoice_request = Vec :: new ( ) ;
2662+ invoice_request. write ( & mut encoded_invoice_request) . unwrap ( ) ;
2663+ BigSize ( EXPERIMENTAL_INVOICE_REQUEST_TYPES . end ) . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2664+ BigSize ( 32 ) . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2665+ [ 42u8 ; 32 ] . write ( & mut encoded_invoice_request) . unwrap ( ) ;
2666+
2667+ match InvoiceRequest :: try_from ( encoded_invoice_request) {
2668+ Ok ( _) => panic ! ( "expected error" ) ,
2669+ Err ( e) => assert_eq ! ( e, Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) ,
2670+ }
25522671 }
25532672
25542673 #[ test]
0 commit comments