Merge pull request #2636 from slanesuke/impl-ToSocketAddrs-for-Hostname
[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         /// Returns whether the given quantity is valid for the offer.
472         pub fn is_valid_quantity(&self, quantity: u64) -> bool {
473                 self.contents.is_valid_quantity(quantity)
474         }
475
476         /// Returns whether a quantity is expected in an [`InvoiceRequest`] for the offer.
477         ///
478         /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
479         pub fn expects_quantity(&self) -> bool {
480                 self.contents.expects_quantity()
481         }
482
483         /// Similar to [`Offer::request_invoice`] except it:
484         /// - derives the [`InvoiceRequest::payer_id`] such that a different key can be used for each
485         ///   request,
486         /// - sets [`InvoiceRequest::payer_metadata`] when [`InvoiceRequestBuilder::build`] is called
487         ///   such that it can be used by [`Bolt12Invoice::verify`] to determine if the invoice was
488         ///   requested using a base [`ExpandedKey`] from which the payer id was derived, and
489         /// - includes the [`PaymentId`] encrypted in [`InvoiceRequest::payer_metadata`] so that it can
490         ///   be used when sending the payment for the requested invoice.
491         ///
492         /// Useful to protect the sender's privacy.
493         ///
494         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
495         ///
496         /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
497         /// [`InvoiceRequest::payer_metadata`]: crate::offers::invoice_request::InvoiceRequest::payer_metadata
498         /// [`Bolt12Invoice::verify`]: crate::offers::invoice::Bolt12Invoice::verify
499         /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
500         pub fn request_invoice_deriving_payer_id<'a, 'b, ES: Deref, T: secp256k1::Signing>(
501                 &'a self, expanded_key: &ExpandedKey, entropy_source: ES, secp_ctx: &'b Secp256k1<T>,
502                 payment_id: PaymentId
503         ) -> Result<InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T>, Bolt12SemanticError>
504         where
505                 ES::Target: EntropySource,
506         {
507                 if self.offer_features().requires_unknown_bits() {
508                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
509                 }
510
511                 Ok(InvoiceRequestBuilder::deriving_payer_id(
512                         self, expanded_key, entropy_source, secp_ctx, payment_id
513                 ))
514         }
515
516         /// Similar to [`Offer::request_invoice_deriving_payer_id`] except uses `payer_id` for the
517         /// [`InvoiceRequest::payer_id`] instead of deriving a different key for each request.
518         ///
519         /// Useful for recurring payments using the same `payer_id` with different invoices.
520         ///
521         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
522         ///
523         /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
524         pub fn request_invoice_deriving_metadata<ES: Deref>(
525                 &self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
526                 payment_id: PaymentId
527         ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError>
528         where
529                 ES::Target: EntropySource,
530         {
531                 if self.offer_features().requires_unknown_bits() {
532                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
533                 }
534
535                 Ok(InvoiceRequestBuilder::deriving_metadata(
536                         self, payer_id, expanded_key, entropy_source, payment_id
537                 ))
538         }
539
540         /// Creates an [`InvoiceRequestBuilder`] for the offer with the given `metadata` and `payer_id`,
541         /// which will be reflected in the `Bolt12Invoice` response.
542         ///
543         /// The `metadata` is useful for including information about the derivation of `payer_id` such
544         /// that invoice response handling can be stateless. Also serves as payer-provided entropy while
545         /// hashing in the signature calculation.
546         ///
547         /// This should not leak any information such as by using a simple BIP-32 derivation path.
548         /// Otherwise, payments may be correlated.
549         ///
550         /// Errors if the offer contains unknown required features.
551         ///
552         /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
553         ///
554         /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
555         pub fn request_invoice(
556                 &self, metadata: Vec<u8>, payer_id: PublicKey
557         ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError> {
558                 if self.offer_features().requires_unknown_bits() {
559                         return Err(Bolt12SemanticError::UnknownRequiredFeatures);
560                 }
561
562                 Ok(InvoiceRequestBuilder::new(self, metadata, payer_id))
563         }
564
565         #[cfg(test)]
566         pub(super) fn as_tlv_stream(&self) -> OfferTlvStreamRef {
567                 self.contents.as_tlv_stream()
568         }
569 }
570
571 impl AsRef<[u8]> for Offer {
572         fn as_ref(&self) -> &[u8] {
573                 &self.bytes
574         }
575 }
576
577 impl OfferContents {
578         pub fn chains(&self) -> Vec<ChainHash> {
579                 self.chains.as_ref().cloned().unwrap_or_else(|| vec![self.implied_chain()])
580         }
581
582         pub fn implied_chain(&self) -> ChainHash {
583                 ChainHash::using_genesis_block(Network::Bitcoin)
584         }
585
586         pub fn supports_chain(&self, chain: ChainHash) -> bool {
587                 self.chains().contains(&chain)
588         }
589
590         pub fn metadata(&self) -> Option<&Vec<u8>> {
591                 self.metadata.as_ref().and_then(|metadata| metadata.as_bytes())
592         }
593
594         pub fn amount(&self) -> Option<&Amount> {
595                 self.amount.as_ref()
596         }
597
598         pub fn description(&self) -> PrintableString {
599                 PrintableString(&self.description)
600         }
601
602         pub fn features(&self) -> &OfferFeatures {
603                 &self.features
604         }
605
606         pub fn absolute_expiry(&self) -> Option<Duration> {
607                 self.absolute_expiry
608         }
609
610         #[cfg(feature = "std")]
611         pub(super) fn is_expired(&self) -> bool {
612                 match self.absolute_expiry {
613                         Some(seconds_from_epoch) => match SystemTime::UNIX_EPOCH.elapsed() {
614                                 Ok(elapsed) => elapsed > seconds_from_epoch,
615                                 Err(_) => false,
616                         },
617                         None => false,
618                 }
619         }
620
621         pub fn issuer(&self) -> Option<PrintableString> {
622                 self.issuer.as_ref().map(|issuer| PrintableString(issuer.as_str()))
623         }
624
625         pub fn paths(&self) -> &[BlindedPath] {
626                 self.paths.as_ref().map(|paths| paths.as_slice()).unwrap_or(&[])
627         }
628
629         pub(super) fn check_amount_msats_for_quantity(
630                 &self, amount_msats: Option<u64>, quantity: Option<u64>
631         ) -> Result<(), Bolt12SemanticError> {
632                 let offer_amount_msats = match self.amount {
633                         None => 0,
634                         Some(Amount::Bitcoin { amount_msats }) => amount_msats,
635                         Some(Amount::Currency { .. }) => return Err(Bolt12SemanticError::UnsupportedCurrency),
636                 };
637
638                 if !self.expects_quantity() || quantity.is_some() {
639                         let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1))
640                                 .ok_or(Bolt12SemanticError::InvalidAmount)?;
641                         let amount_msats = amount_msats.unwrap_or(expected_amount_msats);
642
643                         if amount_msats < expected_amount_msats {
644                                 return Err(Bolt12SemanticError::InsufficientAmount);
645                         }
646
647                         if amount_msats > MAX_VALUE_MSAT {
648                                 return Err(Bolt12SemanticError::InvalidAmount);
649                         }
650                 }
651
652                 Ok(())
653         }
654
655         pub fn supported_quantity(&self) -> Quantity {
656                 self.supported_quantity
657         }
658
659         pub(super) fn check_quantity(&self, quantity: Option<u64>) -> Result<(), Bolt12SemanticError> {
660                 let expects_quantity = self.expects_quantity();
661                 match quantity {
662                         None if expects_quantity => Err(Bolt12SemanticError::MissingQuantity),
663                         Some(_) if !expects_quantity => Err(Bolt12SemanticError::UnexpectedQuantity),
664                         Some(quantity) if !self.is_valid_quantity(quantity) => {
665                                 Err(Bolt12SemanticError::InvalidQuantity)
666                         },
667                         _ => Ok(()),
668                 }
669         }
670
671         fn is_valid_quantity(&self, quantity: u64) -> bool {
672                 match self.supported_quantity {
673                         Quantity::Bounded(n) => quantity <= n.get(),
674                         Quantity::Unbounded => quantity > 0,
675                         Quantity::One => quantity == 1,
676                 }
677         }
678
679         fn expects_quantity(&self) -> bool {
680                 match self.supported_quantity {
681                         Quantity::Bounded(_) => true,
682                         Quantity::Unbounded => true,
683                         Quantity::One => false,
684                 }
685         }
686
687         pub(super) fn signing_pubkey(&self) -> PublicKey {
688                 self.signing_pubkey
689         }
690
691         /// Verifies that the offer metadata was produced from the offer in the TLV stream.
692         pub(super) fn verify<T: secp256k1::Signing>(
693                 &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1<T>
694         ) -> Result<Option<KeyPair>, ()> {
695                 match self.metadata() {
696                         Some(metadata) => {
697                                 let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
698                                         match record.r#type {
699                                                 OFFER_METADATA_TYPE => false,
700                                                 OFFER_NODE_ID_TYPE => {
701                                                         !self.metadata.as_ref().unwrap().derives_recipient_keys()
702                                                 },
703                                                 _ => true,
704                                         }
705                                 });
706                                 signer::verify_recipient_metadata(
707                                         metadata, key, IV_BYTES, self.signing_pubkey(), tlv_stream, secp_ctx
708                                 )
709                         },
710                         None => Err(()),
711                 }
712         }
713
714         pub(super) fn as_tlv_stream(&self) -> OfferTlvStreamRef {
715                 let (currency, amount) = match &self.amount {
716                         None => (None, None),
717                         Some(Amount::Bitcoin { amount_msats }) => (None, Some(*amount_msats)),
718                         Some(Amount::Currency { iso4217_code, amount }) => (
719                                 Some(iso4217_code), Some(*amount)
720                         ),
721                 };
722
723                 let features = {
724                         if self.features == OfferFeatures::empty() { None } else { Some(&self.features) }
725                 };
726
727                 OfferTlvStreamRef {
728                         chains: self.chains.as_ref(),
729                         metadata: self.metadata(),
730                         currency,
731                         amount,
732                         description: Some(&self.description),
733                         features,
734                         absolute_expiry: self.absolute_expiry.map(|duration| duration.as_secs()),
735                         paths: self.paths.as_ref(),
736                         issuer: self.issuer.as_ref(),
737                         quantity_max: self.supported_quantity.to_tlv_record(),
738                         node_id: Some(&self.signing_pubkey),
739                 }
740         }
741 }
742
743 impl Writeable for Offer {
744         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
745                 WithoutLength(&self.bytes).write(writer)
746         }
747 }
748
749 impl Writeable for OfferContents {
750         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
751                 self.as_tlv_stream().write(writer)
752         }
753 }
754
755 /// The minimum amount required for an item in an [`Offer`], denominated in either bitcoin or
756 /// another currency.
757 #[derive(Clone, Debug, PartialEq)]
758 pub enum Amount {
759         /// An amount of bitcoin.
760         Bitcoin {
761                 /// The amount in millisatoshi.
762                 amount_msats: u64,
763         },
764         /// An amount of currency specified using ISO 4712.
765         Currency {
766                 /// The currency that the amount is denominated in.
767                 iso4217_code: CurrencyCode,
768                 /// The amount in the currency unit adjusted by the ISO 4712 exponent (e.g., USD cents).
769                 amount: u64,
770         },
771 }
772
773 /// An ISO 4712 three-letter currency code (e.g., USD).
774 pub type CurrencyCode = [u8; 3];
775
776 /// Quantity of items supported by an [`Offer`].
777 #[derive(Clone, Copy, Debug, PartialEq)]
778 pub enum Quantity {
779         /// Up to a specific number of items (inclusive). Use when more than one item can be requested
780         /// but is limited (e.g., because of per customer or inventory limits).
781         ///
782         /// May be used with `NonZeroU64::new(1)` but prefer to use [`Quantity::One`] if only one item
783         /// is supported.
784         Bounded(NonZeroU64),
785         /// One or more items. Use when more than one item can be requested without any limit.
786         Unbounded,
787         /// Only one item. Use when only a single item can be requested.
788         One,
789 }
790
791 impl Quantity {
792         fn to_tlv_record(&self) -> Option<u64> {
793                 match self {
794                         Quantity::Bounded(n) => Some(n.get()),
795                         Quantity::Unbounded => Some(0),
796                         Quantity::One => None,
797                 }
798         }
799 }
800
801 /// Valid type range for offer TLV records.
802 pub(super) const OFFER_TYPES: core::ops::Range<u64> = 1..80;
803
804 /// TLV record type for [`Offer::metadata`].
805 const OFFER_METADATA_TYPE: u64 = 4;
806
807 /// TLV record type for [`Offer::signing_pubkey`].
808 const OFFER_NODE_ID_TYPE: u64 = 22;
809
810 tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, {
811         (2, chains: (Vec<ChainHash>, WithoutLength)),
812         (OFFER_METADATA_TYPE, metadata: (Vec<u8>, WithoutLength)),
813         (6, currency: CurrencyCode),
814         (8, amount: (u64, HighZeroBytesDroppedBigSize)),
815         (10, description: (String, WithoutLength)),
816         (12, features: (OfferFeatures, WithoutLength)),
817         (14, absolute_expiry: (u64, HighZeroBytesDroppedBigSize)),
818         (16, paths: (Vec<BlindedPath>, WithoutLength)),
819         (18, issuer: (String, WithoutLength)),
820         (20, quantity_max: (u64, HighZeroBytesDroppedBigSize)),
821         (OFFER_NODE_ID_TYPE, node_id: PublicKey),
822 });
823
824 impl Bech32Encode for Offer {
825         const BECH32_HRP: &'static str = "lno";
826 }
827
828 impl FromStr for Offer {
829         type Err = Bolt12ParseError;
830
831         fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
832                 Self::from_bech32_str(s)
833         }
834 }
835
836 impl TryFrom<Vec<u8>> for Offer {
837         type Error = Bolt12ParseError;
838
839         fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
840                 let offer = ParsedMessage::<OfferTlvStream>::try_from(bytes)?;
841                 let ParsedMessage { bytes, tlv_stream } = offer;
842                 let contents = OfferContents::try_from(tlv_stream)?;
843                 Ok(Offer { bytes, contents })
844         }
845 }
846
847 impl TryFrom<OfferTlvStream> for OfferContents {
848         type Error = Bolt12SemanticError;
849
850         fn try_from(tlv_stream: OfferTlvStream) -> Result<Self, Self::Error> {
851                 let OfferTlvStream {
852                         chains, metadata, currency, amount, description, features, absolute_expiry, paths,
853                         issuer, quantity_max, node_id,
854                 } = tlv_stream;
855
856                 let metadata = metadata.map(|metadata| Metadata::Bytes(metadata));
857
858                 let amount = match (currency, amount) {
859                         (None, None) => None,
860                         (None, Some(amount_msats)) if amount_msats > MAX_VALUE_MSAT => {
861                                 return Err(Bolt12SemanticError::InvalidAmount);
862                         },
863                         (None, Some(amount_msats)) => Some(Amount::Bitcoin { amount_msats }),
864                         (Some(_), None) => return Err(Bolt12SemanticError::MissingAmount),
865                         (Some(iso4217_code), Some(amount)) => Some(Amount::Currency { iso4217_code, amount }),
866                 };
867
868                 let description = match description {
869                         None => return Err(Bolt12SemanticError::MissingDescription),
870                         Some(description) => description,
871                 };
872
873                 let features = features.unwrap_or_else(OfferFeatures::empty);
874
875                 let absolute_expiry = absolute_expiry
876                         .map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch));
877
878                 let supported_quantity = match quantity_max {
879                         None => Quantity::One,
880                         Some(0) => Quantity::Unbounded,
881                         Some(n) => Quantity::Bounded(NonZeroU64::new(n).unwrap()),
882                 };
883
884                 let signing_pubkey = match node_id {
885                         None => return Err(Bolt12SemanticError::MissingSigningPubkey),
886                         Some(node_id) => node_id,
887                 };
888
889                 Ok(OfferContents {
890                         chains, metadata, amount, description, features, absolute_expiry, issuer, paths,
891                         supported_quantity, signing_pubkey,
892                 })
893         }
894 }
895
896 impl core::fmt::Display for Offer {
897         fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
898                 self.fmt_bech32_str(f)
899         }
900 }
901
902 #[cfg(test)]
903 mod tests {
904         use super::{Amount, Offer, OfferBuilder, OfferTlvStreamRef, Quantity};
905
906         use bitcoin::blockdata::constants::ChainHash;
907         use bitcoin::network::constants::Network;
908         use bitcoin::secp256k1::Secp256k1;
909         use core::convert::TryFrom;
910         use core::num::NonZeroU64;
911         use core::time::Duration;
912         use crate::blinded_path::{BlindedHop, BlindedPath};
913         use crate::sign::KeyMaterial;
914         use crate::ln::features::OfferFeatures;
915         use crate::ln::inbound_payment::ExpandedKey;
916         use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
917         use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
918         use crate::offers::test_utils::*;
919         use crate::util::ser::{BigSize, Writeable};
920         use crate::util::string::PrintableString;
921
922         #[test]
923         fn builds_offer_with_defaults() {
924                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
925
926                 let mut buffer = Vec::new();
927                 offer.write(&mut buffer).unwrap();
928
929                 assert_eq!(offer.bytes, buffer.as_slice());
930                 assert_eq!(offer.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]);
931                 assert!(offer.supports_chain(ChainHash::using_genesis_block(Network::Bitcoin)));
932                 assert_eq!(offer.metadata(), None);
933                 assert_eq!(offer.amount(), None);
934                 assert_eq!(offer.description(), PrintableString("foo"));
935                 assert_eq!(offer.offer_features(), &OfferFeatures::empty());
936                 assert_eq!(offer.absolute_expiry(), None);
937                 #[cfg(feature = "std")]
938                 assert!(!offer.is_expired());
939                 assert_eq!(offer.paths(), &[]);
940                 assert_eq!(offer.issuer(), None);
941                 assert_eq!(offer.supported_quantity(), Quantity::One);
942                 assert_eq!(offer.signing_pubkey(), pubkey(42));
943
944                 assert_eq!(
945                         offer.as_tlv_stream(),
946                         OfferTlvStreamRef {
947                                 chains: None,
948                                 metadata: None,
949                                 currency: None,
950                                 amount: None,
951                                 description: Some(&String::from("foo")),
952                                 features: None,
953                                 absolute_expiry: None,
954                                 paths: None,
955                                 issuer: None,
956                                 quantity_max: None,
957                                 node_id: Some(&pubkey(42)),
958                         },
959                 );
960
961                 if let Err(e) = Offer::try_from(buffer) {
962                         panic!("error parsing offer: {:?}", e);
963                 }
964         }
965
966         #[test]
967         fn builds_offer_with_chains() {
968                 let mainnet = ChainHash::using_genesis_block(Network::Bitcoin);
969                 let testnet = ChainHash::using_genesis_block(Network::Testnet);
970
971                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
972                         .chain(Network::Bitcoin)
973                         .build()
974                         .unwrap();
975                 assert!(offer.supports_chain(mainnet));
976                 assert_eq!(offer.chains(), vec![mainnet]);
977                 assert_eq!(offer.as_tlv_stream().chains, None);
978
979                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
980                         .chain(Network::Testnet)
981                         .build()
982                         .unwrap();
983                 assert!(offer.supports_chain(testnet));
984                 assert_eq!(offer.chains(), vec![testnet]);
985                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![testnet]));
986
987                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
988                         .chain(Network::Testnet)
989                         .chain(Network::Testnet)
990                         .build()
991                         .unwrap();
992                 assert!(offer.supports_chain(testnet));
993                 assert_eq!(offer.chains(), vec![testnet]);
994                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![testnet]));
995
996                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
997                         .chain(Network::Bitcoin)
998                         .chain(Network::Testnet)
999                         .build()
1000                         .unwrap();
1001                 assert!(offer.supports_chain(mainnet));
1002                 assert!(offer.supports_chain(testnet));
1003                 assert_eq!(offer.chains(), vec![mainnet, testnet]);
1004                 assert_eq!(offer.as_tlv_stream().chains, Some(&vec![mainnet, testnet]));
1005         }
1006
1007         #[test]
1008         fn builds_offer_with_metadata() {
1009                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1010                         .metadata(vec![42; 32]).unwrap()
1011                         .build()
1012                         .unwrap();
1013                 assert_eq!(offer.metadata(), Some(&vec![42; 32]));
1014                 assert_eq!(offer.as_tlv_stream().metadata, Some(&vec![42; 32]));
1015
1016                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1017                         .metadata(vec![42; 32]).unwrap()
1018                         .metadata(vec![43; 32]).unwrap()
1019                         .build()
1020                         .unwrap();
1021                 assert_eq!(offer.metadata(), Some(&vec![43; 32]));
1022                 assert_eq!(offer.as_tlv_stream().metadata, Some(&vec![43; 32]));
1023         }
1024
1025         #[test]
1026         fn builds_offer_with_metadata_derived() {
1027                 let desc = "foo".to_string();
1028                 let node_id = recipient_pubkey();
1029                 let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
1030                 let entropy = FixedEntropy {};
1031                 let secp_ctx = Secp256k1::new();
1032
1033                 let offer = OfferBuilder
1034                         ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
1035                         .amount_msats(1000)
1036                         .build().unwrap();
1037                 assert_eq!(offer.signing_pubkey(), node_id);
1038
1039                 let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1040                         .build().unwrap()
1041                         .sign(payer_sign).unwrap();
1042                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
1043
1044                 // Fails verification with altered offer field
1045                 let mut tlv_stream = offer.as_tlv_stream();
1046                 tlv_stream.amount = Some(100);
1047
1048                 let mut encoded_offer = Vec::new();
1049                 tlv_stream.write(&mut encoded_offer).unwrap();
1050
1051                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1052                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1053                         .build().unwrap()
1054                         .sign(payer_sign).unwrap();
1055                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1056
1057                 // Fails verification with altered metadata
1058                 let mut tlv_stream = offer.as_tlv_stream();
1059                 let metadata = tlv_stream.metadata.unwrap().iter().copied().rev().collect();
1060                 tlv_stream.metadata = Some(&metadata);
1061
1062                 let mut encoded_offer = Vec::new();
1063                 tlv_stream.write(&mut encoded_offer).unwrap();
1064
1065                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1066                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1067                         .build().unwrap()
1068                         .sign(payer_sign).unwrap();
1069                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1070         }
1071
1072         #[test]
1073         fn builds_offer_with_derived_signing_pubkey() {
1074                 let desc = "foo".to_string();
1075                 let node_id = recipient_pubkey();
1076                 let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
1077                 let entropy = FixedEntropy {};
1078                 let secp_ctx = Secp256k1::new();
1079
1080                 let blinded_path = BlindedPath {
1081                         introduction_node_id: pubkey(40),
1082                         blinding_point: pubkey(41),
1083                         blinded_hops: vec![
1084                                 BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] },
1085                                 BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] },
1086                         ],
1087                 };
1088
1089                 let offer = OfferBuilder
1090                         ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
1091                         .amount_msats(1000)
1092                         .path(blinded_path)
1093                         .build().unwrap();
1094                 assert_ne!(offer.signing_pubkey(), node_id);
1095
1096                 let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1097                         .build().unwrap()
1098                         .sign(payer_sign).unwrap();
1099                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_ok());
1100
1101                 // Fails verification with altered offer field
1102                 let mut tlv_stream = offer.as_tlv_stream();
1103                 tlv_stream.amount = Some(100);
1104
1105                 let mut encoded_offer = Vec::new();
1106                 tlv_stream.write(&mut encoded_offer).unwrap();
1107
1108                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1109                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1110                         .build().unwrap()
1111                         .sign(payer_sign).unwrap();
1112                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1113
1114                 // Fails verification with altered signing pubkey
1115                 let mut tlv_stream = offer.as_tlv_stream();
1116                 let signing_pubkey = pubkey(1);
1117                 tlv_stream.node_id = Some(&signing_pubkey);
1118
1119                 let mut encoded_offer = Vec::new();
1120                 tlv_stream.write(&mut encoded_offer).unwrap();
1121
1122                 let invoice_request = Offer::try_from(encoded_offer).unwrap()
1123                         .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1124                         .build().unwrap()
1125                         .sign(payer_sign).unwrap();
1126                 assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
1127         }
1128
1129         #[test]
1130         fn builds_offer_with_amount() {
1131                 let bitcoin_amount = Amount::Bitcoin { amount_msats: 1000 };
1132                 let currency_amount = Amount::Currency { iso4217_code: *b"USD", amount: 10 };
1133
1134                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1135                         .amount_msats(1000)
1136                         .build()
1137                         .unwrap();
1138                 let tlv_stream = offer.as_tlv_stream();
1139                 assert_eq!(offer.amount(), Some(&bitcoin_amount));
1140                 assert_eq!(tlv_stream.amount, Some(1000));
1141                 assert_eq!(tlv_stream.currency, None);
1142
1143                 let builder = OfferBuilder::new("foo".into(), pubkey(42))
1144                         .amount(currency_amount.clone());
1145                 let tlv_stream = builder.offer.as_tlv_stream();
1146                 assert_eq!(builder.offer.amount, Some(currency_amount.clone()));
1147                 assert_eq!(tlv_stream.amount, Some(10));
1148                 assert_eq!(tlv_stream.currency, Some(b"USD"));
1149                 match builder.build() {
1150                         Ok(_) => panic!("expected error"),
1151                         Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedCurrency),
1152                 }
1153
1154                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1155                         .amount(currency_amount.clone())
1156                         .amount(bitcoin_amount.clone())
1157                         .build()
1158                         .unwrap();
1159                 let tlv_stream = offer.as_tlv_stream();
1160                 assert_eq!(tlv_stream.amount, Some(1000));
1161                 assert_eq!(tlv_stream.currency, None);
1162
1163                 let invalid_amount = Amount::Bitcoin { amount_msats: MAX_VALUE_MSAT + 1 };
1164                 match OfferBuilder::new("foo".into(), pubkey(42)).amount(invalid_amount).build() {
1165                         Ok(_) => panic!("expected error"),
1166                         Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount),
1167                 }
1168         }
1169
1170         #[test]
1171         fn builds_offer_with_features() {
1172                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1173                         .features_unchecked(OfferFeatures::unknown())
1174                         .build()
1175                         .unwrap();
1176                 assert_eq!(offer.offer_features(), &OfferFeatures::unknown());
1177                 assert_eq!(offer.as_tlv_stream().features, Some(&OfferFeatures::unknown()));
1178
1179                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1180                         .features_unchecked(OfferFeatures::unknown())
1181                         .features_unchecked(OfferFeatures::empty())
1182                         .build()
1183                         .unwrap();
1184                 assert_eq!(offer.offer_features(), &OfferFeatures::empty());
1185                 assert_eq!(offer.as_tlv_stream().features, None);
1186         }
1187
1188         #[test]
1189         fn builds_offer_with_absolute_expiry() {
1190                 let future_expiry = Duration::from_secs(u64::max_value());
1191                 let past_expiry = Duration::from_secs(0);
1192
1193                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1194                         .absolute_expiry(future_expiry)
1195                         .build()
1196                         .unwrap();
1197                 #[cfg(feature = "std")]
1198                 assert!(!offer.is_expired());
1199                 assert_eq!(offer.absolute_expiry(), Some(future_expiry));
1200                 assert_eq!(offer.as_tlv_stream().absolute_expiry, Some(future_expiry.as_secs()));
1201
1202                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1203                         .absolute_expiry(future_expiry)
1204                         .absolute_expiry(past_expiry)
1205                         .build()
1206                         .unwrap();
1207                 #[cfg(feature = "std")]
1208                 assert!(offer.is_expired());
1209                 assert_eq!(offer.absolute_expiry(), Some(past_expiry));
1210                 assert_eq!(offer.as_tlv_stream().absolute_expiry, Some(past_expiry.as_secs()));
1211         }
1212
1213         #[test]
1214         fn builds_offer_with_paths() {
1215                 let paths = vec![
1216                         BlindedPath {
1217                                 introduction_node_id: pubkey(40),
1218                                 blinding_point: pubkey(41),
1219                                 blinded_hops: vec![
1220                                         BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] },
1221                                         BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
1222                                 ],
1223                         },
1224                         BlindedPath {
1225                                 introduction_node_id: pubkey(40),
1226                                 blinding_point: pubkey(41),
1227                                 blinded_hops: vec![
1228                                         BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },
1229                                         BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] },
1230                                 ],
1231                         },
1232                 ];
1233
1234                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1235                         .path(paths[0].clone())
1236                         .path(paths[1].clone())
1237                         .build()
1238                         .unwrap();
1239                 let tlv_stream = offer.as_tlv_stream();
1240                 assert_eq!(offer.paths(), paths.as_slice());
1241                 assert_eq!(offer.signing_pubkey(), pubkey(42));
1242                 assert_ne!(pubkey(42), pubkey(44));
1243                 assert_eq!(tlv_stream.paths, Some(&paths));
1244                 assert_eq!(tlv_stream.node_id, Some(&pubkey(42)));
1245         }
1246
1247         #[test]
1248         fn builds_offer_with_issuer() {
1249                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1250                         .issuer("bar".into())
1251                         .build()
1252                         .unwrap();
1253                 assert_eq!(offer.issuer(), Some(PrintableString("bar")));
1254                 assert_eq!(offer.as_tlv_stream().issuer, Some(&String::from("bar")));
1255
1256                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1257                         .issuer("bar".into())
1258                         .issuer("baz".into())
1259                         .build()
1260                         .unwrap();
1261                 assert_eq!(offer.issuer(), Some(PrintableString("baz")));
1262                 assert_eq!(offer.as_tlv_stream().issuer, Some(&String::from("baz")));
1263         }
1264
1265         #[test]
1266         fn builds_offer_with_supported_quantity() {
1267                 let one = NonZeroU64::new(1).unwrap();
1268                 let ten = NonZeroU64::new(10).unwrap();
1269
1270                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1271                         .supported_quantity(Quantity::One)
1272                         .build()
1273                         .unwrap();
1274                 let tlv_stream = offer.as_tlv_stream();
1275                 assert_eq!(offer.supported_quantity(), Quantity::One);
1276                 assert_eq!(tlv_stream.quantity_max, None);
1277
1278                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1279                         .supported_quantity(Quantity::Unbounded)
1280                         .build()
1281                         .unwrap();
1282                 let tlv_stream = offer.as_tlv_stream();
1283                 assert_eq!(offer.supported_quantity(), Quantity::Unbounded);
1284                 assert_eq!(tlv_stream.quantity_max, Some(0));
1285
1286                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1287                         .supported_quantity(Quantity::Bounded(ten))
1288                         .build()
1289                         .unwrap();
1290                 let tlv_stream = offer.as_tlv_stream();
1291                 assert_eq!(offer.supported_quantity(), Quantity::Bounded(ten));
1292                 assert_eq!(tlv_stream.quantity_max, Some(10));
1293
1294                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1295                         .supported_quantity(Quantity::Bounded(one))
1296                         .build()
1297                         .unwrap();
1298                 let tlv_stream = offer.as_tlv_stream();
1299                 assert_eq!(offer.supported_quantity(), Quantity::Bounded(one));
1300                 assert_eq!(tlv_stream.quantity_max, Some(1));
1301
1302                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1303                         .supported_quantity(Quantity::Bounded(ten))
1304                         .supported_quantity(Quantity::One)
1305                         .build()
1306                         .unwrap();
1307                 let tlv_stream = offer.as_tlv_stream();
1308                 assert_eq!(offer.supported_quantity(), Quantity::One);
1309                 assert_eq!(tlv_stream.quantity_max, None);
1310         }
1311
1312         #[test]
1313         fn fails_requesting_invoice_with_unknown_required_features() {
1314                 match OfferBuilder::new("foo".into(), pubkey(42))
1315                         .features_unchecked(OfferFeatures::unknown())
1316                         .build().unwrap()
1317                         .request_invoice(vec![1; 32], pubkey(43))
1318                 {
1319                         Ok(_) => panic!("expected error"),
1320                         Err(e) => assert_eq!(e, Bolt12SemanticError::UnknownRequiredFeatures),
1321                 }
1322         }
1323
1324         #[test]
1325         fn parses_offer_with_chains() {
1326                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1327                         .chain(Network::Bitcoin)
1328                         .chain(Network::Testnet)
1329                         .build()
1330                         .unwrap();
1331                 if let Err(e) = offer.to_string().parse::<Offer>() {
1332                         panic!("error parsing offer: {:?}", e);
1333                 }
1334         }
1335
1336         #[test]
1337         fn parses_offer_with_amount() {
1338                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1339                         .amount(Amount::Bitcoin { amount_msats: 1000 })
1340                         .build()
1341                         .unwrap();
1342                 if let Err(e) = offer.to_string().parse::<Offer>() {
1343                         panic!("error parsing offer: {:?}", e);
1344                 }
1345
1346                 let mut tlv_stream = offer.as_tlv_stream();
1347                 tlv_stream.amount = Some(1000);
1348                 tlv_stream.currency = Some(b"USD");
1349
1350                 let mut encoded_offer = Vec::new();
1351                 tlv_stream.write(&mut encoded_offer).unwrap();
1352
1353                 if let Err(e) = Offer::try_from(encoded_offer) {
1354                         panic!("error parsing offer: {:?}", e);
1355                 }
1356
1357                 let mut tlv_stream = offer.as_tlv_stream();
1358                 tlv_stream.amount = None;
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                 match Offer::try_from(encoded_offer) {
1365                         Ok(_) => panic!("expected error"),
1366                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)),
1367                 }
1368
1369                 let mut tlv_stream = offer.as_tlv_stream();
1370                 tlv_stream.amount = Some(MAX_VALUE_MSAT + 1);
1371                 tlv_stream.currency = None;
1372
1373                 let mut encoded_offer = Vec::new();
1374                 tlv_stream.write(&mut encoded_offer).unwrap();
1375
1376                 match Offer::try_from(encoded_offer) {
1377                         Ok(_) => panic!("expected error"),
1378                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)),
1379                 }
1380         }
1381
1382         #[test]
1383         fn parses_offer_with_description() {
1384                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1385                 if let Err(e) = offer.to_string().parse::<Offer>() {
1386                         panic!("error parsing offer: {:?}", e);
1387                 }
1388
1389                 let mut tlv_stream = offer.as_tlv_stream();
1390                 tlv_stream.description = None;
1391
1392                 let mut encoded_offer = Vec::new();
1393                 tlv_stream.write(&mut encoded_offer).unwrap();
1394
1395                 match Offer::try_from(encoded_offer) {
1396                         Ok(_) => panic!("expected error"),
1397                         Err(e) => {
1398                                 assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription));
1399                         },
1400                 }
1401         }
1402
1403         #[test]
1404         fn parses_offer_with_paths() {
1405                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1406                         .path(BlindedPath {
1407                                 introduction_node_id: pubkey(40),
1408                                 blinding_point: pubkey(41),
1409                                 blinded_hops: vec![
1410                                         BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] },
1411                                         BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] },
1412                                 ],
1413                         })
1414                         .path(BlindedPath {
1415                                 introduction_node_id: pubkey(40),
1416                                 blinding_point: pubkey(41),
1417                                 blinded_hops: vec![
1418                                         BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },
1419                                         BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] },
1420                                 ],
1421                         })
1422                         .build()
1423                         .unwrap();
1424                 if let Err(e) = offer.to_string().parse::<Offer>() {
1425                         panic!("error parsing offer: {:?}", e);
1426                 }
1427
1428                 let mut builder = OfferBuilder::new("foo".into(), pubkey(42));
1429                 builder.offer.paths = Some(vec![]);
1430
1431                 let offer = builder.build().unwrap();
1432                 if let Err(e) = offer.to_string().parse::<Offer>() {
1433                         panic!("error parsing offer: {:?}", e);
1434                 }
1435         }
1436
1437         #[test]
1438         fn parses_offer_with_quantity() {
1439                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1440                         .supported_quantity(Quantity::One)
1441                         .build()
1442                         .unwrap();
1443                 if let Err(e) = offer.to_string().parse::<Offer>() {
1444                         panic!("error parsing offer: {:?}", e);
1445                 }
1446
1447                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1448                         .supported_quantity(Quantity::Unbounded)
1449                         .build()
1450                         .unwrap();
1451                 if let Err(e) = offer.to_string().parse::<Offer>() {
1452                         panic!("error parsing offer: {:?}", e);
1453                 }
1454
1455                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1456                         .supported_quantity(Quantity::Bounded(NonZeroU64::new(10).unwrap()))
1457                         .build()
1458                         .unwrap();
1459                 if let Err(e) = offer.to_string().parse::<Offer>() {
1460                         panic!("error parsing offer: {:?}", e);
1461                 }
1462
1463                 let offer = OfferBuilder::new("foo".into(), pubkey(42))
1464                         .supported_quantity(Quantity::Bounded(NonZeroU64::new(1).unwrap()))
1465                         .build()
1466                         .unwrap();
1467                 if let Err(e) = offer.to_string().parse::<Offer>() {
1468                         panic!("error parsing offer: {:?}", e);
1469                 }
1470         }
1471
1472         #[test]
1473         fn parses_offer_with_node_id() {
1474                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1475                 if let Err(e) = offer.to_string().parse::<Offer>() {
1476                         panic!("error parsing offer: {:?}", e);
1477                 }
1478
1479                 let mut tlv_stream = offer.as_tlv_stream();
1480                 tlv_stream.node_id = None;
1481
1482                 let mut encoded_offer = Vec::new();
1483                 tlv_stream.write(&mut encoded_offer).unwrap();
1484
1485                 match Offer::try_from(encoded_offer) {
1486                         Ok(_) => panic!("expected error"),
1487                         Err(e) => {
1488                                 assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
1489                         },
1490                 }
1491         }
1492
1493         #[test]
1494         fn fails_parsing_offer_with_extra_tlv_records() {
1495                 let offer = OfferBuilder::new("foo".into(), pubkey(42)).build().unwrap();
1496
1497                 let mut encoded_offer = Vec::new();
1498                 offer.write(&mut encoded_offer).unwrap();
1499                 BigSize(80).write(&mut encoded_offer).unwrap();
1500                 BigSize(32).write(&mut encoded_offer).unwrap();
1501                 [42u8; 32].write(&mut encoded_offer).unwrap();
1502
1503                 match Offer::try_from(encoded_offer) {
1504                         Ok(_) => panic!("expected error"),
1505                         Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
1506                 }
1507         }
1508 }
1509
1510 #[cfg(test)]
1511 mod bech32_tests {
1512         use super::{Bolt12ParseError, Offer};
1513         use bitcoin::bech32;
1514         use crate::ln::msgs::DecodeError;
1515
1516         #[test]
1517         fn encodes_offer_as_bech32_without_checksum() {
1518                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg";
1519                 let offer = dbg!(encoded_offer.parse::<Offer>().unwrap());
1520                 let reencoded_offer = offer.to_string();
1521                 dbg!(reencoded_offer.parse::<Offer>().unwrap());
1522                 assert_eq!(reencoded_offer, encoded_offer);
1523         }
1524
1525         #[test]
1526         fn parses_bech32_encoded_offers() {
1527                 let offers = [
1528                         // BOLT 12 test vectors
1529                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1530                         "l+no1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1531                         "lno1pqps7sjqpgt+yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+5k7msjzfpy7nz5yqcn+ygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+5xvxg",
1532                         "lno1pqps7sjqpgt+ yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+  5k7msjzfpy7nz5yqcn+\nygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+\r\n 5xvxg",
1533                 ];
1534                 for encoded_offer in &offers {
1535                         if let Err(e) = encoded_offer.parse::<Offer>() {
1536                                 panic!("Invalid offer ({:?}): {}", e, encoded_offer);
1537                         }
1538                 }
1539         }
1540
1541         #[test]
1542         fn fails_parsing_bech32_encoded_offers_with_invalid_continuations() {
1543                 let offers = [
1544                         // BOLT 12 test vectors
1545                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+",
1546                         "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+ ",
1547                         "+lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1548                         "+ lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1549                         "ln++o1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg",
1550                 ];
1551                 for encoded_offer in &offers {
1552                         match encoded_offer.parse::<Offer>() {
1553                                 Ok(_) => panic!("Valid offer: {}", encoded_offer),
1554                                 Err(e) => assert_eq!(e, Bolt12ParseError::InvalidContinuation),
1555                         }
1556                 }
1557
1558         }
1559
1560         #[test]
1561         fn fails_parsing_bech32_encoded_offer_with_invalid_hrp() {
1562                 let encoded_offer = "lni1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg";
1563                 match encoded_offer.parse::<Offer>() {
1564                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1565                         Err(e) => assert_eq!(e, Bolt12ParseError::InvalidBech32Hrp),
1566                 }
1567         }
1568
1569         #[test]
1570         fn fails_parsing_bech32_encoded_offer_with_invalid_bech32_data() {
1571                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo";
1572                 match encoded_offer.parse::<Offer>() {
1573                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1574                         Err(e) => assert_eq!(e, Bolt12ParseError::Bech32(bech32::Error::InvalidChar('o'))),
1575                 }
1576         }
1577
1578         #[test]
1579         fn fails_parsing_bech32_encoded_offer_with_invalid_tlv_data() {
1580                 let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxgqqqqq";
1581                 match encoded_offer.parse::<Offer>() {
1582                         Ok(_) => panic!("Valid offer: {}", encoded_offer),
1583                         Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
1584                 }
1585         }
1586 }