24
24
//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
25
25
//! use core::convert::{Infallible, TryFrom};
26
26
//! use lightning::offers::invoice_request::InvoiceRequest;
27
+ //! use lightning::offers::merkle::AsDigest;
27
28
//! use lightning::offers::refund::Refund;
28
29
//! use lightning::util::ser::Writeable;
29
30
//!
87
88
//! .fallback_v0_p2wpkh(&wpubkey_hash)
88
89
//! .build()?
89
90
//! .sign::<_, Infallible>(
90
- //! |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
91
+ //! |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(& message.as_ref().as_digest(), &keys))
91
92
//! )
92
93
//! .expect("failed verifying signature")
93
94
//! .write(&mut buffer)
@@ -115,7 +116,7 @@ use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures, InvoiceRequ
115
116
use crate :: ln:: inbound_payment:: ExpandedKey ;
116
117
use crate :: ln:: msgs:: DecodeError ;
117
118
use crate :: offers:: invoice_request:: { INVOICE_REQUEST_PAYER_ID_TYPE , INVOICE_REQUEST_TYPES , IV_BYTES as INVOICE_REQUEST_IV_BYTES , InvoiceRequest , InvoiceRequestContents , InvoiceRequestTlvStream , InvoiceRequestTlvStreamRef } ;
118
- use crate :: offers:: merkle:: { SignError , SignatureTlvStream , SignatureTlvStreamRef , TaggedHash , TlvStream , WithoutSignatures , self } ;
119
+ use crate :: offers:: merkle:: { AsDigest , RawData , SignError , SignatureData , SignatureTlvStream , SignatureTlvStreamRef , TaggedHash , TlvStream , WithoutSignatures , self } ;
119
120
use crate :: offers:: offer:: { Amount , OFFER_TYPES , OfferTlvStream , OfferTlvStreamRef , Quantity } ;
120
121
use crate :: offers:: parse:: { Bolt12ParseError , Bolt12SemanticError , ParsedMessage } ;
121
122
use crate :: offers:: payer:: { PAYER_METADATA_TYPE , PayerTlvStream , PayerTlvStreamRef } ;
@@ -149,6 +150,7 @@ pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> {
149
150
invreq_bytes : & ' a Vec < u8 > ,
150
151
invoice : InvoiceContents ,
151
152
signing_pubkey_strategy : S ,
153
+ raw_data : bool ,
152
154
}
153
155
154
156
/// Indicates how [`Bolt12Invoice::signing_pubkey`] was set.
@@ -183,12 +185,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
183
185
) ,
184
186
} ;
185
187
186
- Self :: new ( & invoice_request. bytes , contents, ExplicitSigningPubkey { } )
188
+ Self :: new ( & invoice_request. bytes , contents, ExplicitSigningPubkey { } , false )
187
189
}
188
190
189
191
pub ( super ) fn for_refund (
190
192
refund : & ' a Refund , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , created_at : Duration ,
191
- payment_hash : PaymentHash , signing_pubkey : PublicKey
193
+ payment_hash : PaymentHash , signing_pubkey : PublicKey ,
192
194
) -> Result < Self , Bolt12SemanticError > {
193
195
let amount_msats = refund. amount_msats ( ) ;
194
196
let contents = InvoiceContents :: ForRefund {
@@ -198,7 +200,7 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
198
200
) ,
199
201
} ;
200
202
201
- Self :: new ( & refund. bytes , contents, ExplicitSigningPubkey { } )
203
+ Self :: new ( & refund. bytes , contents, ExplicitSigningPubkey { } , false )
202
204
}
203
205
}
204
206
@@ -216,12 +218,12 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
216
218
) ,
217
219
} ;
218
220
219
- Self :: new ( & invoice_request. bytes , contents, DerivedSigningPubkey ( keys) )
221
+ Self :: new ( & invoice_request. bytes , contents, DerivedSigningPubkey ( keys) , false )
220
222
}
221
223
222
224
pub ( super ) fn for_refund_using_keys (
223
225
refund : & ' a Refund , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , created_at : Duration ,
224
- payment_hash : PaymentHash , keys : KeyPair ,
226
+ payment_hash : PaymentHash , keys : KeyPair
225
227
) -> Result < Self , Bolt12SemanticError > {
226
228
let amount_msats = refund. amount_msats ( ) ;
227
229
let signing_pubkey = keys. public_key ( ) ;
@@ -232,7 +234,7 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
232
234
) ,
233
235
} ;
234
236
235
- Self :: new ( & refund. bytes , contents, DerivedSigningPubkey ( keys) )
237
+ Self :: new ( & refund. bytes , contents, DerivedSigningPubkey ( keys) , false )
236
238
}
237
239
}
238
240
@@ -262,13 +264,14 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
262
264
}
263
265
264
266
fn new (
265
- invreq_bytes : & ' a Vec < u8 > , contents : InvoiceContents , signing_pubkey_strategy : S
267
+ invreq_bytes : & ' a Vec < u8 > , contents : InvoiceContents , signing_pubkey_strategy : S ,
268
+ raw_data : bool ,
266
269
) -> Result < Self , Bolt12SemanticError > {
267
270
if contents. fields ( ) . payment_paths . is_empty ( ) {
268
271
return Err ( Bolt12SemanticError :: MissingPaths ) ;
269
272
}
270
273
271
- Ok ( Self { invreq_bytes, invoice : contents, signing_pubkey_strategy } )
274
+ Ok ( Self { invreq_bytes, invoice : contents, signing_pubkey_strategy, raw_data } )
272
275
}
273
276
274
277
/// Sets the [`Bolt12Invoice::relative_expiry`] as seconds since [`Bolt12Invoice::created_at`].
@@ -327,6 +330,13 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
327
330
self . invoice . fields_mut ( ) . features . set_basic_mpp_optional ( ) ;
328
331
self
329
332
}
333
+
334
+ /// Indicates that instead of forming a fully formed tagged hash to sign when building and
335
+ /// UnsignedBolt12Invoice, we'd like to pass the signer function the raw data instead.
336
+ pub fn raw_data ( mut self ) -> Self {
337
+ self . raw_data = true ;
338
+ self
339
+ }
330
340
}
331
341
332
342
impl < ' a > InvoiceBuilder < ' a , ExplicitSigningPubkey > {
@@ -340,7 +350,7 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
340
350
}
341
351
342
352
let InvoiceBuilder { invreq_bytes, invoice, .. } = self ;
343
- Ok ( UnsignedBolt12Invoice :: new ( invreq_bytes, invoice) )
353
+ Ok ( UnsignedBolt12Invoice :: new ( invreq_bytes, invoice, self . raw_data ) )
344
354
}
345
355
}
346
356
@@ -356,13 +366,13 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
356
366
}
357
367
358
368
let InvoiceBuilder {
359
- invreq_bytes, invoice, signing_pubkey_strategy : DerivedSigningPubkey ( keys)
369
+ invreq_bytes, invoice, signing_pubkey_strategy : DerivedSigningPubkey ( keys) , raw_data ,
360
370
} = self ;
361
- let unsigned_invoice = UnsignedBolt12Invoice :: new ( invreq_bytes, invoice) ;
371
+ let unsigned_invoice = UnsignedBolt12Invoice :: new ( invreq_bytes, invoice, self . raw_data ) ;
362
372
363
373
let invoice = unsigned_invoice
364
374
. sign :: < _ , Infallible > (
365
- |message| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( message. as_ref ( ) . as_digest ( ) , & keys) )
375
+ |message| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( & message. as_ref ( ) . as_digest ( ) , & keys) )
366
376
)
367
377
. unwrap ( ) ;
368
378
Ok ( invoice)
@@ -378,11 +388,11 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
378
388
pub struct UnsignedBolt12Invoice {
379
389
bytes : Vec < u8 > ,
380
390
contents : InvoiceContents ,
381
- tagged_hash : TaggedHash ,
391
+ data_to_sign : SignatureData ,
382
392
}
383
393
384
394
impl UnsignedBolt12Invoice {
385
- fn new ( invreq_bytes : & [ u8 ] , contents : InvoiceContents ) -> Self {
395
+ fn new ( invreq_bytes : & [ u8 ] , contents : InvoiceContents , raw_data : bool ) -> Self {
386
396
// Use the invoice_request bytes instead of the invoice_request TLV stream as the latter may
387
397
// have contained unknown TLV records, which are not stored in `InvoiceRequestContents` or
388
398
// `RefundContents`.
@@ -393,14 +403,20 @@ impl UnsignedBolt12Invoice {
393
403
let mut bytes = Vec :: new ( ) ;
394
404
unsigned_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
395
405
396
- let tagged_hash = TaggedHash :: new ( SIGNATURE_TAG , & bytes) ;
406
+ let mut data_to_sign = SignatureData :: TaggedHash ( TaggedHash :: new ( SIGNATURE_TAG , & bytes) ) ;
407
+ if raw_data {
408
+ data_to_sign = SignatureData :: RawData ( RawData :: new ( SIGNATURE_TAG , & bytes) )
409
+ }
397
410
398
- Self { bytes, contents, tagged_hash }
411
+ Self { bytes, contents, data_to_sign }
399
412
}
400
413
401
414
/// Returns the [`TaggedHash`] of the invoice to sign.
402
415
pub fn tagged_hash ( & self ) -> & TaggedHash {
403
- & self . tagged_hash
416
+ match & self . data_to_sign {
417
+ SignatureData :: TaggedHash ( tagged_hash) => tagged_hash,
418
+ SignatureData :: RawData ( _) => panic ! ( "tagged hash doesn't exist" ) ,
419
+ }
404
420
}
405
421
406
422
/// Signs the [`TaggedHash`] of the invoice using the given function.
@@ -429,10 +445,10 @@ impl UnsignedBolt12Invoice {
429
445
}
430
446
}
431
447
432
- impl AsRef < TaggedHash > for UnsignedBolt12Invoice {
433
- fn as_ref ( & self ) -> & TaggedHash {
434
- & self . tagged_hash
435
- }
448
+ impl AsRef < SignatureData > for UnsignedBolt12Invoice {
449
+ fn as_ref ( & self ) -> & SignatureData {
450
+ & self . data_to_sign
451
+ }
436
452
}
437
453
438
454
/// A `Bolt12Invoice` is a payment request, typically corresponding to an [`Offer`] or a [`Refund`].
@@ -1042,9 +1058,9 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
1042
1058
( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream)
1043
1059
) ?;
1044
1060
1045
- let tagged_hash = TaggedHash :: new ( SIGNATURE_TAG , & bytes) ;
1061
+ let data_to_sign = SignatureData :: TaggedHash ( TaggedHash :: new ( SIGNATURE_TAG , & bytes) ) ;
1046
1062
1047
- Ok ( UnsignedBolt12Invoice { bytes, contents, tagged_hash } )
1063
+ Ok ( UnsignedBolt12Invoice { bytes, contents, data_to_sign } )
1048
1064
}
1049
1065
}
1050
1066
@@ -1368,7 +1384,7 @@ mod tests {
1368
1384
Err ( e) => panic ! ( "error parsing unsigned invoice: {:?}" , e) ,
1369
1385
Ok ( parsed) => {
1370
1386
assert_eq ! ( parsed. bytes, unsigned_invoice. bytes) ;
1371
- assert_eq ! ( parsed. tagged_hash, unsigned_invoice. tagged_hash) ;
1387
+ assert_eq ! ( parsed. tagged_hash( ) , unsigned_invoice. tagged_hash( ) ) ;
1372
1388
} ,
1373
1389
}
1374
1390
0 commit comments