a937a5483c93cd48b55128b590998174807bad36
[rust-lightning] / lightning / src / offers / invoice.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Data structures and encoding for `invoice` messages.
11
12 use bitcoin::blockdata::constants::ChainHash;
13 use bitcoin::hash_types::{WPubkeyHash, WScriptHash};
14 use bitcoin::hashes::Hash;
15 use bitcoin::network::constants::Network;
16 use bitcoin::secp256k1::{Message, PublicKey};
17 use bitcoin::secp256k1::schnorr::Signature;
18 use bitcoin::util::address::{Address, Payload, WitnessVersion};
19 use bitcoin::util::schnorr::TweakedPublicKey;
20 use core::convert::TryFrom;
21 use core::time::Duration;
22 use crate::io;
23 use crate::ln::PaymentHash;
24 use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
25 use crate::ln::msgs::DecodeError;
26 use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef};
27 use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, WithoutSignatures, self};
28 use crate::offers::offer::{Amount, OfferTlvStream, OfferTlvStreamRef};
29 use crate::offers::parse::{ParseError, ParsedMessage, SemanticError};
30 use crate::offers::payer::{PayerTlvStream, PayerTlvStreamRef};
31 use crate::offers::refund::RefundContents;
32 use crate::onion_message::BlindedPath;
33 use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer};
34
35 use crate::prelude::*;
36
37 #[cfg(feature = "std")]
38 use std::time::SystemTime;
39
40 const DEFAULT_RELATIVE_EXPIRY: Duration = Duration::from_secs(7200);
41
42 const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", "signature");
43
44 /// Builds an [`Invoice`] from either:
45 /// - an [`InvoiceRequest`] for the "offer to be paid" flow or
46 /// - a [`Refund`] for the "offer for money" flow.
47 ///
48 /// See [module-level documentation] for usage.
49 ///
50 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
51 /// [`Refund`]: crate::offers::refund::Refund
52 /// [module-level documentation]: self
53 pub struct InvoiceBuilder<'a> {
54         invreq_bytes: &'a Vec<u8>,
55         invoice: InvoiceContents,
56 }
57
58 impl<'a> InvoiceBuilder<'a> {
59         pub(super) fn for_offer(
60                 invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>,
61                 created_at: Duration, payment_hash: PaymentHash
62         ) -> Result<Self, SemanticError> {
63                 if payment_paths.is_empty() {
64                         return Err(SemanticError::MissingPaths);
65                 }
66
67                 let amount_msats = match invoice_request.amount_msats() {
68                         Some(amount_msats) => amount_msats,
69                         None => match invoice_request.contents.offer.amount() {
70                                 Some(Amount::Bitcoin { amount_msats }) => {
71                                         amount_msats * invoice_request.quantity().unwrap_or(1)
72                                 },
73                                 Some(Amount::Currency { .. }) => return Err(SemanticError::UnsupportedCurrency),
74                                 None => return Err(SemanticError::MissingAmount),
75                         },
76                 };
77
78                 Ok(Self {
79                         invreq_bytes: &invoice_request.bytes,
80                         invoice: InvoiceContents::ForOffer {
81                                 invoice_request: invoice_request.contents.clone(),
82                                 fields: InvoiceFields {
83                                         payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats,
84                                         fallbacks: None, features: Bolt12InvoiceFeatures::empty(),
85                                         signing_pubkey: invoice_request.contents.offer.signing_pubkey(),
86                                 },
87                         },
88                 })
89         }
90
91         /// Sets the [`Invoice::relative_expiry`] as seconds since [`Invoice::created_at`]. Any expiry
92         /// that has already passed is valid and can be checked for using [`Invoice::is_expired`].
93         ///
94         /// Successive calls to this method will override the previous setting.
95         pub fn relative_expiry(mut self, relative_expiry_secs: u32) -> Self {
96                 let relative_expiry = Duration::from_secs(relative_expiry_secs as u64);
97                 self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
98                 self
99         }
100
101         /// Adds a P2WSH address to [`Invoice::fallbacks`].
102         ///
103         /// Successive calls to this method will add another address. Caller is responsible for not
104         /// adding duplicate addresses and only calling if capable of receiving to P2WSH addresses.
105         pub fn fallback_v0_p2wsh(mut self, script_hash: &WScriptHash) -> Self {
106                 let address = FallbackAddress {
107                         version: WitnessVersion::V0.to_num(),
108                         program: Vec::from(&script_hash.into_inner()[..]),
109                 };
110                 self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
111                 self
112         }
113
114         /// Adds a P2WPKH address to [`Invoice::fallbacks`].
115         ///
116         /// Successive calls to this method will add another address. Caller is responsible for not
117         /// adding duplicate addresses and only calling if capable of receiving to P2WPKH addresses.
118         pub fn fallback_v0_p2wpkh(mut self, pubkey_hash: &WPubkeyHash) -> Self {
119                 let address = FallbackAddress {
120                         version: WitnessVersion::V0.to_num(),
121                         program: Vec::from(&pubkey_hash.into_inner()[..]),
122                 };
123                 self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
124                 self
125         }
126
127         /// Adds a P2TR address to [`Invoice::fallbacks`].
128         ///
129         /// Successive calls to this method will add another address. Caller is responsible for not
130         /// adding duplicate addresses and only calling if capable of receiving to P2TR addresses.
131         pub fn fallback_v1_p2tr_tweaked(mut self, output_key: &TweakedPublicKey) -> Self {
132                 let address = FallbackAddress {
133                         version: WitnessVersion::V1.to_num(),
134                         program: Vec::from(&output_key.serialize()[..]),
135                 };
136                 self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
137                 self
138         }
139
140         /// Sets [`Invoice::features`] to indicate MPP may be used. Otherwise, MPP is disallowed.
141         pub fn allow_mpp(mut self) -> Self {
142                 self.invoice.fields_mut().features.set_basic_mpp_optional();
143                 self
144         }
145
146         /// Builds an unsigned [`Invoice`] after checking for valid semantics. It can be signed by
147         /// [`UnsignedInvoice::sign`].
148         pub fn build(self) -> Result<UnsignedInvoice<'a>, SemanticError> {
149                 #[cfg(feature = "std")] {
150                         if self.invoice.is_offer_or_refund_expired() {
151                                 return Err(SemanticError::AlreadyExpired);
152                         }
153                 }
154
155                 let InvoiceBuilder { invreq_bytes, invoice } = self;
156                 Ok(UnsignedInvoice { invreq_bytes, invoice })
157         }
158 }
159
160 /// A semantically valid [`Invoice`] that hasn't been signed.
161 pub struct UnsignedInvoice<'a> {
162         invreq_bytes: &'a Vec<u8>,
163         invoice: InvoiceContents,
164 }
165
166 impl<'a> UnsignedInvoice<'a> {
167         /// Signs the invoice using the given function.
168         pub fn sign<F, E>(self, sign: F) -> Result<Invoice, SignError<E>>
169         where
170                 F: FnOnce(&Message) -> Result<Signature, E>
171         {
172                 // Use the invoice_request bytes instead of the invoice_request TLV stream as the latter may
173                 // have contained unknown TLV records, which are not stored in `InvoiceRequestContents` or
174                 // `RefundContents`.
175                 let (_, _, _, invoice_tlv_stream) = self.invoice.as_tlv_stream();
176                 let invoice_request_bytes = WithoutSignatures(self.invreq_bytes);
177                 let unsigned_tlv_stream = (invoice_request_bytes, invoice_tlv_stream);
178
179                 let mut bytes = Vec::new();
180                 unsigned_tlv_stream.write(&mut bytes).unwrap();
181
182                 let pubkey = self.invoice.fields().signing_pubkey;
183                 let signature = merkle::sign_message(sign, SIGNATURE_TAG, &bytes, pubkey)?;
184
185                 // Append the signature TLV record to the bytes.
186                 let signature_tlv_stream = SignatureTlvStreamRef {
187                         signature: Some(&signature),
188                 };
189                 signature_tlv_stream.write(&mut bytes).unwrap();
190
191                 Ok(Invoice {
192                         bytes,
193                         contents: self.invoice,
194                         signature,
195                 })
196         }
197 }
198
199 /// An `Invoice` is a payment request, typically corresponding to an [`Offer`] or a [`Refund`].
200 ///
201 /// An invoice may be sent in response to an [`InvoiceRequest`] in the case of an offer or sent
202 /// directly after scanning a refund. It includes all the information needed to pay a recipient.
203 ///
204 /// [`Offer`]: crate::offers::offer::Offer
205 /// [`Refund`]: crate::offers::refund::Refund
206 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
207 pub struct Invoice {
208         bytes: Vec<u8>,
209         contents: InvoiceContents,
210         signature: Signature,
211 }
212
213 /// The contents of an [`Invoice`] for responding to either an [`Offer`] or a [`Refund`].
214 ///
215 /// [`Offer`]: crate::offers::offer::Offer
216 /// [`Refund`]: crate::offers::refund::Refund
217 enum InvoiceContents {
218         /// Contents for an [`Invoice`] corresponding to an [`Offer`].
219         ///
220         /// [`Offer`]: crate::offers::offer::Offer
221         ForOffer {
222                 invoice_request: InvoiceRequestContents,
223                 fields: InvoiceFields,
224         },
225         /// Contents for an [`Invoice`] corresponding to a [`Refund`].
226         ///
227         /// [`Refund`]: crate::offers::refund::Refund
228         ForRefund {
229                 refund: RefundContents,
230                 fields: InvoiceFields,
231         },
232 }
233
234 /// Invoice-specific fields for an `invoice` message.
235 struct InvoiceFields {
236         payment_paths: Vec<(BlindedPath, BlindedPayInfo)>,
237         created_at: Duration,
238         relative_expiry: Option<Duration>,
239         payment_hash: PaymentHash,
240         amount_msats: u64,
241         fallbacks: Option<Vec<FallbackAddress>>,
242         features: Bolt12InvoiceFeatures,
243         signing_pubkey: PublicKey,
244 }
245
246 impl Invoice {
247         /// Paths to the recipient originating from publicly reachable nodes, including information
248         /// needed for routing payments across them. Blinded paths provide recipient privacy by
249         /// obfuscating its node id.
250         pub fn payment_paths(&self) -> &[(BlindedPath, BlindedPayInfo)] {
251                 &self.contents.fields().payment_paths[..]
252         }
253
254         /// Duration since the Unix epoch when the invoice was created.
255         pub fn created_at(&self) -> Duration {
256                 self.contents.fields().created_at
257         }
258
259         /// Duration since [`Invoice::created_at`] when the invoice has expired and therefore should no
260         /// longer be paid.
261         pub fn relative_expiry(&self) -> Duration {
262                 self.contents.fields().relative_expiry.unwrap_or(DEFAULT_RELATIVE_EXPIRY)
263         }
264
265         /// Whether the invoice has expired.
266         #[cfg(feature = "std")]
267         pub fn is_expired(&self) -> bool {
268                 let absolute_expiry = self.created_at().checked_add(self.relative_expiry());
269                 match absolute_expiry {
270                         Some(seconds_from_epoch) => match SystemTime::UNIX_EPOCH.elapsed() {
271                                 Ok(elapsed) => elapsed > seconds_from_epoch,
272                                 Err(_) => false,
273                         },
274                         None => false,
275                 }
276         }
277
278         /// SHA256 hash of the payment preimage that will be given in return for paying the invoice.
279         pub fn payment_hash(&self) -> PaymentHash {
280                 self.contents.fields().payment_hash
281         }
282
283         /// The minimum amount required for a successful payment of the invoice.
284         pub fn amount_msats(&self) -> u64 {
285                 self.contents.fields().amount_msats
286         }
287
288         /// Fallback addresses for paying the invoice on-chain, in order of most-preferred to
289         /// least-preferred.
290         pub fn fallbacks(&self) -> Vec<Address> {
291                 let network = match self.network() {
292                         None => return Vec::new(),
293                         Some(network) => network,
294                 };
295
296                 let to_valid_address = |address: &FallbackAddress| {
297                         let version = match WitnessVersion::try_from(address.version) {
298                                 Ok(version) => version,
299                                 Err(_) => return None,
300                         };
301
302                         let program = &address.program;
303                         if program.len() < 2 || program.len() > 40 {
304                                 return None;
305                         }
306
307                         let address = Address {
308                                 payload: Payload::WitnessProgram {
309                                         version,
310                                         program: address.program.clone(),
311                                 },
312                                 network,
313                         };
314
315                         if !address.is_standard() && version == WitnessVersion::V0 {
316                                 return None;
317                         }
318
319                         Some(address)
320                 };
321
322                 self.contents.fields().fallbacks
323                         .as_ref()
324                         .map(|fallbacks| fallbacks.iter().filter_map(to_valid_address).collect())
325                         .unwrap_or_else(Vec::new)
326         }
327
328         fn network(&self) -> Option<Network> {
329                 let chain = self.contents.chain();
330                 if chain == ChainHash::using_genesis_block(Network::Bitcoin) {
331                         Some(Network::Bitcoin)
332                 } else if chain == ChainHash::using_genesis_block(Network::Testnet) {
333                         Some(Network::Testnet)
334                 } else if chain == ChainHash::using_genesis_block(Network::Signet) {
335                         Some(Network::Signet)
336                 } else if chain == ChainHash::using_genesis_block(Network::Regtest) {
337                         Some(Network::Regtest)
338                 } else {
339                         None
340                 }
341         }
342
343         /// Features pertaining to paying an invoice.
344         pub fn features(&self) -> &Bolt12InvoiceFeatures {
345                 &self.contents.fields().features
346         }
347
348         /// The public key used to sign invoices.
349         pub fn signing_pubkey(&self) -> PublicKey {
350                 self.contents.fields().signing_pubkey
351         }
352
353         /// Signature of the invoice using [`Invoice::signing_pubkey`].
354         pub fn signature(&self) -> Signature {
355                 self.signature
356         }
357 }
358
359 impl InvoiceContents {
360         /// Whether the original offer or refund has expired.
361         #[cfg(feature = "std")]
362         fn is_offer_or_refund_expired(&self) -> bool {
363                 match self {
364                         InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.offer.is_expired(),
365                         InvoiceContents::ForRefund { refund, .. } => refund.is_expired(),
366                 }
367         }
368
369         fn chain(&self) -> ChainHash {
370                 match self {
371                         InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.chain(),
372                         InvoiceContents::ForRefund { refund, .. } => refund.chain(),
373                 }
374         }
375
376         fn fields(&self) -> &InvoiceFields {
377                 match self {
378                         InvoiceContents::ForOffer { fields, .. } => fields,
379                         InvoiceContents::ForRefund { fields, .. } => fields,
380                 }
381         }
382
383         fn fields_mut(&mut self) -> &mut InvoiceFields {
384                 match self {
385                         InvoiceContents::ForOffer { fields, .. } => fields,
386                         InvoiceContents::ForRefund { fields, .. } => fields,
387                 }
388         }
389
390         fn as_tlv_stream(&self) -> PartialInvoiceTlvStreamRef {
391                 let (payer, offer, invoice_request) = match self {
392                         InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.as_tlv_stream(),
393                         InvoiceContents::ForRefund { refund, .. } => refund.as_tlv_stream(),
394                 };
395                 let invoice = self.fields().as_tlv_stream();
396
397                 (payer, offer, invoice_request, invoice)
398         }
399 }
400
401 impl InvoiceFields {
402         fn as_tlv_stream(&self) -> InvoiceTlvStreamRef {
403                 let features = {
404                         if self.features == Bolt12InvoiceFeatures::empty() { None }
405                         else { Some(&self.features) }
406                 };
407
408                 InvoiceTlvStreamRef {
409                         paths: Some(Iterable(self.payment_paths.iter().map(|(path, _)| path))),
410                         blindedpay: Some(Iterable(self.payment_paths.iter().map(|(_, payinfo)| payinfo))),
411                         created_at: Some(self.created_at.as_secs()),
412                         relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32),
413                         payment_hash: Some(&self.payment_hash),
414                         amount: Some(self.amount_msats),
415                         fallbacks: self.fallbacks.as_ref(),
416                         features,
417                         node_id: Some(&self.signing_pubkey),
418                 }
419         }
420 }
421
422 impl Writeable for Invoice {
423         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
424                 WithoutLength(&self.bytes).write(writer)
425         }
426 }
427
428 impl TryFrom<Vec<u8>> for Invoice {
429         type Error = ParseError;
430
431         fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
432                 let parsed_invoice = ParsedMessage::<FullInvoiceTlvStream>::try_from(bytes)?;
433                 Invoice::try_from(parsed_invoice)
434         }
435 }
436
437 tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
438         (160, paths: (Vec<BlindedPath>, WithoutLength, Iterable<'a, BlindedPathIter<'a>, BlindedPath>)),
439         (162, blindedpay: (Vec<BlindedPayInfo>, WithoutLength, Iterable<'a, BlindedPayInfoIter<'a>, BlindedPayInfo>)),
440         (164, created_at: (u64, HighZeroBytesDroppedBigSize)),
441         (166, relative_expiry: (u32, HighZeroBytesDroppedBigSize)),
442         (168, payment_hash: PaymentHash),
443         (170, amount: (u64, HighZeroBytesDroppedBigSize)),
444         (172, fallbacks: (Vec<FallbackAddress>, WithoutLength)),
445         (174, features: (Bolt12InvoiceFeatures, WithoutLength)),
446         (176, node_id: PublicKey),
447 });
448
449 type BlindedPathIter<'a> = core::iter::Map<
450         core::slice::Iter<'a, (BlindedPath, BlindedPayInfo)>,
451         for<'r> fn(&'r (BlindedPath, BlindedPayInfo)) -> &'r BlindedPath,
452 >;
453
454 type BlindedPayInfoIter<'a> = core::iter::Map<
455         core::slice::Iter<'a, (BlindedPath, BlindedPayInfo)>,
456         for<'r> fn(&'r (BlindedPath, BlindedPayInfo)) -> &'r BlindedPayInfo,
457 >;
458
459 /// Information needed to route a payment across a [`BlindedPath`].
460 #[derive(Debug, PartialEq)]
461 pub struct BlindedPayInfo {
462         fee_base_msat: u32,
463         fee_proportional_millionths: u32,
464         cltv_expiry_delta: u16,
465         htlc_minimum_msat: u64,
466         htlc_maximum_msat: u64,
467         features: BlindedHopFeatures,
468 }
469
470 impl_writeable!(BlindedPayInfo, {
471         fee_base_msat,
472         fee_proportional_millionths,
473         cltv_expiry_delta,
474         htlc_minimum_msat,
475         htlc_maximum_msat,
476         features
477 });
478
479 /// Wire representation for an on-chain fallback address.
480 #[derive(Debug, PartialEq)]
481 pub(super) struct FallbackAddress {
482         version: u8,
483         program: Vec<u8>,
484 }
485
486 impl_writeable!(FallbackAddress, { version, program });
487
488 type FullInvoiceTlvStream =
489         (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream, SignatureTlvStream);
490
491 impl SeekReadable for FullInvoiceTlvStream {
492         fn read<R: io::Read + io::Seek>(r: &mut R) -> Result<Self, DecodeError> {
493                 let payer = SeekReadable::read(r)?;
494                 let offer = SeekReadable::read(r)?;
495                 let invoice_request = SeekReadable::read(r)?;
496                 let invoice = SeekReadable::read(r)?;
497                 let signature = SeekReadable::read(r)?;
498
499                 Ok((payer, offer, invoice_request, invoice, signature))
500         }
501 }
502
503 type PartialInvoiceTlvStream =
504         (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream);
505
506 type PartialInvoiceTlvStreamRef<'a> = (
507         PayerTlvStreamRef<'a>,
508         OfferTlvStreamRef<'a>,
509         InvoiceRequestTlvStreamRef<'a>,
510         InvoiceTlvStreamRef<'a>,
511 );
512
513 impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Invoice {
514         type Error = ParseError;
515
516         fn try_from(invoice: ParsedMessage<FullInvoiceTlvStream>) -> Result<Self, Self::Error> {
517                 let ParsedMessage { bytes, tlv_stream } = invoice;
518                 let (
519                         payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
520                         SignatureTlvStream { signature },
521                 ) = tlv_stream;
522                 let contents = InvoiceContents::try_from(
523                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream)
524                 )?;
525
526                 let signature = match signature {
527                         None => return Err(ParseError::InvalidSemantics(SemanticError::MissingSignature)),
528                         Some(signature) => signature,
529                 };
530                 let pubkey = contents.fields().signing_pubkey;
531                 merkle::verify_signature(&signature, SIGNATURE_TAG, &bytes, pubkey)?;
532
533                 Ok(Invoice { bytes, contents, signature })
534         }
535 }
536
537 impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
538         type Error = SemanticError;
539
540         fn try_from(tlv_stream: PartialInvoiceTlvStream) -> Result<Self, Self::Error> {
541                 let (
542                         payer_tlv_stream,
543                         offer_tlv_stream,
544                         invoice_request_tlv_stream,
545                         InvoiceTlvStream {
546                                 paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks,
547                                 features, node_id,
548                         },
549                 ) = tlv_stream;
550
551                 let payment_paths = match (paths, blindedpay) {
552                         (None, _) => return Err(SemanticError::MissingPaths),
553                         (_, None) => return Err(SemanticError::InvalidPayInfo),
554                         (Some(paths), _) if paths.is_empty() => return Err(SemanticError::MissingPaths),
555                         (Some(paths), Some(blindedpay)) if paths.len() != blindedpay.len() => {
556                                 return Err(SemanticError::InvalidPayInfo);
557                         },
558                         (Some(paths), Some(blindedpay)) => {
559                                 paths.into_iter().zip(blindedpay.into_iter()).collect::<Vec<_>>()
560                         },
561                 };
562
563                 let created_at = match created_at {
564                         None => return Err(SemanticError::MissingCreationTime),
565                         Some(timestamp) => Duration::from_secs(timestamp),
566                 };
567
568                 let relative_expiry = relative_expiry
569                         .map(Into::<u64>::into)
570                         .map(Duration::from_secs);
571
572                 let payment_hash = match payment_hash {
573                         None => return Err(SemanticError::MissingPaymentHash),
574                         Some(payment_hash) => payment_hash,
575                 };
576
577                 let amount_msats = match amount {
578                         None => return Err(SemanticError::MissingAmount),
579                         Some(amount) => amount,
580                 };
581
582                 let features = features.unwrap_or_else(Bolt12InvoiceFeatures::empty);
583
584                 let signing_pubkey = match node_id {
585                         None => return Err(SemanticError::MissingSigningPubkey),
586                         Some(node_id) => node_id,
587                 };
588
589                 let fields = InvoiceFields {
590                         payment_paths, created_at, relative_expiry, payment_hash, amount_msats, fallbacks,
591                         features, signing_pubkey,
592                 };
593
594                 match offer_tlv_stream.node_id {
595                         Some(expected_signing_pubkey) => {
596                                 if fields.signing_pubkey != expected_signing_pubkey {
597                                         return Err(SemanticError::InvalidSigningPubkey);
598                                 }
599
600                                 let invoice_request = InvoiceRequestContents::try_from(
601                                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
602                                 )?;
603                                 Ok(InvoiceContents::ForOffer { invoice_request, fields })
604                         },
605                         None => {
606                                 let refund = RefundContents::try_from(
607                                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
608                                 )?;
609                                 Ok(InvoiceContents::ForRefund { refund, fields })
610                         },
611                 }
612         }
613 }