lightning/offers/
merkle.rs

1// This file is Copyright its original authors, visible in version control
2// history.
3//
4// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7// You may not use this file except in accordance with one or both of these
8// licenses.
9
10//! Tagged hashes for use in signature calculation and verification.
11
12use crate::io;
13use crate::util::ser::{BigSize, Readable, Writeable, Writer};
14use bitcoin::hashes::{sha256, Hash, HashEngine};
15use bitcoin::secp256k1::schnorr::Signature;
16use bitcoin::secp256k1::{self, Message, PublicKey, Secp256k1};
17
18#[allow(unused_imports)]
19use crate::prelude::*;
20
21/// Valid type range for signature TLV records.
22pub(super) const SIGNATURE_TYPES: core::ops::RangeInclusive<u64> = 240..=1000;
23
24tlv_stream!(SignatureTlvStream, SignatureTlvStreamRef<'a>, SIGNATURE_TYPES, {
25	(240, signature: Signature),
26});
27
28/// A hash for use in a specific context by tweaking with a context-dependent tag as per [BIP 340]
29/// and computed over the merkle root of a TLV stream to sign as defined in [BOLT 12].
30///
31/// [BIP 340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
32/// [BOLT 12]: https://github.com/rustyrussell/lightning-rfc/blob/guilt/offers/12-offer-encoding.md#signature-calculation
33#[derive(Clone, Debug, PartialEq)]
34pub struct TaggedHash {
35	tag: &'static str,
36	merkle_root: sha256::Hash,
37	digest: Message,
38}
39
40impl TaggedHash {
41	/// Creates a tagged hash with the given parameters.
42	///
43	/// Panics if `bytes` is not a well-formed TLV stream containing at least one TLV record.
44	pub(super) fn from_valid_tlv_stream_bytes(tag: &'static str, bytes: &[u8]) -> Self {
45		let tlv_stream = TlvStream::new(bytes);
46		Self::from_tlv_stream(tag, tlv_stream)
47	}
48
49	/// Creates a tagged hash with the given parameters.
50	///
51	/// Panics if `tlv_stream` is not a well-formed TLV stream containing at least one TLV record.
52	pub(super) fn from_tlv_stream<'a, I: core::iter::Iterator<Item = TlvRecord<'a>>>(
53		tag: &'static str, tlv_stream: I,
54	) -> Self {
55		let tag_hash = sha256::Hash::hash(tag.as_bytes());
56		let merkle_root = root_hash(tlv_stream);
57		let digest = Message::from_digest(tagged_hash(tag_hash, merkle_root).to_byte_array());
58		Self { tag, merkle_root, digest }
59	}
60
61	/// Returns the digest to sign.
62	pub fn as_digest(&self) -> &Message {
63		&self.digest
64	}
65
66	/// Returns the tag used in the tagged hash.
67	pub fn tag(&self) -> &str {
68		&self.tag
69	}
70
71	/// Returns the merkle root used in the tagged hash.
72	pub fn merkle_root(&self) -> sha256::Hash {
73		self.merkle_root
74	}
75
76	pub(super) fn to_bytes(&self) -> [u8; 32] {
77		*self.digest.as_ref()
78	}
79}
80
81impl AsRef<TaggedHash> for TaggedHash {
82	fn as_ref(&self) -> &TaggedHash {
83		self
84	}
85}
86
87/// Error when signing messages.
88#[derive(Debug, PartialEq)]
89pub enum SignError {
90	/// User-defined error when signing the message.
91	Signing,
92	/// Error when verifying the produced signature using the given pubkey.
93	Verification(secp256k1::Error),
94}
95
96/// A function for signing a [`TaggedHash`].
97///
98/// This is not exported to bindings users as signing functions should just be used per-signed-type
99/// instead.
100pub trait SignFn<T: AsRef<TaggedHash>> {
101	/// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream.
102	fn sign(&self, message: &T) -> Result<Signature, ()>;
103}
104
105impl<F> SignFn<TaggedHash> for F
106where
107	F: Fn(&TaggedHash) -> Result<Signature, ()>,
108{
109	fn sign(&self, message: &TaggedHash) -> Result<Signature, ()> {
110		self(message)
111	}
112}
113
114/// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream, checking if it
115/// can be verified with the supplied `pubkey`.
116///
117/// Since `message` is any type that implements [`AsRef<TaggedHash>`], `sign` may be a closure that
118/// takes a message such as [`Bolt12Invoice`] or [`InvoiceRequest`]. This allows further message
119/// verification before signing its [`TaggedHash`].
120///
121/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
122/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
123pub fn sign_message<F, T>(f: F, message: &T, pubkey: PublicKey) -> Result<Signature, SignError>
124where
125	F: SignFn<T>,
126	T: AsRef<TaggedHash>,
127{
128	let signature = f.sign(message).map_err(|()| SignError::Signing)?;
129
130	let digest = message.as_ref().as_digest();
131	let pubkey = pubkey.into();
132	let secp_ctx = Secp256k1::verification_only();
133	secp_ctx.verify_schnorr(&signature, digest, &pubkey).map_err(|e| SignError::Verification(e))?;
134
135	Ok(signature)
136}
137
138/// Verifies the signature with a pubkey over the given message using a tagged hash as the message
139/// digest.
140pub fn verify_signature(
141	signature: &Signature, message: &TaggedHash, pubkey: PublicKey,
142) -> Result<(), secp256k1::Error> {
143	let digest = message.as_digest();
144	let pubkey = pubkey.into();
145	let secp_ctx = Secp256k1::verification_only();
146	secp_ctx.verify_schnorr(signature, digest, &pubkey)
147}
148
149/// Computes a merkle root hash for the given data, which must be a well-formed TLV stream
150/// containing at least one TLV record.
151fn root_hash<'a, I: core::iter::Iterator<Item = TlvRecord<'a>>>(tlv_stream: I) -> sha256::Hash {
152	let mut tlv_stream = tlv_stream.peekable();
153	let nonce_tag = tagged_hash_engine(sha256::Hash::from_engine({
154		let first_tlv_record = tlv_stream.peek().unwrap();
155		let mut engine = sha256::Hash::engine();
156		engine.input("LnNonce".as_bytes());
157		engine.input(first_tlv_record.record_bytes);
158		engine
159	}));
160	let leaf_tag = tagged_hash_engine(sha256::Hash::hash("LnLeaf".as_bytes()));
161	let branch_tag = tagged_hash_engine(sha256::Hash::hash("LnBranch".as_bytes()));
162
163	let mut leaves = Vec::new();
164	for record in tlv_stream.filter(|record| !SIGNATURE_TYPES.contains(&record.r#type)) {
165		leaves.push(tagged_hash_from_engine(leaf_tag.clone(), &record.record_bytes));
166		leaves.push(tagged_hash_from_engine(nonce_tag.clone(), &record.type_bytes));
167	}
168
169	// Calculate the merkle root hash in place.
170	let num_leaves = leaves.len();
171	for level in 0.. {
172		let step = 2 << level;
173		let offset = step / 2;
174		if offset >= num_leaves {
175			break;
176		}
177
178		let left_branches = (0..num_leaves).step_by(step);
179		let right_branches = (offset..num_leaves).step_by(step);
180		for (i, j) in left_branches.zip(right_branches) {
181			leaves[i] = tagged_branch_hash_from_engine(branch_tag.clone(), leaves[i], leaves[j]);
182		}
183	}
184
185	*leaves.first().unwrap()
186}
187
188fn tagged_hash<T: AsRef<[u8]>>(tag: sha256::Hash, msg: T) -> sha256::Hash {
189	let engine = tagged_hash_engine(tag);
190	tagged_hash_from_engine(engine, msg)
191}
192
193fn tagged_hash_engine(tag: sha256::Hash) -> sha256::HashEngine {
194	let mut engine = sha256::Hash::engine();
195	engine.input(tag.as_ref());
196	engine.input(tag.as_ref());
197	engine
198}
199
200fn tagged_hash_from_engine<T: AsRef<[u8]>>(mut engine: sha256::HashEngine, msg: T) -> sha256::Hash {
201	engine.input(msg.as_ref());
202	sha256::Hash::from_engine(engine)
203}
204
205fn tagged_branch_hash_from_engine(
206	mut engine: sha256::HashEngine, leaf1: sha256::Hash, leaf2: sha256::Hash,
207) -> sha256::Hash {
208	if leaf1 < leaf2 {
209		engine.input(leaf1.as_ref());
210		engine.input(leaf2.as_ref());
211	} else {
212		engine.input(leaf2.as_ref());
213		engine.input(leaf1.as_ref());
214	};
215	sha256::Hash::from_engine(engine)
216}
217
218/// [`Iterator`] over a sequence of bytes yielding [`TlvRecord`]s. The input is assumed to be a
219/// well-formed TLV stream.
220#[derive(Clone)]
221pub(super) struct TlvStream<'a> {
222	data: io::Cursor<&'a [u8]>,
223}
224
225impl<'a> TlvStream<'a> {
226	pub fn new(data: &'a [u8]) -> Self {
227		Self { data: io::Cursor::new(data) }
228	}
229
230	pub fn range<T>(self, types: T) -> impl core::iter::Iterator<Item = TlvRecord<'a>>
231	where
232		T: core::ops::RangeBounds<u64> + Clone,
233	{
234		let take_range = types.clone();
235		self.skip_while(move |record| !types.contains(&record.r#type))
236			.take_while(move |record| take_range.contains(&record.r#type))
237	}
238}
239
240/// A slice into a [`TlvStream`] for a record.
241pub(super) struct TlvRecord<'a> {
242	pub(super) r#type: u64,
243	type_bytes: &'a [u8],
244	// The entire TLV record.
245	pub(super) record_bytes: &'a [u8],
246	pub(super) end: usize,
247}
248
249impl<'a> Iterator for TlvStream<'a> {
250	type Item = TlvRecord<'a>;
251
252	fn next(&mut self) -> Option<Self::Item> {
253		if self.data.position() < self.data.get_ref().len() as u64 {
254			let start = self.data.position();
255
256			let r#type = <BigSize as Readable>::read(&mut self.data).unwrap().0;
257			let offset = self.data.position();
258			let type_bytes = &self.data.get_ref()[start as usize..offset as usize];
259
260			let length = <BigSize as Readable>::read(&mut self.data).unwrap().0;
261			let offset = self.data.position();
262			let end = offset + length;
263
264			let _value = &self.data.get_ref()[offset as usize..end as usize];
265			let record_bytes = &self.data.get_ref()[start as usize..end as usize];
266
267			self.data.set_position(end);
268
269			Some(TlvRecord { r#type, type_bytes, record_bytes, end: end as usize })
270		} else {
271			None
272		}
273	}
274}
275
276impl<'a> Writeable for TlvRecord<'a> {
277	#[inline]
278	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
279		writer.write_all(self.record_bytes)
280	}
281}
282
283#[cfg(test)]
284mod tests {
285	use super::{TlvStream, SIGNATURE_TYPES};
286
287	use crate::ln::channelmanager::PaymentId;
288	use crate::ln::inbound_payment::ExpandedKey;
289	use crate::offers::invoice_request::{InvoiceRequest, UnsignedInvoiceRequest};
290	use crate::offers::nonce::Nonce;
291	use crate::offers::offer::{Amount, CurrencyCode, OfferBuilder};
292	use crate::offers::parse::Bech32Encode;
293	use crate::offers::signer::Metadata;
294	use crate::offers::test_utils::recipient_pubkey;
295	use crate::util::ser::Writeable;
296	use bitcoin::hashes::{sha256, Hash};
297	use bitcoin::hex::FromHex;
298	use bitcoin::secp256k1::schnorr::Signature;
299	use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey};
300
301	#[test]
302	fn calculates_merkle_root_hash() {
303		// BOLT 12 test vectors
304		const HEX_1: &'static str = "010203e8";
305		let bytes_1 =
306			<Vec<u8>>::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93")
307				.unwrap();
308		assert_eq!(
309			super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(HEX_1).unwrap())),
310			sha256::Hash::from_slice(&bytes_1).unwrap(),
311		);
312
313		const HEX_2: &'static str = concat!("010203e8", "02080000010000020003");
314		let bytes_2 =
315			<Vec<u8>>::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1")
316				.unwrap();
317		assert_eq!(
318			super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(HEX_2).unwrap())),
319			sha256::Hash::from_slice(&bytes_2).unwrap(),
320		);
321
322		const HEX_3: &'static str = concat!("010203e8","02080000010000020003", "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002");
323		let bytes_3 =
324			<Vec<u8>>::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d")
325				.unwrap();
326		assert_eq!(
327			super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(HEX_3).unwrap())),
328			sha256::Hash::from_slice(&bytes_3).unwrap(),
329		);
330	}
331
332	#[test]
333	fn calculates_merkle_root_hash_from_invoice_request() {
334		let expanded_key = ExpandedKey::new([42; 32]);
335		let nonce = Nonce([0u8; 16]);
336		let secp_ctx = Secp256k1::new();
337		let payment_id = PaymentId([1; 32]);
338
339		let recipient_pubkey = {
340			let secret_bytes = <Vec<u8>>::from_hex(
341				"4141414141414141414141414141414141414141414141414141414141414141",
342			)
343			.unwrap();
344			let secret_key = SecretKey::from_slice(&secret_bytes).unwrap();
345			Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
346		};
347		let payer_keys = {
348			let secret_bytes = <Vec<u8>>::from_hex(
349				"4242424242424242424242424242424242424242424242424242424242424242",
350			)
351			.unwrap();
352			let secret_key = SecretKey::from_slice(&secret_bytes).unwrap();
353			Keypair::from_secret_key(&secp_ctx, &secret_key)
354		};
355
356		// BOLT 12 test vectors
357		let invoice_request = OfferBuilder::new(recipient_pubkey)
358			.description("A Mathematical Treatise".into())
359			.amount(Amount::Currency {
360				iso4217_code: CurrencyCode::new(*b"USD").unwrap(),
361				amount: 100,
362			})
363			.build_unchecked()
364			// Override the payer metadata and signing pubkey to match the test vectors
365			.request_invoice(&expanded_key, nonce, &secp_ctx, payment_id)
366			.unwrap()
367			.payer_metadata(Metadata::Bytes(vec![0; 8]))
368			.payer_signing_pubkey(payer_keys.public_key())
369			.build_unchecked()
370			.sign(|message: &UnsignedInvoiceRequest| {
371				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
372			})
373			.unwrap();
374		assert_eq!(
375			invoice_request.to_string(),
376			"lnr1qqyqqqqqqqqqqqqqqcp4256ypqqkgzshgysy6ct5dpjk6ct5d93kzmpq23ex2ct5d9ek293pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpjkppqvjx204vgdzgsqpvcp4mldl3plscny0rt707gvpdh6ndydfacz43euzqhrurageg3n7kafgsek6gz3e9w52parv8gs2hlxzk95tzeswywffxlkeyhml0hh46kndmwf4m6xma3tkq2lu04qz3slje2rfthc89vss",
377		);
378
379		let bytes =
380			<Vec<u8>>::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624")
381				.unwrap();
382		assert_eq!(
383			super::root_hash(TlvStream::new(&invoice_request.bytes[..])),
384			sha256::Hash::from_slice(&bytes).unwrap(),
385		);
386
387		let bytes = <Vec<u8>>::from_hex("b8f83ea3288cfd6ea510cdb481472575141e8d8744157f98562d162cc1c472526fdb24befefbdebab4dbb726bbd1b7d8aec057f8fa805187e5950d2bbe0e5642").unwrap();
388		assert_eq!(invoice_request.signature(), Signature::from_slice(&bytes).unwrap(),);
389	}
390
391	#[test]
392	fn compute_tagged_hash() {
393		let expanded_key = ExpandedKey::new([42; 32]);
394		let nonce = Nonce([0u8; 16]);
395		let secp_ctx = Secp256k1::new();
396		let payment_id = PaymentId([1; 32]);
397
398		let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey())
399			.amount_msats(1000)
400			.build()
401			.unwrap()
402			.request_invoice(&expanded_key, nonce, &secp_ctx, payment_id)
403			.unwrap()
404			.payer_note("bar".into())
405			.build_unchecked();
406
407		// Simply test that we can grab the tag and merkle root exposed by the accessor
408		// functions, then use them to succesfully compute a tagged hash.
409		let tagged_hash = unsigned_invoice_request.as_ref();
410		let expected_digest = unsigned_invoice_request.as_ref().as_digest();
411		let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes());
412		let actual_digest = Message::from_digest(
413			super::tagged_hash(tag, tagged_hash.merkle_root()).to_byte_array(),
414		);
415		assert_eq!(*expected_digest, actual_digest);
416	}
417
418	#[test]
419	fn skips_encoding_signature_tlv_records() {
420		let expanded_key = ExpandedKey::new([42; 32]);
421		let nonce = Nonce([0u8; 16]);
422		let secp_ctx = Secp256k1::new();
423		let payment_id = PaymentId([1; 32]);
424
425		let recipient_pubkey = {
426			let secret_key = SecretKey::from_slice(&[41; 32]).unwrap();
427			Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
428		};
429
430		let invoice_request = OfferBuilder::new(recipient_pubkey)
431			.amount_msats(100)
432			.build_unchecked()
433			.request_invoice(&expanded_key, nonce, &secp_ctx, payment_id)
434			.unwrap()
435			.build_and_sign()
436			.unwrap();
437
438		let mut bytes_without_signature = Vec::new();
439		let tlv_stream_without_signatures = TlvStream::new(&invoice_request.bytes)
440			.filter(|record| !SIGNATURE_TYPES.contains(&record.r#type));
441		for record in tlv_stream_without_signatures {
442			record.write(&mut bytes_without_signature).unwrap();
443		}
444
445		assert_ne!(bytes_without_signature, invoice_request.bytes);
446		assert_eq!(
447			TlvStream::new(&bytes_without_signature).count(),
448			TlvStream::new(&invoice_request.bytes).count() - 1,
449		);
450	}
451
452	#[test]
453	fn iterates_over_tlv_stream_range() {
454		let expanded_key = ExpandedKey::new([42; 32]);
455		let nonce = Nonce([0u8; 16]);
456		let secp_ctx = Secp256k1::new();
457		let payment_id = PaymentId([1; 32]);
458
459		let recipient_pubkey = {
460			let secret_key = SecretKey::from_slice(&[41; 32]).unwrap();
461			Keypair::from_secret_key(&secp_ctx, &secret_key).public_key()
462		};
463
464		let invoice_request = OfferBuilder::new(recipient_pubkey)
465			.amount_msats(100)
466			.build_unchecked()
467			.request_invoice(&expanded_key, nonce, &secp_ctx, payment_id)
468			.unwrap()
469			.build_and_sign()
470			.unwrap();
471
472		let tlv_stream = TlvStream::new(&invoice_request.bytes)
473			.range(0..1)
474			.chain(TlvStream::new(&invoice_request.bytes).range(1..80))
475			.chain(TlvStream::new(&invoice_request.bytes).range(80..160))
476			.chain(TlvStream::new(&invoice_request.bytes).range(160..240))
477			.chain(TlvStream::new(&invoice_request.bytes).range(SIGNATURE_TYPES))
478			.map(|r| r.record_bytes.to_vec())
479			.flatten()
480			.collect::<Vec<u8>>();
481
482		assert_eq!(tlv_stream, invoice_request.bytes);
483	}
484
485	impl AsRef<[u8]> for InvoiceRequest {
486		fn as_ref(&self) -> &[u8] {
487			&self.bytes
488		}
489	}
490
491	impl Bech32Encode for InvoiceRequest {
492		const BECH32_HRP: &'static str = "lnr";
493	}
494
495	impl core::fmt::Display for InvoiceRequest {
496		fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
497			self.fmt_bech32_str(f)
498		}
499	}
500}