55
55
//! .allow_mpp()
56
56
//! .fallback_v0_p2wpkh(&wpubkey_hash)
57
57
//! .build()?
58
- //! .sign::<_, Infallible>(|digest| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys)))
58
+ //! .sign::<_, Infallible>(
59
+ //! |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
60
+ //! )
59
61
//! .expect("failed verifying signature")
60
62
//! .write(&mut buffer)
61
63
//! .unwrap();
84
86
//! .allow_mpp()
85
87
//! .fallback_v0_p2wpkh(&wpubkey_hash)
86
88
//! .build()?
87
- //! .sign::<_, Infallible>(|digest| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys)))
89
+ //! .sign::<_, Infallible>(
90
+ //! |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
91
+ //! )
88
92
//! .expect("failed verifying signature")
89
93
//! .write(&mut buffer)
90
94
//! .unwrap();
@@ -97,11 +101,11 @@ use bitcoin::blockdata::constants::ChainHash;
97
101
use bitcoin:: hash_types:: { WPubkeyHash , WScriptHash } ;
98
102
use bitcoin:: hashes:: Hash ;
99
103
use bitcoin:: network:: constants:: Network ;
100
- use bitcoin:: secp256k1:: { KeyPair , Message , PublicKey , Secp256k1 , self } ;
104
+ use bitcoin:: secp256k1:: { KeyPair , PublicKey , Secp256k1 , self } ;
101
105
use bitcoin:: secp256k1:: schnorr:: Signature ;
102
106
use bitcoin:: util:: address:: { Address , Payload , WitnessVersion } ;
103
107
use bitcoin:: util:: schnorr:: TweakedPublicKey ;
104
- use core:: convert:: { Infallible , TryFrom } ;
108
+ use core:: convert:: { AsRef , Infallible , TryFrom } ;
105
109
use core:: time:: Duration ;
106
110
use crate :: io;
107
111
use crate :: blinded_path:: BlindedPath ;
@@ -110,7 +114,7 @@ use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
110
114
use crate :: ln:: inbound_payment:: ExpandedKey ;
111
115
use crate :: ln:: msgs:: DecodeError ;
112
116
use crate :: offers:: invoice_request:: { INVOICE_REQUEST_PAYER_ID_TYPE , INVOICE_REQUEST_TYPES , IV_BYTES as INVOICE_REQUEST_IV_BYTES , InvoiceRequest , InvoiceRequestContents , InvoiceRequestTlvStream , InvoiceRequestTlvStreamRef } ;
113
- use crate :: offers:: merkle:: { SignError , SignatureTlvStream , SignatureTlvStreamRef , TlvStream , WithoutSignatures , self } ;
117
+ use crate :: offers:: merkle:: { SignError , SignatureTlvStream , SignatureTlvStreamRef , TaggedHash , TlvStream , WithoutSignatures , self } ;
114
118
use crate :: offers:: offer:: { Amount , OFFER_TYPES , OfferTlvStream , OfferTlvStreamRef } ;
115
119
use crate :: offers:: parse:: { Bolt12ParseError , Bolt12SemanticError , ParsedMessage } ;
116
120
use crate :: offers:: payer:: { PAYER_METADATA_TYPE , PayerTlvStream , PayerTlvStreamRef } ;
@@ -126,7 +130,8 @@ use std::time::SystemTime;
126
130
127
131
const DEFAULT_RELATIVE_EXPIRY : Duration = Duration :: from_secs ( 7200 ) ;
128
132
129
- pub ( super ) const SIGNATURE_TAG : & ' static str = concat ! ( "lightning" , "invoice" , "signature" ) ;
133
+ /// Tag for the hash function used when signing a [`Bolt12Invoice`]'s merkle root.
134
+ pub const SIGNATURE_TAG : & ' static str = concat ! ( "lightning" , "invoice" , "signature" ) ;
130
135
131
136
/// Builds a [`Bolt12Invoice`] from either:
132
137
/// - an [`InvoiceRequest`] for the "offer to be paid" flow or
@@ -331,15 +336,15 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
331
336
impl < ' a > InvoiceBuilder < ' a , ExplicitSigningPubkey > {
332
337
/// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by
333
338
/// [`UnsignedBolt12Invoice::sign`].
334
- pub fn build ( self ) -> Result < UnsignedBolt12Invoice < ' a > , Bolt12SemanticError > {
339
+ pub fn build ( self ) -> Result < UnsignedBolt12Invoice , Bolt12SemanticError > {
335
340
#[ cfg( feature = "std" ) ] {
336
341
if self . invoice . is_offer_or_refund_expired ( ) {
337
342
return Err ( Bolt12SemanticError :: AlreadyExpired ) ;
338
343
}
339
344
}
340
345
341
346
let InvoiceBuilder { invreq_bytes, invoice, .. } = self ;
342
- Ok ( UnsignedBolt12Invoice { invreq_bytes, invoice } )
347
+ Ok ( UnsignedBolt12Invoice :: new ( invreq_bytes, invoice) )
343
348
}
344
349
}
345
350
@@ -355,23 +360,42 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
355
360
}
356
361
357
362
let InvoiceBuilder { invreq_bytes, invoice, keys, .. } = self ;
358
- let unsigned_invoice = UnsignedBolt12Invoice { invreq_bytes, invoice } ;
363
+ let unsigned_invoice = UnsignedBolt12Invoice :: new ( invreq_bytes, invoice) ;
359
364
360
365
let keys = keys. unwrap ( ) ;
361
366
let invoice = unsigned_invoice
362
- . sign :: < _ , Infallible > ( |digest| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( digest, & keys) ) )
367
+ . sign :: < _ , Infallible > (
368
+ |message| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( message. as_ref ( ) . as_digest ( ) , & keys) )
369
+ )
363
370
. unwrap ( ) ;
364
371
Ok ( invoice)
365
372
}
366
373
}
367
374
368
375
/// A semantically valid [`Bolt12Invoice`] that hasn't been signed.
369
- pub struct UnsignedBolt12Invoice < ' a > {
370
- invreq_bytes : & ' a Vec < u8 > ,
376
+ pub struct UnsignedBolt12Invoice {
377
+ bytes : Vec < u8 > ,
371
378
invoice : InvoiceContents ,
379
+ tagged_hash : TaggedHash ,
372
380
}
373
381
374
- impl < ' a > UnsignedBolt12Invoice < ' a > {
382
+ impl UnsignedBolt12Invoice {
383
+ fn new ( invreq_bytes : & [ u8 ] , invoice : InvoiceContents ) -> Self {
384
+ // Use the invoice_request bytes instead of the invoice_request TLV stream as the latter may
385
+ // have contained unknown TLV records, which are not stored in `InvoiceRequestContents` or
386
+ // `RefundContents`.
387
+ let ( _, _, _, invoice_tlv_stream) = invoice. as_tlv_stream ( ) ;
388
+ let invoice_request_bytes = WithoutSignatures ( invreq_bytes) ;
389
+ let unsigned_tlv_stream = ( invoice_request_bytes, invoice_tlv_stream) ;
390
+
391
+ let mut bytes = Vec :: new ( ) ;
392
+ unsigned_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
393
+
394
+ let tagged_hash = TaggedHash :: new ( SIGNATURE_TAG , & bytes) ;
395
+
396
+ Self { bytes, invoice, tagged_hash }
397
+ }
398
+
375
399
/// The public key corresponding to the key needed to sign the invoice.
376
400
pub fn signing_pubkey ( & self ) -> PublicKey {
377
401
self . invoice . fields ( ) . signing_pubkey
@@ -380,37 +404,33 @@ impl<'a> UnsignedBolt12Invoice<'a> {
380
404
/// Signs the invoice using the given function.
381
405
///
382
406
/// This is not exported to bindings users as functions aren't currently mapped.
383
- pub fn sign < F , E > ( self , sign : F ) -> Result < Bolt12Invoice , SignError < E > >
407
+ pub fn sign < F , E > ( mut self , sign : F ) -> Result < Bolt12Invoice , SignError < E > >
384
408
where
385
- F : FnOnce ( & Message ) -> Result < Signature , E >
409
+ F : FnOnce ( & Self ) -> Result < Signature , E >
386
410
{
387
- // Use the invoice_request bytes instead of the invoice_request TLV stream as the latter may
388
- // have contained unknown TLV records, which are not stored in `InvoiceRequestContents` or
389
- // `RefundContents`.
390
- let ( _, _, _, invoice_tlv_stream) = self . invoice . as_tlv_stream ( ) ;
391
- let invoice_request_bytes = WithoutSignatures ( self . invreq_bytes ) ;
392
- let unsigned_tlv_stream = ( invoice_request_bytes, invoice_tlv_stream) ;
393
-
394
- let mut bytes = Vec :: new ( ) ;
395
- unsigned_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
396
-
397
411
let pubkey = self . invoice . fields ( ) . signing_pubkey ;
398
- let signature = merkle:: sign_message ( sign, SIGNATURE_TAG , & bytes , pubkey) ?;
412
+ let signature = merkle:: sign_message ( sign, & self , pubkey) ?;
399
413
400
414
// Append the signature TLV record to the bytes.
401
415
let signature_tlv_stream = SignatureTlvStreamRef {
402
416
signature : Some ( & signature) ,
403
417
} ;
404
- signature_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
418
+ signature_tlv_stream. write ( & mut self . bytes ) . unwrap ( ) ;
405
419
406
420
Ok ( Bolt12Invoice {
407
- bytes,
421
+ bytes : self . bytes ,
408
422
contents : self . invoice ,
409
423
signature,
410
424
} )
411
425
}
412
426
}
413
427
428
+ impl AsRef < TaggedHash > for UnsignedBolt12Invoice {
429
+ fn as_ref ( & self ) -> & TaggedHash {
430
+ & self . tagged_hash
431
+ }
432
+ }
433
+
414
434
/// A `Bolt12Invoice` is a payment request, typically corresponding to an [`Offer`] or a [`Refund`].
415
435
///
416
436
/// An invoice may be sent in response to an [`InvoiceRequest`] in the case of an offer or sent
@@ -1686,15 +1706,14 @@ mod tests {
1686
1706
. request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1687
1707
. build ( ) . unwrap ( )
1688
1708
. sign ( payer_sign) . unwrap ( ) ;
1689
- let mut unsigned_invoice = invoice_request
1709
+ let mut invoice_builder = invoice_request
1690
1710
. respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1691
1711
. fallback_v0_p2wsh ( & script. wscript_hash ( ) )
1692
1712
. fallback_v0_p2wpkh ( & pubkey. wpubkey_hash ( ) . unwrap ( ) )
1693
- . fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
1694
- . build ( ) . unwrap ( ) ;
1713
+ . fallback_v1_p2tr_tweaked ( & tweaked_pubkey) ;
1695
1714
1696
1715
// Only standard addresses will be included.
1697
- let fallbacks = unsigned_invoice . invoice . fields_mut ( ) . fallbacks . as_mut ( ) . unwrap ( ) ;
1716
+ let fallbacks = invoice_builder . invoice . fields_mut ( ) . fallbacks . as_mut ( ) . unwrap ( ) ;
1698
1717
// Non-standard addresses
1699
1718
fallbacks. push ( FallbackAddress { version : 1 , program : vec ! [ 0u8 ; 41 ] } ) ;
1700
1719
fallbacks. push ( FallbackAddress { version : 2 , program : vec ! [ 0u8 ; 1 ] } ) ;
@@ -1703,7 +1722,7 @@ mod tests {
1703
1722
fallbacks. push ( FallbackAddress { version : 1 , program : vec ! [ 0u8 ; 33 ] } ) ;
1704
1723
fallbacks. push ( FallbackAddress { version : 2 , program : vec ! [ 0u8 ; 40 ] } ) ;
1705
1724
1706
- let invoice = unsigned_invoice . sign ( recipient_sign) . unwrap ( ) ;
1725
+ let invoice = invoice_builder . build ( ) . unwrap ( ) . sign ( recipient_sign) . unwrap ( ) ;
1707
1726
let mut buffer = Vec :: new ( ) ;
1708
1727
invoice. write ( & mut buffer) . unwrap ( ) ;
1709
1728
0 commit comments