Merge pull request #2686 from jkczyz/2023-10-onion-message-fuzz
[rust-lightning] / lightning / src / offers / offer.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 `offer` messages.
11 //!
12 //! An [`Offer`] represents an "offer to be paid." It is typically constructed by a merchant and
13 //! published as a QR code to be scanned by a customer. The customer uses the offer to request an
14 //! invoice from the merchant to be paid.
15 //!
16 //! # Example
17 //!
18 //! ```
19 //! extern crate bitcoin;
20 //! extern crate core;
21 //! extern crate lightning;
22 //!
23 //! use core::convert::TryFrom;
24 //! use core::num::NonZeroU64;
25 //! use core::time::Duration;
26 //!
27 //! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
28 //! use lightning::offers::offer::{Offer, OfferBuilder, Quantity};
29 //! use lightning::offers::parse::Bolt12ParseError;
30 //! use lightning::util::ser::{Readable, Writeable};
31 //!
32 //! # use lightning::blinded_path::BlindedPath;
33 //! # #[cfg(feature = "std")]
34 //! # use std::time::SystemTime;
35 //! #
36 //! # fn create_blinded_path() -> BlindedPath { unimplemented!() }
37 //! # fn create_another_blinded_path() -> BlindedPath { unimplemented!() }
38 //! #
39 //! # #[cfg(feature = "std")]
40 //! # fn build() -> Result<(), Bolt12ParseError> {
41 //! let secp_ctx = Secp256k1::new();
42 //! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
43 //! let pubkey = PublicKey::from(keys);
44 //!
45 //! let expiration = SystemTime::now() + Duration::from_secs(24 * 60 * 60);
46 //! let offer = OfferBuilder::new("coffee, large".to_string(), pubkey)
47 //!     .amount_msats(20_000)
48 //!     .supported_quantity(Quantity::Unbounded)
49 //!     .absolute_expiry(expiration.duration_since(SystemTime::UNIX_EPOCH).unwrap())
50 //!     .issuer("Foo Bar".to_string())
51 //!     .path(create_blinded_path())
52 //!     .path(create_another_blinded_path())
53 //!     .build()?;
54 //!
55 //! // Encode as a bech32 string for use in a QR code.
56 //! let encoded_offer = offer.to_string();
57 //!
58 //! // Parse from a bech32 string after scanning from a QR code.
59 //! let offer = encoded_offer.parse::<Offer>()?;
60 //!
61 //! // Encode offer as raw bytes.
62 //! let mut bytes = Vec::new();
63 //! offer.write(&mut bytes).unwrap();
64 //!
65 //! // Decode raw bytes into an offer.
66 //! let offer = Offer::try_from(bytes)?;
67 //! # Ok(())
68 //! # }
69 //! ```
70 //!
71 //! # Note
72 //!
73 //! If constructing an [`Offer`] for use with a [`ChannelManager`], use
74 //! [`ChannelManager::create_offer_builder`] instead of [`OfferBuilder::new`].
75 //!
76 //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
77 //! [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder
78
79 use bitcoin::blockdata::constants::ChainHash;
80 use bitcoin::network::constants::Network;
81 use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
82 use core::convert::TryFrom;
83 use core::num::NonZeroU64;
84 use core::ops::Deref;
85 use core::str::FromStr;
86 use core::time::Duration;
87 use crate::sign::EntropySource;
88 use crate::io;
89 use crate::blinded_path::BlindedPath;
90 use crate::ln::channelmanager::PaymentId;
91 use crate::ln::features::OfferFeatures;
92 use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
93 use crate::ln::msgs::MAX_VALUE_MSAT;
94 use crate::offers::invoice_request::{DerivedPayerId, ExplicitPayerId, InvoiceRequestBuilder};
95 use crate::offers::merkle::TlvStream;
96 use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
97 use crate::offers::signer::{Metadata, MetadataMaterial, self};
98 use crate::util::ser::{HighZeroBytesDroppedBigSize, WithoutLength, Writeable, Writer};
99 use crate::util::string::PrintableString;
100
101 use crate::prelude::*;
102
103 #[cfg(feature = "std")]
104 use std::time::SystemTime;
105
106 pub(super) const IV_BYTES: &[u8; IV_LEN] = b"LDK Offer ~~~~~~";
107
108 /// Builds an [`Offer`] for the "offer to be paid" flow.
109 ///
110 /// See [module-level documentation] for usage.
111 ///
112 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
113 ///
114 /// [module-level documentation]: self
115 pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> {
116         offer: OfferContents,
117         metadata_strategy: core::marker::PhantomData<M>,
118         secp_ctx: Option<&'a Secp256k1<T>>,
119 }
120
121 /// Indicates how [`Offer::metadata`] may be set.
122 ///
123 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
124 pub trait MetadataStrategy {}
125
126 /// [`Offer::metadata`] may be explicitly set or left empty.
127 ///
128 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
129 pub struct ExplicitMetadata {}
130
131 /// [`Offer::metadata`] will be derived.
132 ///
133 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
134 pub struct DerivedMetadata {}
135
136 impl MetadataStrategy for ExplicitMetadata {}
137 impl MetadataStrategy for DerivedMetadata {}
138
139 impl<'a> OfferBuilder<'a, ExplicitMetadata, secp256k1::SignOnly> {
140         /// Creates a new builder for an offer setting the [`Offer::description`] and using the
141         /// [`Offer::signing_pubkey`] for signing invoices. The associated secret key must be remembered
142         /// while the offer is valid.
143         ///
144         /// Use a different pubkey per offer to avoid correlating offers.
145         ///
146         /// # Note
147         ///
148         /// If constructing an [`Offer`] for use with a [`ChannelManager`], use
149         /// [`ChannelManager::create_offer_builder`] instead of [`OfferBuilder::new`].
150         ///
151         /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
152         /// [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder
153         pub fn new(description: String, signing_pubkey: PublicKey) -> Self {
154                 OfferBuilder {
155                         offer: OfferContents {
156                                 chains: None, metadata: None, amount: None, description,
157                                 features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
158                                 supported_quantity: Quantity::One, signing_pubkey,
159                         },
160                         metadata_strategy: core::marker::PhantomData,
161                         secp_ctx: None,
162                 }
163         }
164
165         /// Sets the [`Offer::metadata`] to the given bytes.
166         ///
167         /// Successive calls to this method will override the previous setting.
168         pub fn metadata(mut self, metadata: Vec<u8>) -> Result<Self, Bolt12SemanticError> {
169                 self.offer.metadata = Some(Metadata::Bytes(metadata));
170                 Ok(self)
171         }
172 }
173
174 impl<'a, T: secp256k1::Signing> OfferBuilder<'a, DerivedMetadata, T> {
175         /// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing
176         /// pubkey is derived from the given [`ExpandedKey`] and [`EntropySource`]. This provides
177         /// recipient privacy by using a different signing pubkey for each offer. Otherwise, the
178         /// provided `node_id` is used for the signing pubkey.
179         ///
180         /// Also, sets the metadata when [`OfferBuilder::build`] is called such that it can be used by
181         /// [`InvoiceRequest::verify`] to determine if the request was produced for the offer given an
182         /// [`ExpandedKey`].
183         ///
184         /// [`InvoiceRequest::verify`]: crate::offers::invoice_request::InvoiceRequest::verify
185         /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
186         pub fn deriving_signing_pubkey<ES: Deref>(
187                 description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
188                 secp_ctx: &'a Secp256k1<T>
189         ) -> Self where ES::Target: EntropySource {
190                 let nonce = Nonce::from_entropy_source(entropy_source);
191                 let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, None);
192                 let metadata = Metadata::DerivedSigningPubkey(derivation_material);
193                 OfferBuilder {
194                         offer: OfferContents {
195                                 chains: None, metadata: Some(metadata), amount: None, description,
196                                 features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None,
197                                 supported_quantity: Quantity::One, signing_pubkey: node_id,
198                         },
199                         metadata_strategy: core::marker::PhantomData,
200                         secp_ctx: Some(secp_ctx),
201                 }
202         }
203 }
204
205 impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
206         /// Adds the chain hash of the given [`Network`] to [`Offer::chains`]. If not called,
207         /// the chain hash of [`Network::Bitcoin`] is assumed to be the only one supported.
208         ///
209         /// See [`Offer::chains`] on how this relates to the payment currency.
210         ///
211         /// Successive calls to this method will add another chain hash.
212         pub fn chain(self, network: Network) -> Self {
213                 self.chain_hash(ChainHash::using_genesis_block(network))
214         }
215
216         /// Adds the [`ChainHash`] to [`Offer::chains`]. If not called, the chain hash of
217         /// [`Network::Bitcoin`] is assumed to be the only one supported.
218         ///
219         /// See [`Offer::chains`] on how this relates to the payment currency.
220         ///
221         /// Successive calls to this method will add another chain hash.
222         pub(crate) fn chain_hash(mut self, chain: ChainHash) -> Self {
223                 let chains = self.offer.chains.get_or_insert_with(Vec::new);
224                 if !chains.contains(&chain) {
225                         chains.push(chain);
226                 }
227
228                 self
229         }
230
231         /// Sets the [`Offer::amount`] as an [`Amount::Bitcoin`].
232         ///
233         /// Successive calls to this method will override the previous setting.
234         pub fn amount_msats(self, amount_msats: u64) -> Self {
235                 self.amount(Amount::Bitcoin { amount_msats })
236         }
237
238         /// Sets the [`Offer::amount`].
239         ///
240         /// Successive calls to this method will override the previous setting.
241         pub(super) fn amount(mut self, amount: Amount) -> Self {
242                 self.offer.amount = Some(amount);
243                 self
244         }
245
246         /// Sets the [`Offer::absolute_expiry`] as seconds since the Unix epoch. Any expiry that has
247         /// already passed is valid and can be checked for using [`Offer::is_expired`].
248         ///
249         /// Successive calls to this method will override the previous setting.
250         pub fn absolute_expiry(mut self, absolute_expiry: Duration) -> Self {
251                 self.offer.absolute_expiry = Some(absolute_expiry);
252                 self
253         }
254
255         /// Sets the [`Offer::issuer`].
256         ///
257         /// Successive calls to this method will override the previous setting.
258         pub fn issuer(mut self, issuer: String) -> Self {
259                 self.offer.issuer = Some(issuer);
260                 self
261         }
262
263         /// Adds a blinded path to [`Offer::paths`]. Must include at least one path if only connected by
264         /// private channels or if [`Offer::signing_pubkey`] is not a public node id.
265         ///
266         /// Successive calls to this method will add another blinded path. Caller is responsible for not
267         /// adding duplicate paths.
268         pub fn path(mut self, path: BlindedPath) -> Self {
269                 self.offer.paths.get_or_insert_with(Vec::new).push(path);
270                 self
271         }
272
273         /// Sets the quantity of items for [`Offer::supported_quantity`]. If not called, defaults to
274         /// [`Quantity::One`].
275         ///
276         /// Successive calls to this method will override the previous setting.
277         pub fn supported_quantity(mut self, quantity: Quantity) -> Self {
278                 self.offer.supported_quantity = quantity;
279                 self
280         }
281
282         /// Builds an [`Offer`] from the builder's settings.
283         pub fn build(mut self) -> Result<Offer, Bolt12SemanticError> {
284                 match self.offer.amount {
285                         Some(Amount::Bitcoin { amount_msats }) => {
286                                 if amount_msats > MAX_VALUE_MSAT {
287                                         return Err(Bolt12SemanticError::InvalidAmount);
288                                 }
289                         },
290                         Some(Amount::Currency { .. }) => return Err(Bolt12SemanticError::UnsupportedCurrency),
291                         None => {},
292                 }
293
294                 if let Some(chains) = &self.offer.chains {
295                         if chains.len() == 1 && chains[0] == self.offer.implied_chain() {
296                                 self.offer.chains = None;
297                         }
298                 }
299
300                 Ok(self.build_without_checks())
301         }
302
303         fn build_without_checks(mut self) -> Offer {
304                 // Create the metadata for stateless verification of an InvoiceRequest.
305                 if let Some(mut metadata) = self.offer.metadata.take() {
306                         if metadata.has_derivation_material() {
307                                 if self.offer.paths.is_none() {
308                                         metadata = metadata.without_keys();
309                                 }
310
311                                 let mut tlv_stream = self.offer.as_tlv_stream();
312                                 debug_assert_eq!(tlv_stream.metadata, None);
313                                 tlv_stream.metadata = None;
314                                 if metadata.derives_recipient_keys() {
315                                         tlv_stream.node_id = None;
316                                 }
317
318                                 let (derived_metadata, keys) = metadata.derive_from(tlv_stream, self.secp_ctx);
319                                 metadata = derived_metadata;
320                                 if let Some(keys) = keys {
321                                         self.offer.signing_pubkey = keys.public_key();
322                                 }
323                         }
324
325                         self.offer.metadata = Some(metadata);
326                 }
327
328                 let mut bytes = Vec::new();
329                 self.offer.write(&mut bytes).unwrap();
330
331                 Offer { bytes, contents: self.offer }
332         }
333 }
334
335 #[cfg(test)]
336 impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
337         fn features_unchecked(mut self, features: OfferFeatures) -> Self {
338                 self.offer.features = features;
339                 self
340         }
341
342         pub(super) fn build_unchecked(self) -> Offer {
343                 self.build_without_checks()
344         }
345 }
346
347 /// An `Offer` is a potentially long-lived proposal for payment of a good or service.
348 ///
349 /// An offer is a precursor to an [`InvoiceRequest`]. A merchant publishes an offer from which a
350 /// customer may request an [`Bolt12Invoice`] for a specific quantity and using an amount sufficient
351 /// to cover that quantity (i.e., at least `quantity * amount`). See [`Offer::amount`].
352 ///
353 /// Offers may be denominated in currency other than bitcoin but are ultimately paid using the
354 /// latter.
355 ///
356 /// Through the use of [`BlindedPath`]s, offers provide recipient privacy.
357 ///
358 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
359 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
360 #[derive(Clone, Debug)]
361 #[cfg_attr(test, derive(PartialEq))]
362 pub struct Offer {
363         // The serialized offer. Needed when creating an `InvoiceRequest` if the offer contains unknown
364         // fields.
365         pub(super) bytes: Vec<u8>,
366         pub(super) contents: OfferContents,
367 }
368
369 /// The contents of an [`Offer`], which may be shared with an [`InvoiceRequest`] or a
370 /// [`Bolt12Invoice`].
371 ///
372 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
373 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
374 #[derive(Clone, Debug)]
375 #[cfg_attr(test, derive(PartialEq))]
376 pub(super) struct OfferContents {
377         chains: Option<Vec<ChainHash>>,
378         metadata: Option<Metadata>,
379         amount: Option<Amount>,
380         description: String,
381         features: OfferFeatures,
382         absolute_expiry: Option<Duration>,
383         issuer: Option<String>,
384         paths: Option<Vec<BlindedPath>>,
385         supported_quantity: Quantity,
386         signing_pubkey: PublicKey,
387 }
388
389 macro_rules! offer_accessors { ($self: ident, $contents: expr) => {
390         // TODO: Return a slice once ChainHash has constants.
391         // - https://github.com/rust-bitcoin/rust-bitcoin/pull/1283
392         // - https://github.com/rust-bitcoin/rust-bitcoin/pull/1286
393         /// The chains that may be used when paying a requested invoice (e.g., bitcoin mainnet).
394         /// Payments must be denominated in units of the minimal lightning-payable unit (e.g., msats)
395         /// for the selected chain.
396         pub fn chains(&$self) -> Vec<bitcoin::blockdata::constants::ChainHash> {
397                 $contents.chains()
398         }
399
400         // TODO: Link to corresponding method in `InvoiceRequest`.
401         /// Opaque bytes set by the originator. Useful for authentication and validating fields since it
402         /// is reflected in `invoice_request` messages along with all the other fields from the `offer`.
403         pub fn metadata(&$self) -> Option<&Vec<u8>> {
404                 $contents.metadata()
405         }
406
407         /// The minimum amount required for a successful payment of a single item.
408         pub fn amount(&$self) -> Option<&$crate::offers::offer::Amount> {
409                 $contents.amount()
410         }
411
412         /// A complete description of the purpose of the payment. Intended to be displayed to the user
413         /// but with the caveat that it has not been verified in any way.
414         pub fn description(&$self) -> $crate::util::string::PrintableString {
415                 $contents.description()
416         }
417
418         /// Features pertaining to the offer.
419         pub fn offer_features(&$self) -> &$crate::ln::features::OfferFeatures {
420                 &$contents.features()
421         }
422
423         /// Duration since the Unix epoch when an invoice should no longer be requested.
424         ///
425         /// If `None`, the offer does not expire.
426         pub fn absolute_expiry(&$self) -> Option<core::time::Duration> {
427                 $contents.absolute_expiry()
428         }
429
430         /// The issuer of the offer, possibly beginning with `user@domain` or `domain`. Intended to be
431         /// displayed to the user but with the caveat that it has not been verified in any way.
432         pub fn issuer(&$self) -> Option<$crate::util::string::PrintableString> {
433                 $contents.issuer()
434         }
435
436         /// Paths to the recipient originating from publicly reachable nodes. Blinded paths provide
437         /// recipient privacy by obfuscating its node id.
438         pub fn paths(&$self) -> &[$crate::blinded_path::BlindedPath] {
439                 $contents.paths()
440         }
441
442         /// The quantity of items supported.
443         pub fn supported_quantity(&$self) -> $crate::offers::offer::Quantity {
444                 $contents.supported_quantity()
445         }
446
447         /// The public key used by the recipient to sign invoices.
448         pub fn signing_pubkey(&$self) -> bitcoin::secp256k1::PublicKey {
449                 $contents.signing_pubkey()
450         }
451 } }
452
453 impl Offer {
454         offer_accessors!(self, self.contents);
455
456         pub(super) fn implied_chain(&self) -> ChainHash {
457                 self.contents.implied_chain()
458         }
459
460         /// Returns whether the given chain is supported by the offer.
461         pub fn supports_chain(&self, chain: ChainHash) -> bool {
462                 self.contents.supports_chain(chain)
463         }
464
465         /// Whether the offer has expired.
466         #[cfg(feature = "std")]
467         pub fn is_expired(&self) -> bool {
468                 self.contents.is_expired()
469         }
470
471         /// Whether the offer has expired given the duration since the Unix epoch.
472         pub fn is_expired_no_std(&self, duration_since_epoch: Duration) -> bool {
473                 self.contents.is_expired_no_std(duration_since_epoch)
474         }
475
476         /// Returns whether the given quantity is valid for the offer.
477         pub fn is_valid_quantity(&self, quantity: u64) -> bool {
478                 self.contents.is_valid_quantity(quantity)
479         }
480
481         /// Returns whether a quantity is expected in an [`InvoiceRequest`] for the offer.
482         ///
483         /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
484         pub fn expects_quantity(&self) -> bool {
485                 self.contents.expects_quantity()
486         }
487
488         /// Similar to [`Offer::request_invoice`] except it:
489         /// - derives the [`InvoiceRequest::payer_id`] such that a different key can be used for each
490         ///   request,
491         /// - sets [`InvoiceRequest::payer_metadata`] when [`InvoiceRequestBuilder::build`] is called
492         ///   such that it can be used by [`Bolt12Invoice::verify`] to determine if the invoice was
493         ///   requested using a base [`ExpandedKey`] from which the payer id was derived, and
494         /// - includes the [`PaymentId`] encrypted in [`InvoiceRequest::payer_metadata`] so that it can
495         ///   be used when sending the payment for the requested invoice.
496         ///
497         /// Useful to protect the sender's privacy.
498         ///
499         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
500         ///
501         /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
502         /// [`InvoiceRequest::payer_metadata`]: crate::offers::invoice_request::InvoiceRequest::payer_metadata
503         /// [`Bolt12Invoice::verify`]: crate::offers::invoice::Bolt12Invoice::verify
504         /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
505         pub fn request_invoice_deriving_payer_id<'a, 'b, ES: Deref, T: secp256k1::Signing>(
506                 &'a self, expanded_key: &ExpandedKey, entropy_source: ES, secp_ctx: &'b Secp256k1<T>,
507                 payment_id: PaymentId
508         ) -> Result<InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T>, Bolt12SemanticError>
509         where
510                 ES::Target: EntropySource,
511         {
512                 if self.offer_features().requires_unknown_bits() {
513                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
514                 }
515
516                 Ok(InvoiceRequestBuilder::deriving_payer_id(
517                         self, expanded_key, entropy_source, secp_ctx, payment_id
518                 ))
519         }
520
521         /// Similar to [`Offer::request_invoice_deriving_payer_id`] except uses `payer_id` for the
522         /// [`InvoiceRequest::payer_id`] instead of deriving a different key for each request.
523         ///
524         /// Useful for recurring payments using the same `payer_id` with different invoices.
525         ///
526         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
527         ///
528         /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
529         pub fn request_invoice_deriving_metadata<ES: Deref>(
530                 &self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
531                 payment_id: PaymentId
532         ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError>
533         where
534                 ES::Target: EntropySource,
535         {
536                 if self.offer_features().requires_unknown_bits() {
537                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
538                 }
539
540                 Ok(InvoiceRequestBuilder::deriving_metadata(
541                         self, payer_id, expanded_key, entropy_source, payment_id
542                 ))
543         }
544
545         /// Creates an [`InvoiceRequestBuilder`] for the offer with the given `metadata` and `payer_id`,
546         /// which will be reflected in the `Bolt12Invoice` response.
547         ///
548         /// The `metadata` is useful for including information about the derivation of `payer_id` such
549         /// that invoice response handling can be stateless. Also serves as payer-provided entropy while
550         /// hashing in the signature calculation.
551         ///
552         /// This should not leak any information such as by using a simple BIP-32 derivation path.
553         /// Otherwise, payments may be correlated.
554         ///
555         /// Errors if the offer contains unknown required features.
556         ///
557         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
558         ///
559         /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
560         pub fn request_invoice(
561                 &self, metadata: Vec<u8>, payer_id: PublicKey
562         ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError> {
563                 if self.offer_features().requires_unknown_bits() {
564                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
565                 }
566
567                 Ok(InvoiceRequestBuilder::new(self, metadata, payer_id))
568         }
569
570         #[cfg(test)]
571         pub(super) fn as_tlv_stream(&self) -> OfferTlvStreamRef {
572                 self.contents.as_tlv_stream()
573         }
574 }
575
576 impl AsRef<[u8]> for Offer {
577         fn as_ref(&self) -> &[u8] {
578                 &self.bytes
579         }
580 }
581
582 impl OfferContents {
583         pub fn chains(&self) -> Vec<ChainHash> {
584                 self.chains.as_ref().cloned().unwrap_or_else(|| vec![self.implied_chain()])
585         }
586
587         pub fn implied_chain(&self) -> ChainHash {
588                 ChainHash::using_genesis_block(Network::Bitcoin)
589         }
590
591         pub fn supports_chain(&self, chain: ChainHash) -> bool {
592                 self.chains().contains(&chain)
593         }
594
595         pub fn metadata(&self) -> Option<&Vec<u8>> {
596                 self.metadata.as_ref().and_then(|metadata| metadata.as_bytes())
597         }
598
599         pub fn amount(&self) -> Option<&Amount> {
600                 self.amount.as_ref()
601         }
602
603         pub fn description(&self) -> PrintableString {
604                 PrintableString(&self.description)
605         }
606
607         pub fn features(&self) -> &OfferFeatures {
608                 &self.features
609         }
610
611         pub fn absolute_expiry(&self) -> Option<Duration> {
612                 self.absolute_expiry
613         }
614
615         #[cfg(feature = "std")]
616         pub(super) fn is_expired(&self) -> bool {
617                 SystemTime::UNIX_EPOCH
618                         .elapsed()
619                         .map(|duration_since_epoch| self.is_expired_no_std(duration_since_epoch))
620                         .unwrap_or(false)
621         }
622
623         pub(super) fn is_expired_no_std(&self, duration_since_epoch: Duration) -> bool {
624                 self.absolute_expiry
625                         .map(|absolute_expiry| duration_since_epoch > absolute_expiry)
626                         .unwrap_or(false)
627         }
628
629         pub fn issuer(&self) -> Option<PrintableString> {
630                 self.issuer.as_ref().map(|issuer| PrintableString(issuer.as_str()))
631         }
632
633         pub fn paths(&self) -> &[BlindedPath] {
634                 self.paths.as_ref().map(|paths| paths.as_slice()).unwrap_or(&[])
635         }
636
637         pub(super) fn check_amount_msats_for_quantity(
638                 &self, amount_msats: Option<u64>, quantity: Option<u64>
639         ) -> Result<(), Bolt12SemanticError> {
640                 let offer_amount_msats = match self.amount {
641                         None => 0,
642                         Some(Amount::Bitcoin { amount_msats }) => amount_msats,
643                         Some(Amount::Currency { .. }) => return Err(Bolt12SemanticError::UnsupportedCurrency),
644                 };
645
646                 if !self.expects_quantity() || quantity.is_some() {
647                         let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1))
648                                 .ok_or(Bolt12SemanticError::InvalidAmount)?;
649                         let amount_msats = amount_msats.unwrap_or(expected_amount_msats);
650
651                         if amount_msats < expected_amount_msats {
652                                 return Err(Bolt12SemanticError::InsufficientAmount);
653                         }
654
655                         if amount_msats > MAX_VALUE_MSAT {
656                                 return Err(Bolt12SemanticError::InvalidAmount);
657                         }
658                 }
659
660                 Ok(())
661         }
662
663         pub fn supported_quantity(&self) -> Quantity {
664                 self.supported_quantity
665         }
666
667         pub(super) fn check_quantity(&self, quantity: Option<u64>) -> Result<(), Bolt12SemanticError> {
668                 let expects_quantity = self.expects_quantity();
669                 match quantity {
670                         None if expects_quantity => Err(Bolt12SemanticError::MissingQuantity),
671                         Some(_) if !expects_quantity => Err(Bolt12SemanticError::UnexpectedQuantity),
672                         Some(quantity) if !self.is_valid_quantity(quantity) => {
673                                 Err(Bolt12SemanticError::InvalidQuantity)
674                         },
675                         _ => Ok(()),
676                 }
677         }
678
679         fn is_valid_quantity(&self, quantity: u64) -> bool {
680                 match self.supported_quantity {
681                         Quantity::Bounded(n) => quantity <= n.get(),
682                         Quantity::Unbounded => quantity > 0,
683                         Quantity::One => quantity == 1,
684                 }
685         }
686
687         fn expects_quantity(&self) -> bool {
688                 match self.supported_quantity {
689                         Quantity::Bounded(_) => true,
690                         Quantity::Unbounded => true,
691                         Quantity::One => false,
692                 }
693         }
694
695         pub(super) fn signing_pubkey(&self) -> PublicKey {
696                 self.signing_pubkey
697         }
698
699         /// Verifies that the offer metadata was produced from the offer in the TLV stream.
700         pub(super) fn verify<T: secp256k1::Signing>(
701                 &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1<T>
702         ) -> Result<Option<KeyPair>, ()> {
703                 match self.metadata() {
704                         Some(metadata) => {
705                                 let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
706                                         match record.r#type {
707                                                 OFFER_METADATA_TYPE => false,
708                                                 OFFER_NODE_ID_TYPE => {
709                                                         !self.metadata.as_ref().unwrap().derives_recipient_keys()
710                                                 },
711                                                 _ => true,
712                                         }
713                                 });
714                                 signer::verify_recipient_metadata(
715                                         metadata, key, IV_BYTES, self.signing_pubkey(), tlv_stream, secp_ctx
716                                 )
717                         },
718                         None => Err(()),
719                 }
720         }
721
722         pub(super) fn as_tlv_stream(&self) -> OfferTlvStreamRef {
723                 let (currency, amount) = match &self.amount {
724                         None => (None, None),
725                         Some(Amount::Bitcoin { amount_msats }) => (None, Some(*amount_msats)),
726                         Some(Amount::Currency { iso4217_code, amount }) => (
727                                 Some(iso4217_code), Some(*amount)
728                         ),
729                 };
730
731                 let features = {
732                         if self.features == OfferFeatures::empty() { None } else { Some(&self.features) }
733                 };
734
735                 OfferTlvStreamRef {
736                         chains: self.chains.as_ref(),
737                         metadata: self.metadata(),
738                         currency,
739                         amount,
740                         description: Some(&self.description),
741                         features,
742                         absolute_expiry: self.absolute_expiry.map(|duration| duration.as_secs()),
743                         paths: self.paths.as_ref(),
744                         issuer: self.issuer.as_ref(),
745                         quantity_max: self.supported_quantity.to_tlv_record(),
746                         node_id: Some(&self.signing_pubkey),
747                 }
748         }
749 }
750
751 impl Writeable for Offer {
752         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
753                 WithoutLength(&self.bytes).write(writer)
754         }
755 }
756
757 impl Writeable for OfferContents {
758         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
759                 self.as_tlv_stream().write(writer)
760         }
761 }
762
763 /// The minimum amount required for an item in an [`Offer`], denominated in either bitcoin or
764 /// another currency.
765 #[derive(Clone, Debug, PartialEq)]
766 pub enum Amount {
767         /// An amount of bitcoin.
768         Bitcoin {
769                 /// The amount in millisatoshi.
770                 amount_msats: u64,
771         },
772         /// An amount of currency specified using ISO 4712.
773         Currency {
774                 /// The currency that the amount is denominated in.
775                 iso4217_code: CurrencyCode,
776                 /// The amount in the currency unit adjusted by the ISO 4712 exponent (e.g., USD cents).
777                 amount: u64,
778         },
779 }
780
781 /// An ISO 4712 three-letter currency code (e.g., USD).
782 pub type CurrencyCode = [u8; 3];
783
784 /// Quantity of items supported by an [`Offer`].
785 #[derive(Clone, Copy, Debug, PartialEq)]
786 pub enum Quantity {
787         /// Up to a specific number of items (inclusive). Use when more than one item can be requested
788         /// but is limited (e.g., because of per customer or inventory limits).
789         ///
790         /// May be used with `NonZeroU64::new(1)` but prefer to use [`Quantity::One`] if only one item
791         /// is supported.
792         Bounded(NonZeroU64),
793         /// One or more items. Use when more than one item can be requested without any limit.
794         Unbounded,
795         /// Only one item. Use when only a single item can be requested.
796         One,
797 }
798
799 impl Quantity {
800         fn to_tlv_record(&self) -> Option<u64> {
801                 match self {
802                         Quantity::Bounded(n) => Some(n.get()),
803                         Quantity::Unbounded => Some(0),
804                         Quantity::One => None,
805                 }
806         }
807 }
808
809 /// Valid type range for offer TLV records.
810 pub(super) const OFFER_TYPES: core::ops::Range<u64> = 1..80;
811
812 /// TLV record type for [`Offer::metadata`].
813 const OFFER_METADATA_TYPE: u64 = 4;
814
815 /// TLV record type for [`Offer::signing_pubkey`].
816 const OFFER_NODE_ID_TYPE: u64 = 22;
817
818 tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, {
819         (2, chains: (Vec<ChainHash>, WithoutLength)),
820         (OFFER_METADATA_TYPE, metadata: (Vec<u8>, WithoutLength)),
821         (6, currency: CurrencyCode),
822         (8, amount: (u64, HighZeroBytesDroppedBigSize)),
823         (10, description: (String, WithoutLength)),
824         (12, features: (OfferFeatures, WithoutLength)),
825         (14, absolute_expiry: (u64, HighZeroBytesDroppedBigSize)),
826         (16, paths: (Vec<BlindedPath>, WithoutLength)),
827         (18, issuer: (String, WithoutLength)),
828         (20, quantity_max: (u64, HighZeroBytesDroppedBigSize)),
829         (OFFER_NODE_ID_TYPE, node_id: PublicKey),
830 });
831
832 impl Bech32Encode for Offer {
833         const BECH32_HRP: &'static str = "lno";
834 }
835
836 impl FromStr for Offer {
837         type Err = Bolt12ParseError;
838
839         fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
840                 Self::from_bech32_str(s)
841         }
842 }
843
844 impl TryFrom<Vec<u8>> for Offer {
845         type Error = Bolt12ParseError;
846
847         fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
848                 let offer = ParsedMessage::<OfferTlvStream>::try_from(bytes)?;
849                 let ParsedMessage { bytes, tlv_stream } = offer;
850                 let contents = OfferContents::try_from(tlv_stream)?;
851                 Ok(Offer { bytes, contents })
852         }
853 }
854
855 impl TryFrom<OfferTlvStream> for OfferContents {
856         type Error = Bolt12SemanticError;
857
858         fn try_from(tlv_stream: OfferTlvStream) -> Result<Self, Self::Error> {
859                 let OfferTlvStream {
860                         chains, metadata, currency, amount, description, features, absolute_expiry, paths,
861                         issuer, quantity_max, node_id,
862                 } = tlv_stream;
863
864                 let metadata = metadata.map(|metadata| Metadata::Bytes(metadata));
865
866                 let amount = match (currency, amount) {
867                         (None, None) => None,
868                         (None, Some(amount_msats)) if amount_msats > MAX_VALUE_MSAT => {
869                                 return Err(Bolt12SemanticError::InvalidAmount);
870                         },
871                         (None, Some(amount_msats)) => Some(Amount::Bitcoin { amount_msats }),
872                         (Some(_), None) => return Err(Bolt12SemanticError::MissingAmount),
873                         (Some(iso4217_code), Some(amount)) => Some(Amount::Currency { iso4217_code, amount }),
874                 };
875
876                 let description = match description {
877                         None => return Err(Bolt12SemanticError::MissingDescription),
878                         Some(description) => description,
879                 };
880
881                 let features = features.unwrap_or_else(OfferFeatures::empty);
882
883                 let absolute_expiry = absolute_expiry
884                         .map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch));
885
886                 let supported_quantity = match quantity_max {
887                         None => Quantity::One,
888                         Some(0) => Quantity::Unbounded,
889                         Some(n) => Quantity::Bounded(NonZeroU64::new(n).unwrap()),
890                 };
891
892                 let signing_pubkey = match node_id {
893                         None => return Err(Bolt12SemanticError::MissingSigningPubkey),
894                         Some(node_id) => node_id,
895                 };
896
897                 Ok(OfferContents {
898                         chains, metadata, amount, description, features, absolute_expiry, issuer, paths,
899                         supported_quantity, signing_pubkey,
900                 })
901         }
902 }
903
904 impl core::fmt::Display for Offer {
905         fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
906                 self.fmt_bech32_str(f)
907         }
908 }
909
910 #[cfg(test)]
911 mod tests {
912         use super::{Amount, Offer, OfferBuilder, OfferTlvStreamRef, Quantity};
913
914         use bitcoin::blockdata::constants::ChainHash;
915         use bitcoin::network::constants::Network;
916         use bitcoin::secp256k1::Secp256k1;
917         use core::convert::TryFrom;
918         use core::num::NonZeroU64;
919         use core::time::Duration;
920         use crate::blinded_path::{BlindedHop, BlindedPath};
921         use crate::sign::KeyMaterial;
922         use crate::ln::features::OfferFeatures;
923         use crate::ln::inbound_payment::ExpandedKey;
924         use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
925         use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
926         use crate::offers::test_utils::*;
927         use crate::util::ser::{BigSize, Writeable};
928         use crate::util::string::PrintableString;
929
930         #[test]
931         fn builds_offer_with_defaults() {
932                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
933
934                 let mut buffer = Vec::new();
935                 offer.write(&mut buffer).unwrap();
936
937                 assert_eq!(offer.bytes, buffer.as_slice());
938                 assert_eq!(offer.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]);
939                 assert!(offer.supports_chain(ChainHash::using_genesis_block(Network::Bitcoin)));
940                 assert_eq!(offer.metadata(), None);
941                 assert_eq!(offer.amount(), None);
942                 assert_eq!(offer.description(), PrintableString("foo"));
943                 assert_eq!(offer.offer_features(), &OfferFeatures::empty());
944                 assert_eq!(offer.absolute_expiry(), None);
945                 #[cfg(feature = "std")]
946                 assert!(!offer.is_expired());
947                 assert_eq!(offer.paths(), &[]);
948                 assert_eq!(offer.issuer(), None);
949                 assert_eq!(offer.supported_quantity(), Quantity::One);
950                 assert_eq!(offer.signing_pubkey(), pubkey(42));
951
952                 assert_eq!(
953                         offer.as_tlv_stream(),
954                         OfferTlvStreamRef {
955                                 chains: None,
956                                 metadata: None,
957                                 currency: None,
958                                 amount: None,
959                                 description: Some(&String::from("foo")),
960                                 features: None,
961                                 absolute_expiry: None,
962                                 paths: None,
963                                 issuer: None,
964                                 quantity_max: None,
965                                 node_id: Some(&pubkey(42)),
966                         },
967                 );
968
969                 if let Err(e) = Offer::try_from(buffer) {
970                         panic!("error parsing offer: {:?}", e);
971                 }
972         }
973
974         #[test]
975         fn builds_offer_with_chains() {
976                 let mainnet = ChainHash::using_genesis_block(Network::Bitcoin);
977                 let testnet = ChainHash::using_genesis_block(Network::Testnet);
978
979                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
980                         .chain(Network::Bitcoin)
981                         .build()
982                         .unwrap();
983                 assert!(offer.supports_chain(mainnet));
984                 assert_eq!(offer.chains(), vec![mainnet]);
985                 assert_eq!(offer.as_tlv_stream().chains, None);
986
987                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
988                         .chain(Network::Testnet)
989                         .build()
990                         .unwrap();
991                 assert!(offer.supports_chain(testnet));
992                 assert_eq!(offer.chains(), vec![testnet]);
993                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![testnet]));
994
995                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
996                         .chain(Network::Testnet)
997                         .chain(Network::Testnet)
998                         .build()
999                         .unwrap();
1000                 assert!(offer.supports_chain(testnet));
1001                 assert_eq!(offer.chains(), vec![testnet]);
1002                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![testnet]));
1003
1004                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1005                         .chain(Network::Bitcoin)
1006                         .chain(Network::Testnet)
1007                         .build()
1008                         .unwrap();
1009                 assert!(offer.supports_chain(mainnet));
1010                 assert!(offer.supports_chain(testnet));
1011                 assert_eq!(offer.chains(), vec![mainnet, testnet]);
1012                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![mainnet, testnet]));
1013         }
1014
1015         #[test]
1016         fn builds_offer_with_metadata() {
1017                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1018                         .metadata(vec![42; 32]).unwrap()
1019                         .build()
1020                         .unwrap();
1021                 assert_eq!(offer.metadata(), Some(&vec![42; 32]));
1022                 assert_eq!(offer.as_tlv_stream().metadata, Some(&vec![42; 32]));
1023
1024                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1025                         .metadata(vec![42; 32]).unwrap()
1026                         .metadata(vec![43; 32]).unwrap()
1027                         .build()
1028                         .unwrap();
1029                 assert_eq!(offer.metadata(), Some(&vec![43; 32]));
1030                 assert_eq!(offer.as_tlv_stream().metadata, Some(&vec![43; 32]));
1031         }
1032
1033         #[test]
1034         fn builds_offer_with_metadata_derived() {
1035                 let desc = "foo".to_string();
1036                 let node_id = recipient_pubkey();
1037                 let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
1038                 let entropy = FixedEntropy {};
1039                 let secp_ctx = Secp256k1::new();
1040
1041                 let offer = OfferBuilder
1042                         ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
1043                         .amount_msats(1000)
1044                         .build().unwrap();
1045                 assert_eq!(offer.signing_pubkey(), node_id);
1046
1047                 let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1048                         .build().unwrap()
1049                         .sign(payer_sign).unwrap();
1050                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
1051
1052                 // Fails verification with altered offer field
1053                 let mut tlv_stream = offer.as_tlv_stream();
1054                 tlv_stream.amount = Some(100);
1055
1056                 let mut encoded_offer = Vec::new();
1057                 tlv_stream.write(&mut encoded_offer).unwrap();
1058
1059                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1060                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1061                         .build().unwrap()
1062                         .sign(payer_sign).unwrap();
1063                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1064
1065                 // Fails verification with altered metadata
1066                 let mut tlv_stream = offer.as_tlv_stream();
1067                 let metadata = tlv_stream.metadata.unwrap().iter().copied().rev().collect();
1068                 tlv_stream.metadata = Some(&metadata);
1069
1070                 let mut encoded_offer = Vec::new();
1071                 tlv_stream.write(&mut encoded_offer).unwrap();
1072
1073                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1074                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1075                         .build().unwrap()
1076                         .sign(payer_sign).unwrap();
1077                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1078         }
1079
1080         #[test]
1081         fn builds_offer_with_derived_signing_pubkey() {
1082                 let desc = "foo".to_string();
1083                 let node_id = recipient_pubkey();
1084                 let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
1085                 let entropy = FixedEntropy {};
1086                 let secp_ctx = Secp256k1::new();
1087
1088                 let blinded_path = BlindedPath {
1089                         introduction_node_id: pubkey(40),
1090                         blinding_point: pubkey(41),
1091                         blinded_hops: vec![
1092                                 BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] },
1093                                 BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] },
1094                         ],
1095                 };
1096
1097                 let offer = OfferBuilder
1098                         ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
1099                         .amount_msats(1000)
1100                         .path(blinded_path)
1101                         .build().unwrap();
1102                 assert_ne!(offer.signing_pubkey(), node_id);
1103
1104                 let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1105                         .build().unwrap()
1106                         .sign(payer_sign).unwrap();
1107                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
1108
1109                 // Fails verification with altered offer field
1110                 let mut tlv_stream = offer.as_tlv_stream();
1111                 tlv_stream.amount = Some(100);
1112
1113                 let mut encoded_offer = Vec::new();
1114                 tlv_stream.write(&mut encoded_offer).unwrap();
1115
1116                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1117                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1118                         .build().unwrap()
1119                         .sign(payer_sign).unwrap();
1120                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1121
1122                 // Fails verification with altered signing pubkey
1123                 let mut tlv_stream = offer.as_tlv_stream();
1124                 let signing_pubkey = pubkey(1);
1125                 tlv_stream.node_id = Some(&signing_pubkey);
1126
1127                 let mut encoded_offer = Vec::new();
1128                 tlv_stream.write(&mut encoded_offer).unwrap();
1129
1130                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1131                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1132                         .build().unwrap()
1133                         .sign(payer_sign).unwrap();
1134                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1135         }
1136
1137         #[test]
1138         fn builds_offer_with_amount() {
1139                 let bitcoin_amount = Amount::Bitcoin { amount_msats: 1000 };
1140                 let currency_amount = Amount::Currency { iso4217_code: *b"USD", amount: 10 };
1141
1142                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1143                         .amount_msats(1000)
1144                         .build()
1145                         .unwrap();
1146                 let tlv_stream = offer.as_tlv_stream();
1147                 assert_eq!(offer.amount(), Some(&bitcoin_amount));
1148                 assert_eq!(tlv_stream.amount, Some(1000));
1149                 assert_eq!(tlv_stream.currency, None);
1150
1151                 let builder = OfferBuilder::new("foo".into(), pubkey(42))
1152                         .amount(currency_amount.clone());
1153                 let tlv_stream = builder.offer.as_tlv_stream();
1154                 assert_eq!(builder.offer.amount, Some(currency_amount.clone()));
1155                 assert_eq!(tlv_stream.amount, Some(10));
1156                 assert_eq!(tlv_stream.currency, Some(b"USD"));
1157                 match builder.build() {
1158                         Ok(_) => panic!("expected error"),
1159                         Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedCurrency),
1160                 }
1161
1162                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1163                         .amount(currency_amount.clone())
1164                         .amount(bitcoin_amount.clone())
1165                         .build()
1166                         .unwrap();
1167                 let tlv_stream = offer.as_tlv_stream();
1168                 assert_eq!(tlv_stream.amount, Some(1000));
1169                 assert_eq!(tlv_stream.currency, None);
1170
1171                 let invalid_amount = Amount::Bitcoin { amount_msats: MAX_VALUE_MSAT + 1 };
1172                 match OfferBuilder::new("foo".into(), pubkey(42)).amount(invalid_amount).build() {
1173                         Ok(_) => panic!("expected error"),
1174                         Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount),
1175                 }
1176         }
1177
1178         #[test]
1179         fn builds_offer_with_features() {
1180                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1181                         .features_unchecked(OfferFeatures::unknown())
1182                         .build()
1183                         .unwrap();
1184                 assert_eq!(offer.offer_features(), &OfferFeatures::unknown());
1185                 assert_eq!(offer.as_tlv_stream().features, Some(&OfferFeatures::unknown()));
1186
1187                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1188                         .features_unchecked(OfferFeatures::unknown())
1189                         .features_unchecked(OfferFeatures::empty())
1190                         .build()
1191                         .unwrap();
1192                 assert_eq!(offer.offer_features(), &OfferFeatures::empty());
1193                 assert_eq!(offer.as_tlv_stream().features, None);
1194         }
1195
1196         #[test]
1197         fn builds_offer_with_absolute_expiry() {
1198                 let future_expiry = Duration::from_secs(u64::max_value());
1199                 let past_expiry = Duration::from_secs(0);
1200                 let now = future_expiry - Duration::from_secs(1_000);
1201
1202                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1203                         .absolute_expiry(future_expiry)
1204                         .build()
1205                         .unwrap();
1206                 #[cfg(feature = "std")]
1207                 assert!(!offer.is_expired());
1208                 assert!(!offer.is_expired_no_std(now));
1209                 assert_eq!(offer.absolute_expiry(), Some(future_expiry));
1210                 assert_eq!(offer.as_tlv_stream().absolute_expiry, Some(future_expiry.as_secs()));
1211
1212                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1213                         .absolute_expiry(future_expiry)
1214                         .absolute_expiry(past_expiry)
1215                         .build()
1216                         .unwrap();
1217                 #[cfg(feature = "std")]
1218                 assert!(offer.is_expired());
1219                 assert!(offer.is_expired_no_std(now));
1220                 assert_eq!(offer.absolute_expiry(), Some(past_expiry));
1221                 assert_eq!(offer.as_tlv_stream().absolute_expiry, Some(past_expiry.as_secs()));
1222         }
1223
1224         #[test]
1225         fn builds_offer_with_paths() {
1226                 let paths = vec![
1227                         BlindedPath {
1228                                 introduction_node_id: pubkey(40),
1229                                 blinding_point: pubkey(41),
1230                                 blinded_hops: vec![
1231                                         BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] },
1232                                         BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
1233                                 ],
1234                         },
1235                         BlindedPath {
1236                                 introduction_node_id: pubkey(40),
1237                                 blinding_point: pubkey(41),
1238                                 blinded_hops: vec![
1239                                         BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },
1240                                         BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] },
1241                                 ],
1242                         },
1243                 ];
1244
1245                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1246                         .path(paths[0].clone())
1247                         .path(paths[1].clone())
1248                         .build()
1249                         .unwrap();
1250                 let tlv_stream = offer.as_tlv_stream();
1251                 assert_eq!(offer.paths(), paths.as_slice());
1252                 assert_eq!(offer.signing_pubkey(), pubkey(42));
1253                 assert_ne!(pubkey(42), pubkey(44));
1254                 assert_eq!(tlv_stream.paths, Some(&paths));
1255                 assert_eq!(tlv_stream.node_id, Some(&pubkey(42)));
1256         }
1257
1258         #[test]
1259         fn builds_offer_with_issuer() {
1260                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1261                         .issuer("bar".into())
1262                         .build()
1263                         .unwrap();
1264                 assert_eq!(offer.issuer(), Some(PrintableString("bar")));
1265                 assert_eq!(offer.as_tlv_stream().issuer, Some(&String::from("bar")));
1266
1267                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1268                         .issuer("bar".into())
1269                         .issuer("baz".into())
1270                         .build()
1271                         .unwrap();
1272                 assert_eq!(offer.issuer(), Some(PrintableString("baz")));
1273                 assert_eq!(offer.as_tlv_stream().issuer, Some(&String::from("baz")));
1274         }
1275
1276         #[test]
1277         fn builds_offer_with_supported_quantity() {
1278                 let one = NonZeroU64::new(1).unwrap();
1279                 let ten = NonZeroU64::new(10).unwrap();
1280
1281                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1282                         .supported_quantity(Quantity::One)
1283                         .build()
1284                         .unwrap();
1285                 let tlv_stream = offer.as_tlv_stream();
1286                 assert_eq!(offer.supported_quantity(), Quantity::One);
1287                 assert_eq!(tlv_stream.quantity_max, None);
1288
1289                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1290                         .supported_quantity(Quantity::Unbounded)
1291                         .build()
1292                         .unwrap();
1293                 let tlv_stream = offer.as_tlv_stream();
1294                 assert_eq!(offer.supported_quantity(), Quantity::Unbounded);
1295                 assert_eq!(tlv_stream.quantity_max, Some(0));
1296
1297                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1298                         .supported_quantity(Quantity::Bounded(ten))
1299                         .build()
1300                         .unwrap();
1301                 let tlv_stream = offer.as_tlv_stream();
1302                 assert_eq!(offer.supported_quantity(), Quantity::Bounded(ten));
1303                 assert_eq!(tlv_stream.quantity_max, Some(10));
1304
1305                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1306                         .supported_quantity(Quantity::Bounded(one))
1307                         .build()
1308                         .unwrap();
1309                 let tlv_stream = offer.as_tlv_stream();
1310                 assert_eq!(offer.supported_quantity(), Quantity::Bounded(one));
1311                 assert_eq!(tlv_stream.quantity_max, Some(1));
1312
1313                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1314                         .supported_quantity(Quantity::Bounded(ten))
1315                         .supported_quantity(Quantity::One)
1316                         .build()
1317                         .unwrap();
1318                 let tlv_stream = offer.as_tlv_stream();
1319                 assert_eq!(offer.supported_quantity(), Quantity::One);
1320                 assert_eq!(tlv_stream.quantity_max, None);
1321         }
1322
1323         #[test]
1324         fn fails_requesting_invoice_with_unknown_required_features() {
1325                 match OfferBuilder::new("foo".into(), pubkey(42))
1326                         .features_unchecked(OfferFeatures::unknown())
1327                         .build().unwrap()
1328                         .request_invoice(vec![1; 32], pubkey(43))
1329                 {
1330                         Ok(_) => panic!("expected error"),
1331                         Err(e) => assert_eq!(e, Bolt12SemanticError::UnknownRequiredFeatures),
1332                 }
1333         }
1334
1335         #[test]
1336         fn parses_offer_with_chains() {
1337                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1338                         .chain(Network::Bitcoin)
1339                         .chain(Network::Testnet)
1340                         .build()
1341                         .unwrap();
1342                 if let Err(e) = offer.to_string().parse::<Offer>() {
1343                         panic!("error parsing offer: {:?}", e);
1344                 }
1345         }
1346
1347         #[test]
1348         fn parses_offer_with_amount() {
1349                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1350                         .amount(Amount::Bitcoin { amount_msats: 1000 })
1351                         .build()
1352                         .unwrap();
1353                 if let Err(e) = offer.to_string().parse::<Offer>() {
1354                         panic!("error parsing offer: {:?}", e);
1355                 }
1356
1357                 let mut tlv_stream = offer.as_tlv_stream();
1358                 tlv_stream.amount = Some(1000);
1359                 tlv_stream.currency = Some(b"USD");
1360
1361                 let mut encoded_offer = Vec::new();
1362                 tlv_stream.write(&mut encoded_offer).unwrap();
1363
1364                 if let Err(e) = Offer::try_from(encoded_offer) {
1365                         panic!("error parsing offer: {:?}", e);
1366                 }
1367
1368                 let mut tlv_stream = offer.as_tlv_stream();
1369                 tlv_stream.amount = None;
1370                 tlv_stream.currency = Some(b"USD");
1371
1372                 let mut encoded_offer = Vec::new();
1373                 tlv_stream.write(&mut encoded_offer).unwrap();
1374
1375                 match Offer::try_from(encoded_offer) {
1376                         Ok(_) => panic!("expected error"),
1377                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)),
1378                 }
1379
1380                 let mut tlv_stream = offer.as_tlv_stream();
1381                 tlv_stream.amount = Some(MAX_VALUE_MSAT + 1);
1382                 tlv_stream.currency = None;
1383
1384                 let mut encoded_offer = Vec::new();
1385                 tlv_stream.write(&mut encoded_offer).unwrap();
1386
1387                 match Offer::try_from(encoded_offer) {
1388                         Ok(_) => panic!("expected error"),
1389                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)),
1390                 }
1391         }
1392
1393         #[test]
1394         fn parses_offer_with_description() {
1395                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1396                 if let Err(e) = offer.to_string().parse::<Offer>() {
1397                         panic!("error parsing offer: {:?}", e);
1398                 }
1399
1400                 let mut tlv_stream = offer.as_tlv_stream();
1401                 tlv_stream.description = None;
1402
1403                 let mut encoded_offer = Vec::new();
1404                 tlv_stream.write(&mut encoded_offer).unwrap();
1405
1406                 match Offer::try_from(encoded_offer) {
1407                         Ok(_) => panic!("expected error"),
1408                         Err(e) => {
1409                                 assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription));
1410                         },
1411                 }
1412         }
1413
1414         #[test]
1415         fn parses_offer_with_paths() {
1416                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1417                         .path(BlindedPath {
1418                                 introduction_node_id: pubkey(40),
1419                                 blinding_point: pubkey(41),
1420                                 blinded_hops: vec![
1421                                         BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] },
1422                                         BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
1423                                 ],
1424                         })
1425                         .path(BlindedPath {
1426                                 introduction_node_id: pubkey(40),
1427                                 blinding_point: pubkey(41),
1428                                 blinded_hops: vec![
1429                                         BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },
1430                                         BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] },
1431                                 ],
1432                         })
1433                         .build()
1434                         .unwrap();
1435                 if let Err(e) = offer.to_string().parse::<Offer>() {
1436                         panic!("error parsing offer: {:?}", e);
1437                 }
1438
1439                 let mut builder = OfferBuilder::new("foo".into(), pubkey(42));
1440                 builder.offer.paths = Some(vec![]);
1441
1442                 let offer = builder.build().unwrap();
1443                 if let Err(e) = offer.to_string().parse::<Offer>() {
1444                         panic!("error parsing offer: {:?}", e);
1445                 }
1446         }
1447
1448         #[test]
1449         fn parses_offer_with_quantity() {
1450                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1451                         .supported_quantity(Quantity::One)
1452                         .build()
1453                         .unwrap();
1454                 if let Err(e) = offer.to_string().parse::<Offer>() {
1455                         panic!("error parsing offer: {:?}", e);
1456                 }
1457
1458                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1459                         .supported_quantity(Quantity::Unbounded)
1460                         .build()
1461                         .unwrap();
1462                 if let Err(e) = offer.to_string().parse::<Offer>() {
1463                         panic!("error parsing offer: {:?}", e);
1464                 }
1465
1466                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1467                         .supported_quantity(Quantity::Bounded(NonZeroU64::new(10).unwrap()))
1468                         .build()
1469                         .unwrap();
1470                 if let Err(e) = offer.to_string().parse::<Offer>() {
1471                         panic!("error parsing offer: {:?}", e);
1472                 }
1473
1474                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1475                         .supported_quantity(Quantity::Bounded(NonZeroU64::new(1).unwrap()))
1476                         .build()
1477                         .unwrap();
1478                 if let Err(e) = offer.to_string().parse::<Offer>() {
1479                         panic!("error parsing offer: {:?}", e);
1480                 }
1481         }
1482
1483         #[test]
1484         fn parses_offer_with_node_id() {
1485                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1486                 if let Err(e) = offer.to_string().parse::<Offer>() {
1487                         panic!("error parsing offer: {:?}", e);
1488                 }
1489
1490                 let mut tlv_stream = offer.as_tlv_stream();
1491                 tlv_stream.node_id = None;
1492
1493                 let mut encoded_offer = Vec::new();
1494                 tlv_stream.write(&mut encoded_offer).unwrap();
1495
1496                 match Offer::try_from(encoded_offer) {
1497                         Ok(_) => panic!("expected error"),
1498                         Err(e) => {
1499                                 assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
1500                         },
1501                 }
1502         }
1503
1504         #[test]
1505         fn fails_parsing_offer_with_extra_tlv_records() {
1506                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1507
1508                 let mut encoded_offer = Vec::new();
1509                 offer.write(&mut encoded_offer).unwrap();
1510                 BigSize(80).write(&mut encoded_offer).unwrap();
1511                 BigSize(32).write(&mut encoded_offer).unwrap();
1512                 [42u8; 32].write(&mut encoded_offer).unwrap();
1513
1514                 match Offer::try_from(encoded_offer) {
1515                         Ok(_) => panic!("expected error"),
1516                         Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
1517                 }
1518         }
1519 }
1520
1521 #[cfg(test)]
1522 mod bech32_tests {
1523         use super::{Bolt12ParseError, Offer};
1524         use bitcoin::bech32;
1525         use crate::ln::msgs::DecodeError;
1526
1527         #[test]
1528         fn encodes_offer_as_bech32_without_checksum() {
1529                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg";
1530                 let offer = dbg!(encoded_offer.parse::<Offer>().unwrap());
1531                 let reencoded_offer = offer.to_string();
1532                 dbg!(reencoded_offer.parse::<Offer>().unwrap());
1533                 assert_eq!(reencoded_offer, encoded_offer);
1534         }
1535
1536         #[test]
1537         fn parses_bech32_encoded_offers() {
1538                 let offers = [
1539                         // BOLT 12 test vectors
1540                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1541                         "l+no1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1542                         "lno1pqps7sjqpgt+yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+5k7msjzfpy7nz5yqcn+ygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+5xvxg",
1543                         "lno1pqps7sjqpgt+ yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+  5k7msjzfpy7nz5yqcn+\nygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+\r\n 5xvxg",
1544                 ];
1545                 for encoded_offer in &offers {
1546                         if let Err(e) = encoded_offer.parse::<Offer>() {
1547                                 panic!("Invalid offer ({:?}): {}", e, encoded_offer);
1548                         }
1549                 }
1550         }
1551
1552         #[test]
1553         fn fails_parsing_bech32_encoded_offers_with_invalid_continuations() {
1554                 let offers = [
1555                         // BOLT 12 test vectors
1556                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+",
1557                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+ ",
1558                         "+lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1559                         "+ lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1560                         "ln++o1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1561                 ];
1562                 for encoded_offer in &offers {
1563                         match encoded_offer.parse::<Offer>() {
1564                                 Ok(_) => panic!("Valid offer: {}", encoded_offer),
1565                                 Err(e) => assert_eq!(e, Bolt12ParseError::InvalidContinuation),
1566                         }
1567                 }
1568
1569         }
1570
1571         #[test]
1572         fn fails_parsing_bech32_encoded_offer_with_invalid_hrp() {
1573                 let encoded_offer = "lni1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg";
1574                 match encoded_offer.parse::<Offer>() {
1575                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1576                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidBech32Hrp),
1577                 }
1578         }
1579
1580         #[test]
1581         fn fails_parsing_bech32_encoded_offer_with_invalid_bech32_data() {
1582                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo";
1583                 match encoded_offer.parse::<Offer>() {
1584                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1585                         Err(e) => assert_eq!(e, Bolt12ParseError::Bech32(bech32::Error::InvalidChar('o'))),
1586                 }
1587         }
1588
1589         #[test]
1590         fn fails_parsing_bech32_encoded_offer_with_invalid_tlv_data() {
1591                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxgqqqqq";
1592                 match encoded_offer.parse::<Offer>() {
1593                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1594                         Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
1595                 }
1596         }
1597 }