lightning/offers/
static_invoice.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//! Data structures and encoding for static BOLT 12 invoices.
11
12use crate::blinded_path::message::BlindedMessagePath;
13use crate::blinded_path::payment::BlindedPaymentPath;
14use crate::io;
15use crate::ln::inbound_payment::ExpandedKey;
16use crate::ln::msgs::DecodeError;
17use crate::offers::invoice::{
18	check_invoice_signing_pubkey, construct_payment_paths, filter_fallbacks,
19	ExperimentalInvoiceTlvStream, ExperimentalInvoiceTlvStreamRef, FallbackAddress,
20	InvoiceTlvStream, InvoiceTlvStreamRef,
21};
22#[cfg(test)]
23use crate::offers::invoice_macros::invoice_builder_methods_test_common;
24use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common};
25use crate::offers::invoice_request::InvoiceRequest;
26use crate::offers::merkle::{
27	self, SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream,
28};
29use crate::offers::nonce::Nonce;
30use crate::offers::offer::{
31	Amount, ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, Offer, OfferContents,
32	OfferId, OfferTlvStream, OfferTlvStreamRef, Quantity, EXPERIMENTAL_OFFER_TYPES, OFFER_TYPES,
33};
34use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
35use crate::types::features::{Bolt12InvoiceFeatures, OfferFeatures};
36use crate::types::string::PrintableString;
37use crate::util::ser::{
38	CursorReadable, Iterable, LengthLimitedRead, LengthReadable, WithoutLength, Writeable, Writer,
39};
40use bitcoin::address::Address;
41use bitcoin::constants::ChainHash;
42use bitcoin::secp256k1::schnorr::Signature;
43use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1};
44use core::time::Duration;
45
46#[cfg(feature = "std")]
47use crate::offers::invoice::is_expired;
48
49#[allow(unused_imports)]
50use crate::prelude::*;
51
52/// Static invoices default to expiring after 2 weeks.
53pub const DEFAULT_RELATIVE_EXPIRY: Duration = Duration::from_secs(3600 * 24 * 14);
54
55/// Tag for the hash function used when signing a [`StaticInvoice`]'s merkle root.
56pub const SIGNATURE_TAG: &'static str = concat!("lightning", "static_invoice", "signature");
57
58/// A `StaticInvoice` is a reusable payment request corresponding to an [`Offer`].
59///
60/// A static invoice may be sent in response to an [`InvoiceRequest`] and includes all the
61/// information needed to pay the recipient. However, unlike [`Bolt12Invoice`]s, static invoices do
62/// not provide proof-of-payment. Therefore, [`Bolt12Invoice`]s should be preferred when the
63/// recipient is online to provide one.
64///
65/// [`Offer`]: crate::offers::offer::Offer
66/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
67/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
68#[derive(Clone, Debug)]
69pub struct StaticInvoice {
70	bytes: Vec<u8>,
71	contents: InvoiceContents,
72	signature: Signature,
73	offer_id: OfferId,
74}
75
76impl PartialEq for StaticInvoice {
77	fn eq(&self, other: &Self) -> bool {
78		self.bytes.eq(&other.bytes)
79	}
80}
81
82impl Eq for StaticInvoice {}
83
84impl core::hash::Hash for StaticInvoice {
85	fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
86		self.bytes.hash(state);
87	}
88}
89
90/// The contents of a [`StaticInvoice`] for responding to an [`Offer`].
91///
92/// [`Offer`]: crate::offers::offer::Offer
93#[derive(Clone, Debug)]
94struct InvoiceContents {
95	offer: OfferContents,
96	payment_paths: Vec<BlindedPaymentPath>,
97	created_at: Duration,
98	relative_expiry: Option<Duration>,
99	fallbacks: Option<Vec<FallbackAddress>>,
100	features: Bolt12InvoiceFeatures,
101	signing_pubkey: PublicKey,
102	message_paths: Vec<BlindedMessagePath>,
103	#[cfg(test)]
104	experimental_baz: Option<u64>,
105}
106
107/// Builds a [`StaticInvoice`] from an [`Offer`].
108///
109/// [`Offer`]: crate::offers::offer::Offer
110/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
111// TODO: add module-level docs and link here
112pub struct StaticInvoiceBuilder<'a> {
113	offer_bytes: &'a Vec<u8>,
114	invoice: InvoiceContents,
115	keys: Keypair,
116}
117
118impl<'a> StaticInvoiceBuilder<'a> {
119	/// Initialize a [`StaticInvoiceBuilder`] from the given [`Offer`].
120	///
121	/// The invoice's expiration will default to [`DEFAULT_RELATIVE_EXPIRY`] after `created_at` unless
122	/// overridden by [`StaticInvoiceBuilder::relative_expiry`].
123	pub fn for_offer_using_derived_keys<T: secp256k1::Signing>(
124		offer: &'a Offer, payment_paths: Vec<BlindedPaymentPath>,
125		message_paths: Vec<BlindedMessagePath>, created_at: Duration, expanded_key: &ExpandedKey,
126		nonce: Nonce, secp_ctx: &Secp256k1<T>,
127	) -> Result<Self, Bolt12SemanticError> {
128		if offer.chains().len() > 1 {
129			return Err(Bolt12SemanticError::UnexpectedChain);
130		}
131
132		if payment_paths.is_empty() || message_paths.is_empty() || offer.paths().is_empty() {
133			return Err(Bolt12SemanticError::MissingPaths);
134		}
135
136		let issuer_signing_pubkey =
137			offer.issuer_signing_pubkey().ok_or(Bolt12SemanticError::MissingIssuerSigningPubkey)?;
138
139		let keys = offer
140			.verify(nonce, &expanded_key, &secp_ctx)
141			.map_err(|()| Bolt12SemanticError::InvalidMetadata)?
142			.1
143			.ok_or(Bolt12SemanticError::MissingSigningPubkey)?;
144
145		let signing_pubkey = keys.public_key();
146		if signing_pubkey != issuer_signing_pubkey {
147			return Err(Bolt12SemanticError::InvalidSigningPubkey);
148		}
149
150		let invoice =
151			InvoiceContents::new(offer, payment_paths, message_paths, created_at, signing_pubkey);
152
153		Ok(Self { offer_bytes: &offer.bytes, invoice, keys })
154	}
155
156	/// Builds an [`UnsignedStaticInvoice`] after checking for valid semantics, returning it along with
157	/// the [`Keypair`] needed to sign it.
158	pub fn build(self) -> Result<(UnsignedStaticInvoice, Keypair), Bolt12SemanticError> {
159		#[cfg(feature = "std")]
160		{
161			if self.invoice.is_offer_expired() {
162				return Err(Bolt12SemanticError::AlreadyExpired);
163			}
164		}
165
166		#[cfg(not(feature = "std"))]
167		{
168			if self.invoice.is_offer_expired_no_std(self.invoice.created_at()) {
169				return Err(Bolt12SemanticError::AlreadyExpired);
170			}
171		}
172
173		let Self { offer_bytes, invoice, keys } = self;
174		Ok((UnsignedStaticInvoice::new(&offer_bytes, invoice), keys))
175	}
176
177	/// Builds a signed [`StaticInvoice`] after checking for valid semantics.
178	pub fn build_and_sign<T: secp256k1::Signing>(
179		self, secp_ctx: &Secp256k1<T>,
180	) -> Result<StaticInvoice, Bolt12SemanticError> {
181		let (unsigned_invoice, keys) = self.build()?;
182		let invoice = unsigned_invoice
183			.sign(|message: &UnsignedStaticInvoice| {
184				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.tagged_hash.as_digest(), &keys))
185			})
186			.unwrap();
187		Ok(invoice)
188	}
189
190	invoice_builder_methods_common!(self, Self, self.invoice, Self, self, StaticInvoice, mut);
191
192	#[cfg(test)]
193	invoice_builder_methods_test_common!(self, Self, self.invoice, Self, self, mut);
194}
195
196/// A semantically valid [`StaticInvoice`] that hasn't been signed.
197pub struct UnsignedStaticInvoice {
198	bytes: Vec<u8>,
199	experimental_bytes: Vec<u8>,
200	contents: InvoiceContents,
201	tagged_hash: TaggedHash,
202}
203
204macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
205	/// The chain that must be used when paying the invoice. [`StaticInvoice`]s currently can only be
206	/// created from offers that support a single chain.
207	pub fn chain(&$self) -> ChainHash {
208		$contents.chain()
209	}
210
211	/// Opaque bytes set by the originating [`Offer::metadata`].
212	///
213	/// [`Offer::metadata`]: crate::offers::offer::Offer::metadata
214	pub fn metadata(&$self) -> Option<&Vec<u8>> {
215		$contents.metadata()
216	}
217
218	/// The minimum amount required for a successful payment of a single item.
219	///
220	/// From [`Offer::amount`].
221	///
222	/// [`Offer::amount`]: crate::offers::offer::Offer::amount
223	pub fn amount(&$self) -> Option<Amount> {
224		$contents.amount()
225	}
226
227	/// Features pertaining to the originating [`Offer`], from [`Offer::offer_features`].
228	///
229	/// [`Offer`]: crate::offers::offer::Offer
230	/// [`Offer::offer_features`]: crate::offers::offer::Offer::offer_features
231	pub fn offer_features(&$self) -> &OfferFeatures {
232		$contents.offer_features()
233	}
234
235	/// A complete description of the purpose of the originating offer, from [`Offer::description`].
236	///
237	/// [`Offer::description`]: crate::offers::offer::Offer::description
238	pub fn description(&$self) -> Option<PrintableString<'_>> {
239		$contents.description()
240	}
241
242	/// Duration since the Unix epoch when an invoice should no longer be requested, from
243	/// [`Offer::absolute_expiry`].
244	///
245	/// [`Offer::absolute_expiry`]: crate::offers::offer::Offer::absolute_expiry
246	pub fn absolute_expiry(&$self) -> Option<Duration> {
247		$contents.absolute_expiry()
248	}
249
250	/// The issuer of the offer, from [`Offer::issuer`].
251	///
252	/// [`Offer::issuer`]: crate::offers::offer::Offer::issuer
253	pub fn issuer(&$self) -> Option<PrintableString<'_>> {
254		$contents.issuer()
255	}
256
257	/// Paths to the node that may supply the invoice on the recipient's behalf, originating from
258	/// publicly reachable nodes. Taken from [`Offer::paths`].
259	///
260	/// [`Offer::paths`]: crate::offers::offer::Offer::paths
261	pub fn offer_message_paths(&$self) -> &[BlindedMessagePath] {
262		$contents.offer_message_paths()
263	}
264
265	/// Paths to the recipient for indicating that a held HTLC is available to claim when they next
266	/// come online.
267	pub fn message_paths(&$self) -> &[BlindedMessagePath] {
268		$contents.message_paths()
269	}
270
271	/// The quantity of items supported, from [`Offer::supported_quantity`].
272	///
273	/// [`Offer::supported_quantity`]: crate::offers::offer::Offer::supported_quantity
274	pub fn supported_quantity(&$self) -> Quantity {
275		$contents.supported_quantity()
276	}
277
278	/// The public key used by the recipient to sign invoices, from
279	/// [`Offer::issuer_signing_pubkey`].
280	///
281	/// [`Offer::issuer_signing_pubkey`]: crate::offers::offer::Offer::issuer_signing_pubkey
282	pub fn issuer_signing_pubkey(&$self) -> Option<PublicKey> {
283		$contents.issuer_signing_pubkey()
284	}
285} }
286
287macro_rules! invoice_accessors_signing_pubkey {
288	($self: ident, $contents: expr, $invoice_type: ty) =>
289{
290	/// The public key corresponding to the key used to sign the invoice.
291	///
292	/// This will be:
293	/// - [`Offer::issuer_signing_pubkey`] if it's `Some`, otherwise
294	/// - the final blinded node id from a [`BlindedMessagePath`] in [`Offer::paths`] if `None`.
295	///
296	/// [`Offer::issuer_signing_pubkey`]: crate::offers::offer::Offer::issuer_signing_pubkey
297	/// [`Offer::paths`]: crate::offers::offer::Offer::paths
298	pub fn signing_pubkey(&$self) -> PublicKey {
299		$contents.signing_pubkey()
300	}
301} }
302
303impl UnsignedStaticInvoice {
304	fn new(offer_bytes: &Vec<u8>, contents: InvoiceContents) -> Self {
305		let (_, invoice_tlv_stream, _, experimental_invoice_tlv_stream) = contents.as_tlv_stream();
306
307		const INVOICE_ALLOCATION_SIZE: usize = 1024;
308		let mut bytes = Vec::with_capacity(INVOICE_ALLOCATION_SIZE);
309
310		// Use the offer bytes instead of the offer TLV stream as the latter may have contained
311		// unknown TLV records, which are not stored in `InvoiceContents`.
312		for record in TlvStream::new(offer_bytes).range(OFFER_TYPES) {
313			record.write(&mut bytes).unwrap();
314		}
315
316		let remaining_bytes = &offer_bytes[bytes.len()..];
317
318		invoice_tlv_stream.write(&mut bytes).unwrap();
319
320		const EXPERIMENTAL_TLV_ALLOCATION_SIZE: usize = 0;
321		let mut experimental_bytes = Vec::with_capacity(EXPERIMENTAL_TLV_ALLOCATION_SIZE);
322
323		let experimental_tlv_stream =
324			TlvStream::new(remaining_bytes).range(EXPERIMENTAL_OFFER_TYPES);
325		for record in experimental_tlv_stream {
326			record.write(&mut experimental_bytes).unwrap();
327		}
328
329		experimental_invoice_tlv_stream.write(&mut experimental_bytes).unwrap();
330
331		let tlv_stream = TlvStream::new(&bytes).chain(TlvStream::new(&experimental_bytes));
332		let tagged_hash = TaggedHash::from_tlv_stream(SIGNATURE_TAG, tlv_stream);
333
334		Self { bytes, experimental_bytes, contents, tagged_hash }
335	}
336
337	/// Signs the [`TaggedHash`] of the invoice using the given function.
338	///
339	/// Note: The hash computation may have included unknown, odd TLV records.
340	pub fn sign<F: SignStaticInvoiceFn>(mut self, sign: F) -> Result<StaticInvoice, SignError> {
341		let pubkey = self.contents.signing_pubkey;
342		let signature = merkle::sign_message(sign, &self, pubkey)?;
343
344		// Append the signature TLV record to the bytes.
345		let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&signature) };
346		signature_tlv_stream.write(&mut self.bytes).unwrap();
347
348		// Append the experimental bytes after the signature.
349		self.bytes.extend_from_slice(&self.experimental_bytes);
350
351		let offer_id = OfferId::from_valid_bolt12_tlv_stream(&self.bytes);
352		Ok(StaticInvoice { bytes: self.bytes, contents: self.contents, signature, offer_id })
353	}
354
355	invoice_accessors_common!(self, self.contents, UnsignedStaticInvoice);
356	invoice_accessors_signing_pubkey!(self, self.contents, UnsignedStaticInvoice);
357	invoice_accessors!(self, self.contents);
358}
359
360impl AsRef<TaggedHash> for UnsignedStaticInvoice {
361	fn as_ref(&self) -> &TaggedHash {
362		&self.tagged_hash
363	}
364}
365
366/// A function for signing an [`UnsignedStaticInvoice`].
367pub trait SignStaticInvoiceFn {
368	/// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream.
369	fn sign_invoice(&self, message: &UnsignedStaticInvoice) -> Result<Signature, ()>;
370}
371
372impl<F> SignStaticInvoiceFn for F
373where
374	F: Fn(&UnsignedStaticInvoice) -> Result<Signature, ()>,
375{
376	fn sign_invoice(&self, message: &UnsignedStaticInvoice) -> Result<Signature, ()> {
377		self(message)
378	}
379}
380
381impl<F> SignFn<UnsignedStaticInvoice> for F
382where
383	F: SignStaticInvoiceFn,
384{
385	fn sign(&self, message: &UnsignedStaticInvoice) -> Result<Signature, ()> {
386		self.sign_invoice(message)
387	}
388}
389
390impl StaticInvoice {
391	invoice_accessors_common!(self, self.contents, StaticInvoice);
392	invoice_accessors_signing_pubkey!(self, self.contents, StaticInvoice);
393	invoice_accessors!(self, self.contents);
394
395	/// Signature of the invoice verified using [`StaticInvoice::signing_pubkey`].
396	pub fn signature(&self) -> Signature {
397		self.signature
398	}
399
400	/// Whether the [`Offer`] that this invoice is based on is expired.
401	#[cfg(feature = "std")]
402	pub fn is_offer_expired(&self) -> bool {
403		self.contents.is_expired()
404	}
405
406	/// Whether the [`Offer`] that this invoice is based on is expired, given the current time as
407	/// duration since the Unix epoch.
408	pub fn is_offer_expired_no_std(&self, duration_since_epoch: Duration) -> bool {
409		self.contents.is_offer_expired_no_std(duration_since_epoch)
410	}
411
412	/// Returns the [`OfferId`] corresponding to the originating [`Offer`].
413	///
414	/// [`Offer`]: crate::offers::offer::Offer
415	pub fn offer_id(&self) -> OfferId {
416		self.offer_id
417	}
418
419	#[allow(unused)] // TODO: remove this once we remove the `async_payments` cfg flag
420	pub(crate) fn is_from_same_offer(&self, invreq: &InvoiceRequest) -> bool {
421		let invoice_offer_tlv_stream =
422			Offer::tlv_stream_iter(&self.bytes).map(|tlv_record| tlv_record.record_bytes);
423		let invreq_offer_tlv_stream =
424			Offer::tlv_stream_iter(invreq.bytes()).map(|tlv_record| tlv_record.record_bytes);
425		invoice_offer_tlv_stream.eq(invreq_offer_tlv_stream)
426	}
427}
428
429impl InvoiceContents {
430	#[cfg(feature = "std")]
431	fn is_offer_expired(&self) -> bool {
432		self.offer.is_expired()
433	}
434
435	fn is_offer_expired_no_std(&self, duration_since_epoch: Duration) -> bool {
436		self.offer.is_expired_no_std(duration_since_epoch)
437	}
438
439	fn new(
440		offer: &Offer, payment_paths: Vec<BlindedPaymentPath>,
441		message_paths: Vec<BlindedMessagePath>, created_at: Duration, signing_pubkey: PublicKey,
442	) -> Self {
443		Self {
444			offer: offer.contents.clone(),
445			payment_paths,
446			message_paths,
447			created_at,
448			relative_expiry: None,
449			fallbacks: None,
450			features: Bolt12InvoiceFeatures::empty(),
451			signing_pubkey,
452			#[cfg(test)]
453			experimental_baz: None,
454		}
455	}
456
457	fn as_tlv_stream(&self) -> PartialInvoiceTlvStreamRef<'_> {
458		let features = {
459			if self.features == Bolt12InvoiceFeatures::empty() {
460				None
461			} else {
462				Some(&self.features)
463			}
464		};
465
466		let invoice = InvoiceTlvStreamRef {
467			paths: Some(Iterable(self.payment_paths.iter().map(|path| path.inner_blinded_path()))),
468			message_paths: Some(self.message_paths.as_ref()),
469			blindedpay: Some(Iterable(self.payment_paths.iter().map(|path| &path.payinfo))),
470			created_at: Some(self.created_at.as_secs()),
471			relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
472			fallbacks: self.fallbacks.as_ref(),
473			features,
474			node_id: Some(&self.signing_pubkey),
475			amount: None,
476			payment_hash: None,
477		};
478
479		let experimental_invoice = ExperimentalInvoiceTlvStreamRef {
480			#[cfg(test)]
481			experimental_baz: self.experimental_baz,
482		};
483
484		let (offer, experimental_offer) = self.offer.as_tlv_stream();
485
486		(offer, invoice, experimental_offer, experimental_invoice)
487	}
488
489	fn chain(&self) -> ChainHash {
490		debug_assert_eq!(self.offer.chains().len(), 1);
491		self.offer.chains().first().cloned().unwrap_or_else(|| self.offer.implied_chain())
492	}
493
494	fn metadata(&self) -> Option<&Vec<u8>> {
495		self.offer.metadata()
496	}
497
498	fn amount(&self) -> Option<Amount> {
499		self.offer.amount()
500	}
501
502	fn offer_features(&self) -> &OfferFeatures {
503		self.offer.features()
504	}
505
506	fn description(&self) -> Option<PrintableString<'_>> {
507		self.offer.description()
508	}
509
510	fn absolute_expiry(&self) -> Option<Duration> {
511		self.offer.absolute_expiry()
512	}
513
514	fn issuer(&self) -> Option<PrintableString<'_>> {
515		self.offer.issuer()
516	}
517
518	fn offer_message_paths(&self) -> &[BlindedMessagePath] {
519		self.offer.paths()
520	}
521
522	fn message_paths(&self) -> &[BlindedMessagePath] {
523		&self.message_paths[..]
524	}
525
526	fn supported_quantity(&self) -> Quantity {
527		self.offer.supported_quantity()
528	}
529
530	fn issuer_signing_pubkey(&self) -> Option<PublicKey> {
531		self.offer.issuer_signing_pubkey()
532	}
533
534	fn payment_paths(&self) -> &[BlindedPaymentPath] {
535		&self.payment_paths[..]
536	}
537
538	fn created_at(&self) -> Duration {
539		self.created_at
540	}
541
542	fn relative_expiry(&self) -> Duration {
543		self.relative_expiry.unwrap_or(DEFAULT_RELATIVE_EXPIRY)
544	}
545
546	#[cfg(feature = "std")]
547	fn is_expired(&self) -> bool {
548		is_expired(self.created_at(), self.relative_expiry())
549	}
550
551	fn is_expired_no_std(&self, duration_since_epoch: Duration) -> bool {
552		self.created_at().saturating_add(self.relative_expiry()) < duration_since_epoch
553	}
554
555	fn fallbacks(&self) -> Vec<Address> {
556		let chain = self.chain();
557		self.fallbacks
558			.as_ref()
559			.map(|fallbacks| filter_fallbacks(chain, fallbacks))
560			.unwrap_or_else(Vec::new)
561	}
562
563	fn features(&self) -> &Bolt12InvoiceFeatures {
564		&self.features
565	}
566
567	fn signing_pubkey(&self) -> PublicKey {
568		self.signing_pubkey
569	}
570}
571
572impl Writeable for StaticInvoice {
573	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
574		WithoutLength(&self.bytes).write(writer)
575	}
576}
577impl LengthReadable for StaticInvoice {
578	fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
579		let bytes: WithoutLength<Vec<u8>> = LengthReadable::read_from_fixed_length_buffer(r)?;
580		Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
581	}
582}
583
584impl TryFrom<Vec<u8>> for StaticInvoice {
585	type Error = Bolt12ParseError;
586
587	fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
588		let parsed_invoice = ParsedMessage::<FullInvoiceTlvStream>::try_from(bytes)?;
589		StaticInvoice::try_from(parsed_invoice)
590	}
591}
592
593type FullInvoiceTlvStream = (
594	OfferTlvStream,
595	InvoiceTlvStream,
596	SignatureTlvStream,
597	ExperimentalOfferTlvStream,
598	ExperimentalInvoiceTlvStream,
599);
600
601impl CursorReadable for FullInvoiceTlvStream {
602	fn read<R: AsRef<[u8]>>(r: &mut io::Cursor<R>) -> Result<Self, DecodeError> {
603		let offer = CursorReadable::read(r)?;
604		let invoice = CursorReadable::read(r)?;
605		let signature = CursorReadable::read(r)?;
606		let experimental_offer = CursorReadable::read(r)?;
607		let experimental_invoice = CursorReadable::read(r)?;
608
609		Ok((offer, invoice, signature, experimental_offer, experimental_invoice))
610	}
611}
612
613type PartialInvoiceTlvStream =
614	(OfferTlvStream, InvoiceTlvStream, ExperimentalOfferTlvStream, ExperimentalInvoiceTlvStream);
615
616type PartialInvoiceTlvStreamRef<'a> = (
617	OfferTlvStreamRef<'a>,
618	InvoiceTlvStreamRef<'a>,
619	ExperimentalOfferTlvStreamRef,
620	ExperimentalInvoiceTlvStreamRef,
621);
622
623impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for StaticInvoice {
624	type Error = Bolt12ParseError;
625
626	fn try_from(invoice: ParsedMessage<FullInvoiceTlvStream>) -> Result<Self, Self::Error> {
627		let ParsedMessage { bytes, tlv_stream } = invoice;
628		let (
629			offer_tlv_stream,
630			invoice_tlv_stream,
631			SignatureTlvStream { signature },
632			experimental_offer_tlv_stream,
633			experimental_invoice_tlv_stream,
634		) = tlv_stream;
635		let contents = InvoiceContents::try_from((
636			offer_tlv_stream,
637			invoice_tlv_stream,
638			experimental_offer_tlv_stream,
639			experimental_invoice_tlv_stream,
640		))?;
641
642		let signature = match signature {
643			None => {
644				return Err(Bolt12ParseError::InvalidSemantics(
645					Bolt12SemanticError::MissingSignature,
646				))
647			},
648			Some(signature) => signature,
649		};
650		let tagged_hash = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &bytes);
651		let pubkey = contents.signing_pubkey;
652		merkle::verify_signature(&signature, &tagged_hash, pubkey)?;
653
654		let offer_id = OfferId::from_valid_bolt12_tlv_stream(&bytes);
655		Ok(StaticInvoice { bytes, contents, signature, offer_id })
656	}
657}
658
659impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
660	type Error = Bolt12SemanticError;
661
662	fn try_from(tlv_stream: PartialInvoiceTlvStream) -> Result<Self, Self::Error> {
663		let (
664			offer_tlv_stream,
665			InvoiceTlvStream {
666				paths,
667				blindedpay,
668				created_at,
669				relative_expiry,
670				fallbacks,
671				features,
672				node_id,
673				message_paths,
674				payment_hash,
675				amount,
676			},
677			experimental_offer_tlv_stream,
678			ExperimentalInvoiceTlvStream {
679				#[cfg(test)]
680				experimental_baz,
681			},
682		) = tlv_stream;
683
684		if payment_hash.is_some() {
685			return Err(Bolt12SemanticError::UnexpectedPaymentHash);
686		}
687		if amount.is_some() {
688			return Err(Bolt12SemanticError::UnexpectedAmount);
689		}
690
691		let payment_paths = construct_payment_paths(blindedpay, paths)?;
692		let message_paths = message_paths.ok_or(Bolt12SemanticError::MissingPaths)?;
693
694		let created_at = match created_at {
695			None => return Err(Bolt12SemanticError::MissingCreationTime),
696			Some(timestamp) => Duration::from_secs(timestamp),
697		};
698
699		let relative_expiry = relative_expiry.map(Into::<u64>::into).map(Duration::from_secs);
700
701		let features = features.unwrap_or_else(Bolt12InvoiceFeatures::empty);
702
703		let signing_pubkey = node_id.ok_or(Bolt12SemanticError::MissingSigningPubkey)?;
704		check_invoice_signing_pubkey(&signing_pubkey, &offer_tlv_stream)?;
705
706		if offer_tlv_stream.paths.is_none() {
707			return Err(Bolt12SemanticError::MissingPaths);
708		}
709		if offer_tlv_stream.chains.as_ref().map_or(0, |chains| chains.len()) > 1 {
710			return Err(Bolt12SemanticError::UnexpectedChain);
711		}
712
713		Ok(InvoiceContents {
714			offer: OfferContents::try_from((offer_tlv_stream, experimental_offer_tlv_stream))?,
715			payment_paths,
716			message_paths,
717			created_at,
718			relative_expiry,
719			fallbacks,
720			features,
721			signing_pubkey,
722			#[cfg(test)]
723			experimental_baz,
724		})
725	}
726}
727
728#[cfg(test)]
729mod tests {
730	use crate::blinded_path::message::BlindedMessagePath;
731	use crate::blinded_path::BlindedHop;
732	use crate::ln::inbound_payment::ExpandedKey;
733	use crate::ln::msgs::DecodeError;
734	use crate::offers::invoice::{
735		ExperimentalInvoiceTlvStreamRef, InvoiceTlvStreamRef, EXPERIMENTAL_INVOICE_TYPES,
736		INVOICE_TYPES,
737	};
738	use crate::offers::merkle;
739	use crate::offers::merkle::{SignatureTlvStreamRef, TaggedHash, TlvStream};
740	use crate::offers::nonce::Nonce;
741	use crate::offers::offer::{
742		ExperimentalOfferTlvStreamRef, Offer, OfferBuilder, OfferTlvStreamRef, Quantity,
743	};
744	use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
745	use crate::offers::static_invoice::{
746		StaticInvoice, StaticInvoiceBuilder, UnsignedStaticInvoice, DEFAULT_RELATIVE_EXPIRY,
747		SIGNATURE_TAG,
748	};
749	use crate::offers::test_utils::*;
750	use crate::types::features::{Bolt12InvoiceFeatures, OfferFeatures};
751	use crate::util::ser::{BigSize, Iterable, Writeable};
752	use bitcoin::constants::ChainHash;
753	use bitcoin::secp256k1::{self, Secp256k1};
754	use bitcoin::Network;
755	use core::time::Duration;
756
757	type FullInvoiceTlvStreamRef<'a> = (
758		OfferTlvStreamRef<'a>,
759		InvoiceTlvStreamRef<'a>,
760		SignatureTlvStreamRef<'a>,
761		ExperimentalOfferTlvStreamRef,
762		ExperimentalInvoiceTlvStreamRef,
763	);
764
765	impl StaticInvoice {
766		fn as_tlv_stream(&self) -> FullInvoiceTlvStreamRef<'_> {
767			let (
768				offer_tlv_stream,
769				invoice_tlv_stream,
770				experimental_offer_tlv_stream,
771				experimental_invoice_tlv_stream,
772			) = self.contents.as_tlv_stream();
773			(
774				offer_tlv_stream,
775				invoice_tlv_stream,
776				SignatureTlvStreamRef { signature: Some(&self.signature) },
777				experimental_offer_tlv_stream,
778				experimental_invoice_tlv_stream,
779			)
780		}
781	}
782
783	fn tlv_stream_to_bytes(
784		tlv_stream: &(
785			OfferTlvStreamRef,
786			InvoiceTlvStreamRef,
787			SignatureTlvStreamRef,
788			ExperimentalOfferTlvStreamRef,
789			ExperimentalInvoiceTlvStreamRef,
790		),
791	) -> Vec<u8> {
792		let mut buffer = Vec::new();
793		tlv_stream.0.write(&mut buffer).unwrap();
794		tlv_stream.1.write(&mut buffer).unwrap();
795		tlv_stream.2.write(&mut buffer).unwrap();
796		tlv_stream.3.write(&mut buffer).unwrap();
797		tlv_stream.4.write(&mut buffer).unwrap();
798		buffer
799	}
800
801	fn invoice() -> StaticInvoice {
802		let node_id = recipient_pubkey();
803		let payment_paths = payment_paths();
804		let now = now();
805		let expanded_key = ExpandedKey::new([42; 32]);
806		let entropy = FixedEntropy {};
807		let nonce = Nonce::from_entropy_source(&entropy);
808		let secp_ctx = Secp256k1::new();
809
810		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
811			.path(blinded_path())
812			.build()
813			.unwrap();
814
815		StaticInvoiceBuilder::for_offer_using_derived_keys(
816			&offer,
817			payment_paths.clone(),
818			vec![blinded_path()],
819			now,
820			&expanded_key,
821			nonce,
822			&secp_ctx,
823		)
824		.unwrap()
825		.build_and_sign(&secp_ctx)
826		.unwrap()
827	}
828
829	fn blinded_path() -> BlindedMessagePath {
830		BlindedMessagePath::from_blinded_path(
831			pubkey(40),
832			pubkey(41),
833			vec![
834				BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] },
835				BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 44] },
836			],
837		)
838	}
839
840	#[test]
841	fn builds_invoice_for_offer_with_defaults() {
842		let node_id = recipient_pubkey();
843		let payment_paths = payment_paths();
844		let now = now();
845		let expanded_key = ExpandedKey::new([42; 32]);
846		let entropy = FixedEntropy {};
847		let nonce = Nonce::from_entropy_source(&entropy);
848		let secp_ctx = Secp256k1::new();
849
850		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
851			.path(blinded_path())
852			.build()
853			.unwrap();
854
855		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
856			&offer,
857			payment_paths.clone(),
858			vec![blinded_path()],
859			now,
860			&expanded_key,
861			nonce,
862			&secp_ctx,
863		)
864		.unwrap()
865		.build_and_sign(&secp_ctx)
866		.unwrap();
867
868		let mut buffer = Vec::new();
869		invoice.write(&mut buffer).unwrap();
870
871		assert_eq!(invoice.bytes, buffer.as_slice());
872		assert_eq!(invoice.metadata(), None);
873		assert_eq!(invoice.amount(), None);
874		assert_eq!(invoice.description(), None);
875		assert_eq!(invoice.offer_features(), &OfferFeatures::empty());
876		assert_eq!(invoice.absolute_expiry(), None);
877		assert_eq!(invoice.offer_message_paths(), &[blinded_path()]);
878		assert_eq!(invoice.message_paths(), &[blinded_path()]);
879		assert_eq!(invoice.issuer(), None);
880		assert_eq!(invoice.supported_quantity(), Quantity::One);
881		assert_ne!(invoice.signing_pubkey(), recipient_pubkey());
882		assert_eq!(invoice.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
883		assert_eq!(invoice.payment_paths(), payment_paths.as_slice());
884		assert_eq!(invoice.created_at(), now);
885		assert_eq!(invoice.relative_expiry(), DEFAULT_RELATIVE_EXPIRY);
886		#[cfg(feature = "std")]
887		assert!(!invoice.is_expired());
888		assert!(invoice.fallbacks().is_empty());
889		assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
890
891		let signing_pubkey = offer.issuer_signing_pubkey().unwrap();
892		let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
893		assert!(merkle::verify_signature(&invoice.signature, &message, signing_pubkey).is_ok());
894
895		let paths = vec![blinded_path()];
896		assert_eq!(
897			invoice.as_tlv_stream(),
898			(
899				OfferTlvStreamRef {
900					chains: None,
901					metadata: None,
902					currency: None,
903					amount: None,
904					description: None,
905					features: None,
906					absolute_expiry: None,
907					paths: Some(&paths),
908					issuer: None,
909					quantity_max: None,
910					issuer_id: Some(&signing_pubkey),
911				},
912				InvoiceTlvStreamRef {
913					paths: Some(Iterable(
914						payment_paths.iter().map(|path| path.inner_blinded_path())
915					)),
916					blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))),
917					created_at: Some(now.as_secs()),
918					relative_expiry: None,
919					payment_hash: None,
920					amount: None,
921					fallbacks: None,
922					features: None,
923					node_id: Some(&signing_pubkey),
924					message_paths: Some(&paths),
925				},
926				SignatureTlvStreamRef { signature: Some(&invoice.signature()) },
927				ExperimentalOfferTlvStreamRef { experimental_foo: None },
928				ExperimentalInvoiceTlvStreamRef { experimental_baz: None },
929			)
930		);
931
932		if let Err(e) = StaticInvoice::try_from(buffer) {
933			panic!("error parsing invoice: {:?}", e);
934		}
935	}
936
937	#[cfg(feature = "std")]
938	#[test]
939	fn builds_invoice_from_offer_with_expiration() {
940		let node_id = recipient_pubkey();
941		let now = now();
942		let expanded_key = ExpandedKey::new([42; 32]);
943		let entropy = FixedEntropy {};
944		let nonce = Nonce::from_entropy_source(&entropy);
945		let secp_ctx = Secp256k1::new();
946
947		let future_expiry = Duration::from_secs(u64::max_value());
948		let past_expiry = Duration::from_secs(0);
949
950		let valid_offer =
951			OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
952				.path(blinded_path())
953				.absolute_expiry(future_expiry)
954				.build()
955				.unwrap();
956
957		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
958			&valid_offer,
959			payment_paths(),
960			vec![blinded_path()],
961			now,
962			&expanded_key,
963			nonce,
964			&secp_ctx,
965		)
966		.unwrap()
967		.build_and_sign(&secp_ctx)
968		.unwrap();
969		assert!(!invoice.is_expired());
970		assert_eq!(invoice.absolute_expiry(), Some(future_expiry));
971
972		let expired_offer =
973			OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
974				.path(blinded_path())
975				.absolute_expiry(past_expiry)
976				.build()
977				.unwrap();
978		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
979			&expired_offer,
980			payment_paths(),
981			vec![blinded_path()],
982			now,
983			&expanded_key,
984			nonce,
985			&secp_ctx,
986		)
987		.unwrap()
988		.build_and_sign(&secp_ctx)
989		{
990			assert_eq!(e, Bolt12SemanticError::AlreadyExpired);
991		} else {
992			panic!("expected error")
993		}
994	}
995
996	#[test]
997	fn builds_invoice_from_offer_using_derived_key() {
998		let node_id = recipient_pubkey();
999		let now = now();
1000		let expanded_key = ExpandedKey::new([42; 32]);
1001		let entropy = FixedEntropy {};
1002		let nonce = Nonce::from_entropy_source(&entropy);
1003		let secp_ctx = Secp256k1::new();
1004
1005		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1006			.path(blinded_path())
1007			.experimental_foo(42)
1008			.build()
1009			.unwrap();
1010
1011		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1012			&offer,
1013			payment_paths(),
1014			vec![blinded_path()],
1015			now,
1016			&expanded_key,
1017			nonce,
1018			&secp_ctx,
1019		)
1020		.unwrap()
1021		.build_and_sign(&secp_ctx)
1022		{
1023			panic!("error building invoice: {:?}", e);
1024		}
1025
1026		let expanded_key = ExpandedKey::new([41; 32]);
1027		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1028			&offer,
1029			payment_paths(),
1030			vec![blinded_path()],
1031			now,
1032			&expanded_key,
1033			nonce,
1034			&secp_ctx,
1035		) {
1036			assert_eq!(e, Bolt12SemanticError::InvalidMetadata);
1037		} else {
1038			panic!("expected error")
1039		}
1040	}
1041
1042	#[test]
1043	fn fails_build_with_missing_paths() {
1044		let node_id = recipient_pubkey();
1045		let now = now();
1046		let expanded_key = ExpandedKey::new([42; 32]);
1047		let entropy = FixedEntropy {};
1048		let nonce = Nonce::from_entropy_source(&entropy);
1049		let secp_ctx = Secp256k1::new();
1050
1051		let valid_offer =
1052			OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1053				.path(blinded_path())
1054				.build()
1055				.unwrap();
1056
1057		// Error if payment paths are missing.
1058		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1059			&valid_offer,
1060			Vec::new(),
1061			vec![blinded_path()],
1062			now,
1063			&expanded_key,
1064			nonce,
1065			&secp_ctx,
1066		) {
1067			assert_eq!(e, Bolt12SemanticError::MissingPaths);
1068		} else {
1069			panic!("expected error")
1070		}
1071
1072		// Error if message paths are missing.
1073		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1074			&valid_offer,
1075			payment_paths(),
1076			Vec::new(),
1077			now,
1078			&expanded_key,
1079			nonce,
1080			&secp_ctx,
1081		) {
1082			assert_eq!(e, Bolt12SemanticError::MissingPaths);
1083		} else {
1084			panic!("expected error")
1085		}
1086
1087		// Error if offer paths are missing.
1088		let mut offer_without_paths = valid_offer.clone();
1089		let (mut offer_tlv_stream, _) = offer_without_paths.as_tlv_stream();
1090		offer_tlv_stream.paths.take();
1091		let mut buffer = Vec::new();
1092		offer_tlv_stream.write(&mut buffer).unwrap();
1093		offer_without_paths = Offer::try_from(buffer).unwrap();
1094		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1095			&offer_without_paths,
1096			payment_paths(),
1097			vec![blinded_path()],
1098			now,
1099			&expanded_key,
1100			nonce,
1101			&secp_ctx,
1102		) {
1103			assert_eq!(e, Bolt12SemanticError::MissingPaths);
1104		} else {
1105			panic!("expected error")
1106		}
1107	}
1108
1109	#[test]
1110	fn fails_building_with_missing_issuer_signing_pubkey() {
1111		let node_id = recipient_pubkey();
1112		let now = now();
1113		let expanded_key = ExpandedKey::new([42; 32]);
1114		let entropy = FixedEntropy {};
1115		let nonce = Nonce::from_entropy_source(&entropy);
1116		let secp_ctx = Secp256k1::new();
1117
1118		let valid_offer =
1119			OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1120				.path(blinded_path())
1121				.build()
1122				.unwrap();
1123
1124		let mut offer_missing_issuer_id = valid_offer.clone();
1125		let (mut offer_tlv_stream, _) = offer_missing_issuer_id.as_tlv_stream();
1126		offer_tlv_stream.issuer_id.take();
1127		let mut buffer = Vec::new();
1128		offer_tlv_stream.write(&mut buffer).unwrap();
1129		offer_missing_issuer_id = Offer::try_from(buffer).unwrap();
1130
1131		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1132			&offer_missing_issuer_id,
1133			payment_paths(),
1134			vec![blinded_path()],
1135			now,
1136			&expanded_key,
1137			nonce,
1138			&secp_ctx,
1139		) {
1140			assert_eq!(e, Bolt12SemanticError::MissingIssuerSigningPubkey);
1141		} else {
1142			panic!("expected error")
1143		}
1144	}
1145
1146	#[test]
1147	fn fails_building_with_invalid_metadata() {
1148		let now = now();
1149		let expanded_key = ExpandedKey::new([42; 32]);
1150		let entropy = FixedEntropy {};
1151		let nonce = Nonce::from_entropy_source(&entropy);
1152		let secp_ctx = Secp256k1::new();
1153
1154		let offer = OfferBuilder::new(recipient_pubkey())
1155			.path(blinded_path())
1156			.metadata(vec![42; 32])
1157			.unwrap()
1158			.build()
1159			.unwrap();
1160		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1161			&offer,
1162			payment_paths(),
1163			vec![blinded_path()],
1164			now,
1165			&expanded_key,
1166			nonce,
1167			&secp_ctx,
1168		) {
1169			assert_eq!(e, Bolt12SemanticError::InvalidMetadata);
1170		} else {
1171			panic!("expected error")
1172		}
1173	}
1174
1175	#[test]
1176	fn fails_building_with_extra_offer_chains() {
1177		let node_id = recipient_pubkey();
1178		let now = now();
1179		let expanded_key = ExpandedKey::new([42; 32]);
1180		let entropy = FixedEntropy {};
1181		let nonce = Nonce::from_entropy_source(&entropy);
1182		let secp_ctx = Secp256k1::new();
1183
1184		let offer_with_extra_chain =
1185			OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1186				.path(blinded_path())
1187				.chain(Network::Bitcoin)
1188				.chain(Network::Testnet)
1189				.build()
1190				.unwrap();
1191
1192		if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1193			&offer_with_extra_chain,
1194			payment_paths(),
1195			vec![blinded_path()],
1196			now,
1197			&expanded_key,
1198			nonce,
1199			&secp_ctx,
1200		) {
1201			assert_eq!(e, Bolt12SemanticError::UnexpectedChain);
1202		} else {
1203			panic!("expected error")
1204		}
1205	}
1206
1207	#[test]
1208	fn parses_invoice_with_relative_expiry() {
1209		let node_id = recipient_pubkey();
1210		let payment_paths = payment_paths();
1211		let now = now();
1212		let expanded_key = ExpandedKey::new([42; 32]);
1213		let entropy = FixedEntropy {};
1214		let nonce = Nonce::from_entropy_source(&entropy);
1215		let secp_ctx = Secp256k1::new();
1216
1217		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1218			.path(blinded_path())
1219			.build()
1220			.unwrap();
1221
1222		const TEST_RELATIVE_EXPIRY: u32 = 3600;
1223		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
1224			&offer,
1225			payment_paths.clone(),
1226			vec![blinded_path()],
1227			now,
1228			&expanded_key,
1229			nonce,
1230			&secp_ctx,
1231		)
1232		.unwrap()
1233		.relative_expiry(TEST_RELATIVE_EXPIRY)
1234		.build_and_sign(&secp_ctx)
1235		.unwrap();
1236
1237		let mut buffer = Vec::new();
1238		invoice.write(&mut buffer).unwrap();
1239
1240		match StaticInvoice::try_from(buffer) {
1241			Ok(invoice) => assert_eq!(
1242				invoice.relative_expiry(),
1243				Duration::from_secs(TEST_RELATIVE_EXPIRY as u64)
1244			),
1245			Err(e) => panic!("error parsing invoice: {:?}", e),
1246		}
1247	}
1248
1249	#[test]
1250	fn parses_invoice_with_allow_mpp() {
1251		let node_id = recipient_pubkey();
1252		let payment_paths = payment_paths();
1253		let now = now();
1254		let expanded_key = ExpandedKey::new([42; 32]);
1255		let entropy = FixedEntropy {};
1256		let nonce = Nonce::from_entropy_source(&entropy);
1257		let secp_ctx = Secp256k1::new();
1258
1259		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1260			.path(blinded_path())
1261			.build()
1262			.unwrap();
1263
1264		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
1265			&offer,
1266			payment_paths.clone(),
1267			vec![blinded_path()],
1268			now,
1269			&expanded_key,
1270			nonce,
1271			&secp_ctx,
1272		)
1273		.unwrap()
1274		.allow_mpp()
1275		.build_and_sign(&secp_ctx)
1276		.unwrap();
1277
1278		let mut buffer = Vec::new();
1279		invoice.write(&mut buffer).unwrap();
1280
1281		match StaticInvoice::try_from(buffer) {
1282			Ok(invoice) => {
1283				let mut features = Bolt12InvoiceFeatures::empty();
1284				features.set_basic_mpp_optional();
1285				assert_eq!(invoice.invoice_features(), &features);
1286			},
1287			Err(e) => panic!("error parsing invoice: {:?}", e),
1288		}
1289	}
1290
1291	#[test]
1292	fn fails_parsing_missing_invoice_fields() {
1293		// Error if `created_at` is missing.
1294		let missing_created_at_invoice = invoice();
1295		let mut tlv_stream = missing_created_at_invoice.as_tlv_stream();
1296		tlv_stream.1.created_at = None;
1297		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1298			Ok(_) => panic!("expected error"),
1299			Err(e) => {
1300				assert_eq!(
1301					e,
1302					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingCreationTime)
1303				);
1304			},
1305		}
1306
1307		// Error if `node_id` is missing.
1308		let missing_node_id_invoice = invoice();
1309		let mut tlv_stream = missing_node_id_invoice.as_tlv_stream();
1310		tlv_stream.1.node_id = None;
1311		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1312			Ok(_) => panic!("expected error"),
1313			Err(e) => {
1314				assert_eq!(
1315					e,
1316					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)
1317				);
1318			},
1319		}
1320
1321		// Error if message paths are missing.
1322		let missing_message_paths_invoice = invoice();
1323		let mut tlv_stream = missing_message_paths_invoice.as_tlv_stream();
1324		tlv_stream.1.message_paths = None;
1325		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1326			Ok(_) => panic!("expected error"),
1327			Err(e) => {
1328				assert_eq!(
1329					e,
1330					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)
1331				);
1332			},
1333		}
1334
1335		// Error if signature is missing.
1336		let invoice = invoice();
1337		let mut buffer = Vec::new();
1338		invoice.contents.as_tlv_stream().write(&mut buffer).unwrap();
1339		match StaticInvoice::try_from(buffer) {
1340			Ok(_) => panic!("expected error"),
1341			Err(e) => assert_eq!(
1342				e,
1343				Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)
1344			),
1345		}
1346	}
1347
1348	#[test]
1349	fn fails_parsing_invalid_signing_pubkey() {
1350		let invoice = invoice();
1351		let invalid_pubkey = payer_pubkey();
1352		let mut tlv_stream = invoice.as_tlv_stream();
1353		tlv_stream.1.node_id = Some(&invalid_pubkey);
1354
1355		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1356			Ok(_) => panic!("expected error"),
1357			Err(e) => {
1358				assert_eq!(
1359					e,
1360					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey)
1361				);
1362			},
1363		}
1364	}
1365
1366	#[test]
1367	fn fails_parsing_invoice_with_invalid_signature() {
1368		let mut invoice = invoice();
1369		let last_signature_byte = invoice.bytes.last_mut().unwrap();
1370		*last_signature_byte = last_signature_byte.wrapping_add(1);
1371
1372		let mut buffer = Vec::new();
1373		invoice.write(&mut buffer).unwrap();
1374
1375		match StaticInvoice::try_from(buffer) {
1376			Ok(_) => panic!("expected error"),
1377			Err(e) => {
1378				assert_eq!(
1379					e,
1380					Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)
1381				);
1382			},
1383		}
1384	}
1385
1386	#[test]
1387	fn parses_invoice_with_unknown_tlv_records() {
1388		let node_id = recipient_pubkey();
1389		let payment_paths = payment_paths();
1390		let now = now();
1391		let expanded_key = ExpandedKey::new([42; 32]);
1392		let entropy = FixedEntropy {};
1393		let nonce = Nonce::from_entropy_source(&entropy);
1394		let secp_ctx = Secp256k1::new();
1395
1396		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1397			.path(blinded_path())
1398			.build()
1399			.unwrap();
1400
1401		const UNKNOWN_ODD_TYPE: u64 = INVOICE_TYPES.end - 1;
1402		assert!(UNKNOWN_ODD_TYPE % 2 == 1);
1403
1404		let (mut unsigned_invoice, keys) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1405			&offer,
1406			payment_paths.clone(),
1407			vec![blinded_path()],
1408			now,
1409			&expanded_key,
1410			nonce,
1411			&secp_ctx,
1412		)
1413		.unwrap()
1414		.build()
1415		.unwrap();
1416
1417		let mut unknown_bytes = Vec::new();
1418		BigSize(UNKNOWN_ODD_TYPE).write(&mut unknown_bytes).unwrap();
1419		BigSize(32).write(&mut unknown_bytes).unwrap();
1420		[42u8; 32].write(&mut unknown_bytes).unwrap();
1421
1422		unsigned_invoice.bytes.extend_from_slice(&unknown_bytes);
1423		unsigned_invoice.tagged_hash =
1424			TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &unsigned_invoice.bytes);
1425
1426		let invoice = unsigned_invoice
1427			.sign(|message: &UnsignedStaticInvoice| {
1428				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
1429			})
1430			.unwrap();
1431
1432		let mut encoded_invoice = Vec::new();
1433		invoice.write(&mut encoded_invoice).unwrap();
1434
1435		match StaticInvoice::try_from(encoded_invoice.clone()) {
1436			Ok(invoice) => assert_eq!(invoice.bytes, encoded_invoice),
1437			Err(e) => panic!("error parsing invoice: {:?}", e),
1438		}
1439
1440		const UNKNOWN_EVEN_TYPE: u64 = INVOICE_TYPES.end - 2;
1441		assert!(UNKNOWN_EVEN_TYPE % 2 == 0);
1442
1443		let (mut unsigned_invoice, keys) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1444			&offer,
1445			payment_paths.clone(),
1446			vec![blinded_path()],
1447			now,
1448			&expanded_key,
1449			nonce,
1450			&secp_ctx,
1451		)
1452		.unwrap()
1453		.build()
1454		.unwrap();
1455
1456		let mut unknown_bytes = Vec::new();
1457		BigSize(UNKNOWN_EVEN_TYPE).write(&mut unknown_bytes).unwrap();
1458		BigSize(32).write(&mut unknown_bytes).unwrap();
1459		[42u8; 32].write(&mut unknown_bytes).unwrap();
1460
1461		unsigned_invoice.bytes.extend_from_slice(&unknown_bytes);
1462		unsigned_invoice.tagged_hash =
1463			TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &unsigned_invoice.bytes);
1464
1465		let invoice = unsigned_invoice
1466			.sign(|message: &UnsignedStaticInvoice| {
1467				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
1468			})
1469			.unwrap();
1470
1471		let mut encoded_invoice = Vec::new();
1472		invoice.write(&mut encoded_invoice).unwrap();
1473
1474		match StaticInvoice::try_from(encoded_invoice) {
1475			Ok(_) => panic!("expected error"),
1476			Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::UnknownRequiredFeature)),
1477		}
1478	}
1479
1480	#[test]
1481	fn parses_invoice_with_experimental_tlv_records() {
1482		let node_id = recipient_pubkey();
1483		let payment_paths = payment_paths();
1484		let now = now();
1485		let expanded_key = ExpandedKey::new([42; 32]);
1486		let entropy = FixedEntropy {};
1487		let nonce = Nonce::from_entropy_source(&entropy);
1488		let secp_ctx = Secp256k1::new();
1489
1490		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1491			.path(blinded_path())
1492			.build()
1493			.unwrap();
1494
1495		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
1496			&offer,
1497			payment_paths.clone(),
1498			vec![blinded_path()],
1499			now,
1500			&expanded_key,
1501			nonce,
1502			&secp_ctx,
1503		)
1504		.unwrap()
1505		.experimental_baz(42)
1506		.build_and_sign(&secp_ctx)
1507		.unwrap();
1508
1509		let mut encoded_invoice = Vec::new();
1510		invoice.write(&mut encoded_invoice).unwrap();
1511
1512		assert!(StaticInvoice::try_from(encoded_invoice).is_ok());
1513
1514		const UNKNOWN_ODD_TYPE: u64 = EXPERIMENTAL_INVOICE_TYPES.start + 1;
1515		assert!(UNKNOWN_ODD_TYPE % 2 == 1);
1516
1517		let (mut unsigned_invoice, keys) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1518			&offer,
1519			payment_paths.clone(),
1520			vec![blinded_path()],
1521			now,
1522			&expanded_key,
1523			nonce,
1524			&secp_ctx,
1525		)
1526		.unwrap()
1527		.build()
1528		.unwrap();
1529
1530		let mut unknown_bytes = Vec::new();
1531		BigSize(UNKNOWN_ODD_TYPE).write(&mut unknown_bytes).unwrap();
1532		BigSize(32).write(&mut unknown_bytes).unwrap();
1533		[42u8; 32].write(&mut unknown_bytes).unwrap();
1534
1535		unsigned_invoice.experimental_bytes.extend_from_slice(&unknown_bytes);
1536
1537		let tlv_stream = TlvStream::new(&unsigned_invoice.bytes)
1538			.chain(TlvStream::new(&unsigned_invoice.experimental_bytes));
1539		unsigned_invoice.tagged_hash = TaggedHash::from_tlv_stream(SIGNATURE_TAG, tlv_stream);
1540
1541		let invoice = unsigned_invoice
1542			.sign(|message: &UnsignedStaticInvoice| {
1543				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
1544			})
1545			.unwrap();
1546
1547		let mut encoded_invoice = Vec::new();
1548		invoice.write(&mut encoded_invoice).unwrap();
1549
1550		match StaticInvoice::try_from(encoded_invoice.clone()) {
1551			Ok(invoice) => assert_eq!(invoice.bytes, encoded_invoice),
1552			Err(e) => panic!("error parsing invoice: {:?}", e),
1553		}
1554
1555		const UNKNOWN_EVEN_TYPE: u64 = EXPERIMENTAL_INVOICE_TYPES.start;
1556		assert!(UNKNOWN_EVEN_TYPE % 2 == 0);
1557
1558		let (mut unsigned_invoice, keys) = StaticInvoiceBuilder::for_offer_using_derived_keys(
1559			&offer,
1560			payment_paths.clone(),
1561			vec![blinded_path()],
1562			now,
1563			&expanded_key,
1564			nonce,
1565			&secp_ctx,
1566		)
1567		.unwrap()
1568		.build()
1569		.unwrap();
1570
1571		let mut unknown_bytes = Vec::new();
1572		BigSize(UNKNOWN_EVEN_TYPE).write(&mut unknown_bytes).unwrap();
1573		BigSize(32).write(&mut unknown_bytes).unwrap();
1574		[42u8; 32].write(&mut unknown_bytes).unwrap();
1575
1576		unsigned_invoice.experimental_bytes.extend_from_slice(&unknown_bytes);
1577
1578		let tlv_stream = TlvStream::new(&unsigned_invoice.bytes)
1579			.chain(TlvStream::new(&unsigned_invoice.experimental_bytes));
1580		unsigned_invoice.tagged_hash = TaggedHash::from_tlv_stream(SIGNATURE_TAG, tlv_stream);
1581
1582		let invoice = unsigned_invoice
1583			.sign(|message: &UnsignedStaticInvoice| {
1584				Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
1585			})
1586			.unwrap();
1587
1588		let mut encoded_invoice = Vec::new();
1589		invoice.write(&mut encoded_invoice).unwrap();
1590
1591		match StaticInvoice::try_from(encoded_invoice) {
1592			Ok(_) => panic!("expected error"),
1593			Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::UnknownRequiredFeature)),
1594		}
1595
1596		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1597			.path(blinded_path())
1598			.build()
1599			.unwrap();
1600
1601		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
1602			&offer,
1603			payment_paths.clone(),
1604			vec![blinded_path()],
1605			now,
1606			&expanded_key,
1607			nonce,
1608			&secp_ctx,
1609		)
1610		.unwrap()
1611		.build_and_sign(&secp_ctx)
1612		.unwrap();
1613
1614		let mut encoded_invoice = Vec::new();
1615		invoice.write(&mut encoded_invoice).unwrap();
1616
1617		BigSize(UNKNOWN_ODD_TYPE).write(&mut encoded_invoice).unwrap();
1618		BigSize(32).write(&mut encoded_invoice).unwrap();
1619		[42u8; 32].write(&mut encoded_invoice).unwrap();
1620
1621		match StaticInvoice::try_from(encoded_invoice) {
1622			Ok(_) => panic!("expected error"),
1623			Err(e) => assert_eq!(
1624				e,
1625				Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)
1626			),
1627		}
1628	}
1629
1630	#[test]
1631	fn fails_parsing_invoice_with_out_of_range_tlv_records() {
1632		let invoice = invoice();
1633		let mut encoded_invoice = Vec::new();
1634		invoice.write(&mut encoded_invoice).unwrap();
1635		BigSize(1002).write(&mut encoded_invoice).unwrap();
1636		BigSize(32).write(&mut encoded_invoice).unwrap();
1637		[42u8; 32].write(&mut encoded_invoice).unwrap();
1638
1639		match StaticInvoice::try_from(encoded_invoice) {
1640			Ok(_) => panic!("expected error"),
1641			Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
1642		}
1643	}
1644
1645	#[test]
1646	fn fails_parsing_invoice_with_invalid_offer_fields() {
1647		// Error if the offer is missing paths.
1648		let missing_offer_paths_invoice = invoice();
1649		let mut tlv_stream = missing_offer_paths_invoice.as_tlv_stream();
1650		tlv_stream.0.paths = None;
1651		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1652			Ok(_) => panic!("expected error"),
1653			Err(e) => {
1654				assert_eq!(
1655					e,
1656					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)
1657				);
1658			},
1659		}
1660
1661		// Error if the offer has more than one chain.
1662		let invalid_offer_chains_invoice = invoice();
1663		let mut tlv_stream = invalid_offer_chains_invoice.as_tlv_stream();
1664		let invalid_chains = vec![
1665			ChainHash::using_genesis_block(Network::Bitcoin),
1666			ChainHash::using_genesis_block(Network::Testnet),
1667		];
1668		tlv_stream.0.chains = Some(&invalid_chains);
1669		match StaticInvoice::try_from(tlv_stream_to_bytes(&tlv_stream)) {
1670			Ok(_) => panic!("expected error"),
1671			Err(e) => {
1672				assert_eq!(
1673					e,
1674					Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain)
1675				);
1676			},
1677		}
1678	}
1679
1680	#[test]
1681	fn static_invoice_offer_id_matches_offer_id() {
1682		let node_id = recipient_pubkey();
1683		let payment_paths = payment_paths();
1684		let now = now();
1685		let expanded_key = ExpandedKey::new([42; 32]);
1686		let entropy = FixedEntropy {};
1687		let nonce = Nonce::from_entropy_source(&entropy);
1688		let secp_ctx = Secp256k1::new();
1689
1690		let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx)
1691			.path(blinded_path())
1692			.build()
1693			.unwrap();
1694
1695		let offer_id = offer.id();
1696
1697		let invoice = StaticInvoiceBuilder::for_offer_using_derived_keys(
1698			&offer,
1699			payment_paths.clone(),
1700			vec![blinded_path()],
1701			now,
1702			&expanded_key,
1703			nonce,
1704			&secp_ctx,
1705		)
1706		.unwrap()
1707		.build_and_sign(&secp_ctx)
1708		.unwrap();
1709
1710		assert_eq!(invoice.offer_id(), offer_id);
1711	}
1712}