Skip to content

Commit ab17126

Browse files
committed
f - TaggedBytes for lazy digest calculation
1 parent 369374a commit ab17126

File tree

7 files changed

+63
-43
lines changed

7 files changed

+63
-43
lines changed

fuzz/src/invoice_request_deser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
3838
if signing_pubkey == odd_pubkey || signing_pubkey == even_pubkey {
3939
unsigned_invoice
4040
.sign::<_, Infallible>(
41-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
41+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
4242
)
4343
.unwrap()
4444
.write(&mut buffer)
4545
.unwrap();
4646
} else {
4747
unsigned_invoice
4848
.sign::<_, Infallible>(
49-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
49+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
5050
)
5151
.unwrap_err();
5252
}

fuzz/src/offer_deser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
3030
if let Ok(invoice_request) = build_response(&offer, pubkey) {
3131
invoice_request
3232
.sign::<_, Infallible>(
33-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
33+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
3434
)
3535
.unwrap()
3636
.write(&mut buffer)

fuzz/src/refund_deser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
3434
if let Ok(invoice) = build_response(&refund, pubkey, &secp_ctx) {
3535
invoice
3636
.sign::<_, Infallible>(
37-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
37+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
3838
)
3939
.unwrap()
4040
.write(&mut buffer)

lightning/src/offers/invoice.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
//! .allow_mpp()
5656
//! .fallback_v0_p2wpkh(&wpubkey_hash)
5757
//! .build()?
58-
//! .sign::<_, Infallible>(|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys)))
58+
//! .sign::<_, Infallible>(|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys)))
5959
//! .expect("failed verifying signature")
6060
//! .write(&mut buffer)
6161
//! .unwrap();
@@ -84,7 +84,7 @@
8484
//! .allow_mpp()
8585
//! .fallback_v0_p2wpkh(&wpubkey_hash)
8686
//! .build()?
87-
//! .sign::<_, Infallible>(|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys)))
87+
//! .sign::<_, Infallible>(|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys)))
8888
//! .expect("failed verifying signature")
8989
//! .write(&mut buffer)
9090
//! .unwrap();
@@ -97,7 +97,7 @@ use bitcoin::blockdata::constants::ChainHash;
9797
use bitcoin::hash_types::{WPubkeyHash, WScriptHash};
9898
use bitcoin::hashes::Hash;
9999
use bitcoin::network::constants::Network;
100-
use bitcoin::secp256k1::{KeyPair, Message, PublicKey, Secp256k1, self};
100+
use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
101101
use bitcoin::secp256k1::schnorr::Signature;
102102
use bitcoin::util::address::{Address, Payload, WitnessVersion};
103103
use bitcoin::util::schnorr::TweakedPublicKey;
@@ -110,7 +110,7 @@ use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
110110
use crate::ln::inbound_payment::ExpandedKey;
111111
use crate::ln::msgs::DecodeError;
112112
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};
113+
use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedBytes, TlvStream, WithoutSignatures, self};
114114
use crate::offers::offer::{Amount, OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef};
115115
use crate::offers::parse::{ParseError, ParsedMessage, SemanticError};
116116
use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef};
@@ -359,7 +359,7 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
359359
let keys = keys.unwrap();
360360
let invoice = unsigned_invoice
361361
.sign::<_, Infallible>(
362-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
362+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
363363
)
364364
.unwrap();
365365
Ok(invoice)
@@ -383,7 +383,7 @@ impl<'a> UnsignedInvoice<'a> {
383383
/// This is not exported to bindings users as functions aren't currently mapped.
384384
pub fn sign<F, E>(self, sign: F) -> Result<Invoice, SignError<E>>
385385
where
386-
F: FnOnce(&Message, &str, &[u8], &[u8]) -> Result<Signature, E>
386+
F: FnOnce(TaggedBytes, &[u8]) -> Result<Signature, E>
387387
{
388388
// Use the invoice_request bytes instead of the invoice_request TLV stream as the latter may
389389
// have contained unknown TLV records, which are not stored in `InvoiceRequestContents` or
@@ -395,9 +395,10 @@ impl<'a> UnsignedInvoice<'a> {
395395
let mut bytes = Vec::new();
396396
unsigned_tlv_stream.write(&mut bytes).unwrap();
397397

398+
let message = TaggedBytes::new(SIGNATURE_TAG, &bytes);
398399
let metadata = self.invoice.metadata();
399400
let pubkey = self.invoice.fields().signing_pubkey;
400-
let signature = merkle::sign_message(sign, SIGNATURE_TAG, &bytes, metadata, pubkey)?;
401+
let signature = merkle::sign_message(sign, message, metadata, pubkey)?;
401402

402403
// Append the signature TLV record to the bytes.
403404
let signature_tlv_stream = SignatureTlvStreamRef {
@@ -1468,7 +1469,7 @@ mod tests {
14681469
.sign(payer_sign).unwrap()
14691470
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
14701471
.build().unwrap()
1471-
.sign(|_, _, _, _| Err(()))
1472+
.sign(|_, _| Err(()))
14721473
{
14731474
Ok(_) => panic!("expected error"),
14741475
Err(e) => assert_eq!(e, SignError::Signing(())),

lightning/src/offers/invoice_request.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
//! .quantity(5)?
4545
//! .payer_note("foo".to_string())
4646
//! .build()?
47-
//! .sign::<_, Infallible>(|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys)))
47+
//! .sign::<_, Infallible>(|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys)))
4848
//! .expect("failed verifying signature")
4949
//! .write(&mut buffer)
5050
//! .unwrap();
@@ -54,7 +54,7 @@
5454
5555
use bitcoin::blockdata::constants::ChainHash;
5656
use bitcoin::network::constants::Network;
57-
use bitcoin::secp256k1::{KeyPair, Message, PublicKey, Secp256k1, self};
57+
use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
5858
use bitcoin::secp256k1::schnorr::Signature;
5959
use core::convert::{Infallible, TryFrom};
6060
use core::ops::Deref;
@@ -66,7 +66,7 @@ use crate::ln::features::InvoiceRequestFeatures;
6666
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
6767
use crate::ln::msgs::DecodeError;
6868
use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder};
69-
use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, self};
69+
use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedBytes, self};
7070
use crate::offers::offer::{Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef};
7171
use crate::offers::parse::{ParseError, ParsedMessage, SemanticError};
7272
use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef};
@@ -307,7 +307,7 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId
307307
let keys = keys.unwrap();
308308
let invoice_request = unsigned_invoice_request
309309
.sign::<_, Infallible>(
310-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
310+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
311311
)
312312
.unwrap();
313313
Ok(invoice_request)
@@ -354,7 +354,7 @@ impl<'a> UnsignedInvoiceRequest<'a> {
354354
/// This is not exported to bindings users as functions are not yet mapped.
355355
pub fn sign<F, E>(self, sign: F) -> Result<InvoiceRequest, SignError<E>>
356356
where
357-
F: FnOnce(&Message, &str, &[u8], &[u8]) -> Result<Signature, E>
357+
F: FnOnce(TaggedBytes, &[u8]) -> Result<Signature, E>
358358
{
359359
// Use the offer bytes instead of the offer TLV stream as the offer may have contained
360360
// unknown TLV records, which are not stored in `OfferContents`.
@@ -366,9 +366,10 @@ impl<'a> UnsignedInvoiceRequest<'a> {
366366
let mut bytes = Vec::new();
367367
unsigned_tlv_stream.write(&mut bytes).unwrap();
368368

369+
let message = TaggedBytes::new(SIGNATURE_TAG, &bytes);
369370
let metadata = self.offer.metadata().map(|metadata| metadata.as_slice()).unwrap_or(&[]);
370371
let pubkey = self.invoice_request.payer_id;
371-
let signature = merkle::sign_message(sign, SIGNATURE_TAG, &bytes, metadata, pubkey)?;
372+
let signature = merkle::sign_message(sign, message, metadata, pubkey)?;
372373

373374
// Append the signature TLV record to the bytes.
374375
let signature_tlv_stream = SignatureTlvStreamRef {
@@ -793,7 +794,7 @@ mod tests {
793794
use crate::ln::inbound_payment::ExpandedKey;
794795
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
795796
use crate::offers::invoice::{Invoice, SIGNATURE_TAG as INVOICE_SIGNATURE_TAG};
796-
use crate::offers::merkle::{SignError, SignatureTlvStreamRef, self};
797+
use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedBytes, self};
797798
use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity};
798799
use crate::offers::parse::{ParseError, SemanticError};
799800
use crate::offers::payer::PayerTlvStreamRef;
@@ -925,9 +926,9 @@ mod tests {
925926
let mut bytes = Vec::new();
926927
tlv_stream.write(&mut bytes).unwrap();
927928

929+
let message = TaggedBytes::new(INVOICE_SIGNATURE_TAG, &bytes);
928930
let signature = merkle::sign_message(
929-
recipient_sign, INVOICE_SIGNATURE_TAG, &bytes, invoice_request.metadata(),
930-
recipient_pubkey()
931+
recipient_sign, message, invoice_request.metadata(), recipient_pubkey()
931932
).unwrap();
932933
signature_tlv_stream.signature = Some(&signature);
933934

@@ -950,8 +951,9 @@ mod tests {
950951
let mut bytes = Vec::new();
951952
tlv_stream.write(&mut bytes).unwrap();
952953

954+
let message = TaggedBytes::new(INVOICE_SIGNATURE_TAG, &bytes);
953955
let signature = merkle::sign_message(
954-
recipient_sign, INVOICE_SIGNATURE_TAG, &bytes, &metadata, recipient_pubkey()
956+
recipient_sign, message, &metadata, recipient_pubkey()
955957
).unwrap();
956958
signature_tlv_stream.signature = Some(&signature);
957959

@@ -996,9 +998,9 @@ mod tests {
996998
let mut bytes = Vec::new();
997999
tlv_stream.write(&mut bytes).unwrap();
9981000

1001+
let message = TaggedBytes::new(INVOICE_SIGNATURE_TAG, &bytes);
9991002
let signature = merkle::sign_message(
1000-
recipient_sign, INVOICE_SIGNATURE_TAG, &bytes, invoice_request.metadata(),
1001-
recipient_pubkey()
1003+
recipient_sign, message, invoice_request.metadata(), recipient_pubkey()
10021004
).unwrap();
10031005
signature_tlv_stream.signature = Some(&signature);
10041006

@@ -1021,9 +1023,9 @@ mod tests {
10211023
let mut bytes = Vec::new();
10221024
tlv_stream.write(&mut bytes).unwrap();
10231025

1026+
let message = TaggedBytes::new(INVOICE_SIGNATURE_TAG, &bytes);
10241027
let signature = merkle::sign_message(
1025-
recipient_sign, INVOICE_SIGNATURE_TAG, &bytes, invoice_request.metadata(),
1026-
recipient_pubkey()
1028+
recipient_sign, message, invoice_request.metadata(), recipient_pubkey()
10271029
).unwrap();
10281030
signature_tlv_stream.signature = Some(&signature);
10291031

@@ -1363,7 +1365,7 @@ mod tests {
13631365
.build().unwrap()
13641366
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
13651367
.build().unwrap()
1366-
.sign(|_, _, _, _| Err(()))
1368+
.sign(|_, _| Err(()))
13671369
{
13681370
Ok(_) => panic!("expected error"),
13691371
Err(e) => assert_eq!(e, SignError::Signing(())),
@@ -1778,7 +1780,7 @@ mod tests {
17781780
.request_invoice(vec![1; 32], keys.public_key()).unwrap()
17791781
.build().unwrap()
17801782
.sign::<_, Infallible>(
1781-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
1783+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
17821784
)
17831785
.unwrap();
17841786

lightning/src/offers/merkle.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ tlv_stream!(SignatureTlvStream, SignatureTlvStreamRef, SIGNATURE_TYPES, {
2424
(240, signature: Signature),
2525
});
2626

27+
/// Bytes associated with a tag, which is used to produced a [`Message`] digest to sign.
28+
pub struct TaggedBytes<'a> {
29+
tag: &'a str,
30+
bytes: &'a [u8],
31+
}
32+
33+
impl<'a> TaggedBytes<'a> {
34+
/// Creates tagged bytes with the given parameters.
35+
pub fn new(tag: &'a str, bytes: &'a [u8]) -> Self {
36+
Self { tag, bytes }
37+
}
38+
39+
/// Returns the digest to sign.
40+
pub fn digest(&self) -> Message {
41+
message_digest(self.tag, self.bytes)
42+
}
43+
}
44+
2745
/// Error when signing messages.
2846
#[derive(Debug, PartialEq)]
2947
pub enum SignError<E> {
@@ -41,17 +59,17 @@ pub enum SignError<E> {
4159
///
4260
/// Panics if `bytes` is not a well-formed TLV stream containing at least one TLV record.
4361
pub(super) fn sign_message<F, E>(
44-
sign: F, tag: &str, bytes: &[u8], metadata: &[u8], pubkey: PublicKey,
62+
sign: F, message: TaggedBytes, metadata: &[u8], pubkey: PublicKey,
4563
) -> Result<Signature, SignError<E>>
4664
where
47-
F: FnOnce(&Message, &str, &[u8], &[u8]) -> Result<Signature, E>
65+
F: FnOnce(TaggedBytes, &[u8]) -> Result<Signature, E>
4866
{
49-
let digest = message_digest(tag, bytes);
50-
let signature = sign(&digest, tag, bytes, metadata).map_err(|e| SignError::Signing(e))?;
67+
let signature = sign(message, metadata).map_err(|e| SignError::Signing(e))?;
5168

5269
let pubkey = pubkey.into();
5370
let secp_ctx = Secp256k1::verification_only();
54-
secp_ctx.verify_schnorr(&signature, &digest, &pubkey).map_err(|e| SignError::Verification(e))?;
71+
secp_ctx.verify_schnorr(&signature, &message.digest(), &pubkey)
72+
.map_err(|e| SignError::Verification(e))?;
5573

5674
Ok(signature)
5775
}
@@ -275,7 +293,7 @@ mod tests {
275293
.request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
276294
.build_unchecked()
277295
.sign::<_, Infallible>(
278-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &payer_keys))
296+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &payer_keys))
279297
)
280298
.unwrap();
281299
assert_eq!(
@@ -310,7 +328,7 @@ mod tests {
310328
.request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
311329
.build_unchecked()
312330
.sign::<_, Infallible>(
313-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &payer_keys))
331+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &payer_keys))
314332
)
315333
.unwrap();
316334

@@ -342,7 +360,7 @@ mod tests {
342360
.request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
343361
.build_unchecked()
344362
.sign::<_, Infallible>(
345-
|digest, _, _, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &payer_keys))
363+
|message, _| Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &payer_keys))
346364
)
347365
.unwrap();
348366

lightning/src/offers/test_utils.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
//! Utilities for testing BOLT 12 Offers interfaces
1111
12-
use bitcoin::secp256k1::{KeyPair, Message, PublicKey, Secp256k1, SecretKey};
12+
use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
1313
use bitcoin::secp256k1::schnorr::Signature;
1414
use core::convert::Infallible;
1515
use core::time::Duration;
@@ -18,18 +18,17 @@ use crate::sign::EntropySource;
1818
use crate::ln::PaymentHash;
1919
use crate::ln::features::BlindedHopFeatures;
2020
use crate::offers::invoice::BlindedPayInfo;
21+
use crate::offers::merkle::TaggedBytes;
2122

2223
pub(super) fn payer_keys() -> KeyPair {
2324
let secp_ctx = Secp256k1::new();
2425
KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
2526
}
2627

27-
pub(super) fn payer_sign(
28-
digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
29-
) -> Result<Signature, Infallible> {
28+
pub(super) fn payer_sign(message: TaggedBytes, _metadata: &[u8]) -> Result<Signature, Infallible> {
3029
let secp_ctx = Secp256k1::new();
3130
let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
32-
Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
31+
Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
3332
}
3433

3534
pub(super) fn payer_pubkey() -> PublicKey {
@@ -42,11 +41,11 @@ pub(super) fn recipient_keys() -> KeyPair {
4241
}
4342

4443
pub(super) fn recipient_sign(
45-
digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
44+
message: TaggedBytes, _metadata: &[u8]
4645
) -> Result<Signature, Infallible> {
4746
let secp_ctx = Secp256k1::new();
4847
let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap());
49-
Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))
48+
Ok(secp_ctx.sign_schnorr_no_aux_rand(&message.digest(), &keys))
5049
}
5150

5251
pub(super) fn recipient_pubkey() -> PublicKey {

0 commit comments

Comments
 (0)