]> git.bitcoin.ninja Git - rust-lightning/blob - lightning/src/offers/invoice.rs
8264aa15fb31da48d9a280dc1d2f293423ba74a7
[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::network::constants::Network;
14 use bitcoin::secp256k1::PublicKey;
15 use bitcoin::secp256k1::schnorr::Signature;
16 use bitcoin::util::address::{Address, Payload, WitnessVersion};
17 use core::convert::TryFrom;
18 use core::time::Duration;
19 use crate::io;
20 use crate::ln::PaymentHash;
21 use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
22 use crate::ln::msgs::DecodeError;
23 use crate::offers::invoice_request::{InvoiceRequestContents, InvoiceRequestTlvStream};
24 use crate::offers::merkle::{SignatureTlvStream, self};
25 use crate::offers::offer::OfferTlvStream;
26 use crate::offers::parse::{ParseError, ParsedMessage, SemanticError};
27 use crate::offers::payer::PayerTlvStream;
28 use crate::offers::refund::RefundContents;
29 use crate::onion_message::BlindedPath;
30 use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer};
31
32 use crate::prelude::*;
33
34 #[cfg(feature = "std")]
35 use std::time::SystemTime;
36
37 const DEFAULT_RELATIVE_EXPIRY: Duration = Duration::from_secs(7200);
38
39 const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", "signature");
40
41 /// An `Invoice` is a payment request, typically corresponding to an [`Offer`] or a [`Refund`].
42 ///
43 /// An invoice may be sent in response to an [`InvoiceRequest`] in the case of an offer or sent
44 /// directly after scanning a refund. It includes all the information needed to pay a recipient.
45 ///
46 /// [`Offer`]: crate::offers::offer::Offer
47 /// [`Refund`]: crate::offers::refund::Refund
48 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
49 pub struct Invoice {
50         bytes: Vec<u8>,
51         contents: InvoiceContents,
52         signature: Signature,
53 }
54
55 /// The contents of an [`Invoice`] for responding to either an [`Offer`] or a [`Refund`].
56 ///
57 /// [`Offer`]: crate::offers::offer::Offer
58 /// [`Refund`]: crate::offers::refund::Refund
59 enum InvoiceContents {
60         /// Contents for an [`Invoice`] corresponding to an [`Offer`].
61         ///
62         /// [`Offer`]: crate::offers::offer::Offer
63         ForOffer {
64                 invoice_request: InvoiceRequestContents,
65                 fields: InvoiceFields,
66         },
67         /// Contents for an [`Invoice`] corresponding to a [`Refund`].
68         ///
69         /// [`Refund`]: crate::offers::refund::Refund
70         ForRefund {
71                 refund: RefundContents,
72                 fields: InvoiceFields,
73         },
74 }
75
76 /// Invoice-specific fields for an `invoice` message.
77 struct InvoiceFields {
78         payment_paths: Vec<(BlindedPath, BlindedPayInfo)>,
79         created_at: Duration,
80         relative_expiry: Option<Duration>,
81         payment_hash: PaymentHash,
82         amount_msats: u64,
83         fallbacks: Option<Vec<FallbackAddress>>,
84         features: Bolt12InvoiceFeatures,
85         signing_pubkey: PublicKey,
86 }
87
88 impl Invoice {
89         /// Paths to the recipient originating from publicly reachable nodes, including information
90         /// needed for routing payments across them. Blinded paths provide recipient privacy by
91         /// obfuscating its node id.
92         pub fn payment_paths(&self) -> &[(BlindedPath, BlindedPayInfo)] {
93                 &self.contents.fields().payment_paths[..]
94         }
95
96         /// Duration since the Unix epoch when the invoice was created.
97         pub fn created_at(&self) -> Duration {
98                 self.contents.fields().created_at
99         }
100
101         /// Duration since [`Invoice::created_at`] when the invoice has expired and therefore should no
102         /// longer be paid.
103         pub fn relative_expiry(&self) -> Duration {
104                 self.contents.fields().relative_expiry.unwrap_or(DEFAULT_RELATIVE_EXPIRY)
105         }
106
107         /// Whether the invoice has expired.
108         #[cfg(feature = "std")]
109         pub fn is_expired(&self) -> bool {
110                 let absolute_expiry = self.created_at().checked_add(self.relative_expiry());
111                 match absolute_expiry {
112                         Some(seconds_from_epoch) => match SystemTime::UNIX_EPOCH.elapsed() {
113                                 Ok(elapsed) => elapsed > seconds_from_epoch,
114                                 Err(_) => false,
115                         },
116                         None => false,
117                 }
118         }
119
120         /// SHA256 hash of the payment preimage that will be given in return for paying the invoice.
121         pub fn payment_hash(&self) -> PaymentHash {
122                 self.contents.fields().payment_hash
123         }
124
125         /// The minimum amount required for a successful payment of the invoice.
126         pub fn amount_msats(&self) -> u64 {
127                 self.contents.fields().amount_msats
128         }
129
130         /// Fallback addresses for paying the invoice on-chain, in order of most-preferred to
131         /// least-preferred.
132         pub fn fallbacks(&self) -> Vec<Address> {
133                 let network = match self.network() {
134                         None => return Vec::new(),
135                         Some(network) => network,
136                 };
137
138                 let to_valid_address = |address: &FallbackAddress| {
139                         let version = match WitnessVersion::try_from(address.version) {
140                                 Ok(version) => version,
141                                 Err(_) => return None,
142                         };
143
144                         let program = &address.program;
145                         if program.len() < 2 || program.len() > 40 {
146                                 return None;
147                         }
148
149                         let address = Address {
150                                 payload: Payload::WitnessProgram {
151                                         version,
152                                         program: address.program.clone(),
153                                 },
154                                 network,
155                         };
156
157                         if !address.is_standard() && version == WitnessVersion::V0 {
158                                 return None;
159                         }
160
161                         Some(address)
162                 };
163
164                 self.contents.fields().fallbacks
165                         .as_ref()
166                         .map(|fallbacks| fallbacks.iter().filter_map(to_valid_address).collect())
167                         .unwrap_or_else(Vec::new)
168         }
169
170         fn network(&self) -> Option<Network> {
171                 let chain = self.contents.chain();
172                 if chain == ChainHash::using_genesis_block(Network::Bitcoin) {
173                         Some(Network::Bitcoin)
174                 } else if chain == ChainHash::using_genesis_block(Network::Testnet) {
175                         Some(Network::Testnet)
176                 } else if chain == ChainHash::using_genesis_block(Network::Signet) {
177                         Some(Network::Signet)
178                 } else if chain == ChainHash::using_genesis_block(Network::Regtest) {
179                         Some(Network::Regtest)
180                 } else {
181                         None
182                 }
183         }
184
185         /// Features pertaining to paying an invoice.
186         pub fn features(&self) -> &Bolt12InvoiceFeatures {
187                 &self.contents.fields().features
188         }
189
190         /// The public key used to sign invoices.
191         pub fn signing_pubkey(&self) -> PublicKey {
192                 self.contents.fields().signing_pubkey
193         }
194
195         /// Signature of the invoice using [`Invoice::signing_pubkey`].
196         pub fn signature(&self) -> Signature {
197                 self.signature
198         }
199 }
200
201 impl InvoiceContents {
202         fn chain(&self) -> ChainHash {
203                 match self {
204                         InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.chain(),
205                         InvoiceContents::ForRefund { refund, .. } => refund.chain(),
206                 }
207         }
208
209         fn fields(&self) -> &InvoiceFields {
210                 match self {
211                         InvoiceContents::ForOffer { fields, .. } => fields,
212                         InvoiceContents::ForRefund { fields, .. } => fields,
213                 }
214         }
215 }
216
217 impl Writeable for Invoice {
218         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
219                 WithoutLength(&self.bytes).write(writer)
220         }
221 }
222
223 impl TryFrom<Vec<u8>> for Invoice {
224         type Error = ParseError;
225
226         fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
227                 let parsed_invoice = ParsedMessage::<FullInvoiceTlvStream>::try_from(bytes)?;
228                 Invoice::try_from(parsed_invoice)
229         }
230 }
231
232 tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
233         (160, paths: (Vec<BlindedPath>, WithoutLength)),
234         (162, blindedpay: (Vec<BlindedPayInfo>, WithoutLength)),
235         (164, created_at: (u64, HighZeroBytesDroppedBigSize)),
236         (166, relative_expiry: (u32, HighZeroBytesDroppedBigSize)),
237         (168, payment_hash: PaymentHash),
238         (170, amount: (u64, HighZeroBytesDroppedBigSize)),
239         (172, fallbacks: (Vec<FallbackAddress>, WithoutLength)),
240         (174, features: (Bolt12InvoiceFeatures, WithoutLength)),
241         (176, node_id: PublicKey),
242 });
243
244 /// Information needed to route a payment across a [`BlindedPath`] hop.
245 #[derive(Debug, PartialEq)]
246 pub struct BlindedPayInfo {
247         fee_base_msat: u32,
248         fee_proportional_millionths: u32,
249         cltv_expiry_delta: u16,
250         htlc_minimum_msat: u64,
251         htlc_maximum_msat: u64,
252         features: BlindedHopFeatures,
253 }
254
255 impl_writeable!(BlindedPayInfo, {
256         fee_base_msat,
257         fee_proportional_millionths,
258         cltv_expiry_delta,
259         htlc_minimum_msat,
260         htlc_maximum_msat,
261         features
262 });
263
264 /// Wire representation for an on-chain fallback address.
265 #[derive(Debug, PartialEq)]
266 pub(super) struct FallbackAddress {
267         version: u8,
268         program: Vec<u8>,
269 }
270
271 impl_writeable!(FallbackAddress, { version, program });
272
273 type FullInvoiceTlvStream =
274         (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream, SignatureTlvStream);
275
276 impl SeekReadable for FullInvoiceTlvStream {
277         fn read<R: io::Read + io::Seek>(r: &mut R) -> Result<Self, DecodeError> {
278                 let payer = SeekReadable::read(r)?;
279                 let offer = SeekReadable::read(r)?;
280                 let invoice_request = SeekReadable::read(r)?;
281                 let invoice = SeekReadable::read(r)?;
282                 let signature = SeekReadable::read(r)?;
283
284                 Ok((payer, offer, invoice_request, invoice, signature))
285         }
286 }
287
288 type PartialInvoiceTlvStream =
289         (PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream);
290
291 impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Invoice {
292         type Error = ParseError;
293
294         fn try_from(invoice: ParsedMessage<FullInvoiceTlvStream>) -> Result<Self, Self::Error> {
295                 let ParsedMessage { bytes, tlv_stream } = invoice;
296                 let (
297                         payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
298                         SignatureTlvStream { signature },
299                 ) = tlv_stream;
300                 let contents = InvoiceContents::try_from(
301                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream)
302                 )?;
303
304                 let signature = match signature {
305                         None => return Err(ParseError::InvalidSemantics(SemanticError::MissingSignature)),
306                         Some(signature) => signature,
307                 };
308                 let pubkey = contents.fields().signing_pubkey;
309                 merkle::verify_signature(&signature, SIGNATURE_TAG, &bytes, pubkey)?;
310
311                 Ok(Invoice { bytes, contents, signature })
312         }
313 }
314
315 impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
316         type Error = SemanticError;
317
318         fn try_from(tlv_stream: PartialInvoiceTlvStream) -> Result<Self, Self::Error> {
319                 let (
320                         payer_tlv_stream,
321                         offer_tlv_stream,
322                         invoice_request_tlv_stream,
323                         InvoiceTlvStream {
324                                 paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks,
325                                 features, node_id,
326                         },
327                 ) = tlv_stream;
328
329                 let payment_paths = match (paths, blindedpay) {
330                         (None, _) => return Err(SemanticError::MissingPaths),
331                         (_, None) => return Err(SemanticError::InvalidPayInfo),
332                         (Some(paths), _) if paths.is_empty() => return Err(SemanticError::MissingPaths),
333                         (Some(paths), Some(blindedpay)) if paths.len() != blindedpay.len() => {
334                                 return Err(SemanticError::InvalidPayInfo);
335                         },
336                         (Some(paths), Some(blindedpay)) => {
337                                 paths.into_iter().zip(blindedpay.into_iter()).collect::<Vec<_>>()
338                         },
339                 };
340
341                 let created_at = match created_at {
342                         None => return Err(SemanticError::MissingCreationTime),
343                         Some(timestamp) => Duration::from_secs(timestamp),
344                 };
345
346                 let relative_expiry = relative_expiry
347                         .map(Into::<u64>::into)
348                         .map(Duration::from_secs);
349
350                 let payment_hash = match payment_hash {
351                         None => return Err(SemanticError::MissingPaymentHash),
352                         Some(payment_hash) => payment_hash,
353                 };
354
355                 let amount_msats = match amount {
356                         None => return Err(SemanticError::MissingAmount),
357                         Some(amount) => amount,
358                 };
359
360                 let features = features.unwrap_or_else(Bolt12InvoiceFeatures::empty);
361
362                 let signing_pubkey = match node_id {
363                         None => return Err(SemanticError::MissingSigningPubkey),
364                         Some(node_id) => node_id,
365                 };
366
367                 let fields = InvoiceFields {
368                         payment_paths, created_at, relative_expiry, payment_hash, amount_msats, fallbacks,
369                         features, signing_pubkey,
370                 };
371
372                 match offer_tlv_stream.node_id {
373                         Some(expected_signing_pubkey) => {
374                                 if fields.signing_pubkey != expected_signing_pubkey {
375                                         return Err(SemanticError::InvalidSigningPubkey);
376                                 }
377
378                                 let invoice_request = InvoiceRequestContents::try_from(
379                                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
380                                 )?;
381                                 Ok(InvoiceContents::ForOffer { invoice_request, fields })
382                         },
383                         None => {
384                                 let refund = RefundContents::try_from(
385                                         (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
386                                 )?;
387                                 Ok(InvoiceContents::ForRefund { refund, fields })
388                         },
389                 }
390         }
391 }