2 #![deny(non_upper_case_globals)]
3 #![deny(non_camel_case_types)]
4 #![deny(non_snake_case)]
6 #![deny(broken_intra_doc_links)]
8 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
10 #![cfg_attr(feature = "strict", deny(warnings))]
11 #![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
13 //! This crate provides data structures to represent
14 //! [lightning BOLT11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md)
15 //! invoices and functions to create, encode and decode these. If you just want to use the standard
16 //! en-/decoding functionality this should get you started:
18 //! * For parsing use `str::parse::<Invoice>(&self)` (see the docs of `impl FromStr for Invoice`)
19 //! * For constructing invoices use the `InvoiceBuilder`
20 //! * For serializing invoices use the `Display`/`ToString` traits
22 #[cfg(not(any(feature = "std", feature = "no-std")))]
23 compile_error!("at least one of the `std` or `no-std` features must be enabled");
29 extern crate bitcoin_hashes;
30 #[macro_use] extern crate lightning;
31 extern crate num_traits;
32 extern crate secp256k1;
34 #[cfg(any(test, feature = "std"))]
37 #[cfg(feature = "std")]
38 use std::time::SystemTime;
41 use bitcoin_hashes::Hash;
42 use bitcoin_hashes::sha256;
43 use lightning::ln::PaymentSecret;
44 use lightning::ln::features::InvoiceFeatures;
45 #[cfg(any(doc, test))]
46 use lightning::routing::network_graph::RoutingFees;
47 use lightning::routing::router::RouteHint;
48 use lightning::util::invoice::construct_invoice_preimage;
50 use secp256k1::PublicKey;
51 use secp256k1::{Message, Secp256k1};
52 use secp256k1::ecdsa::RecoverableSignature;
54 use core::fmt::{Display, Formatter, self};
55 use core::iter::FilterMap;
56 use core::num::ParseIntError;
58 use core::slice::Iter;
59 use core::time::Duration;
67 #[cfg(feature = "hashbrown")]
68 extern crate hashbrown;
70 pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque, boxed::Box};
71 #[cfg(not(feature = "hashbrown"))]
72 pub use std::collections::{HashMap, HashSet, hash_map};
73 #[cfg(feature = "hashbrown")]
74 pub use self::hashbrown::{HashMap, HashSet, hash_map};
76 pub use alloc::string::ToString;
81 /// Sync compat for std/no_std
82 #[cfg(feature = "std")]
84 pub use ::std::sync::{Mutex, MutexGuard};
87 /// Sync compat for std/no_std
88 #[cfg(not(feature = "std"))]
91 /// Errors that indicate what is wrong with the invoice. They have some granularity for debug
92 /// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
93 #[allow(missing_docs)]
94 #[derive(PartialEq, Debug, Clone)]
96 Bech32Error(bech32::Error),
97 ParseAmountError(ParseIntError),
98 MalformedSignature(secp256k1::Error),
104 UnexpectedEndOfTaggedFields,
105 DescriptionDecodeError(str::Utf8Error),
107 IntegerOverflowError,
108 InvalidSegWitProgramLength,
109 InvalidPubKeyHashLength,
110 InvalidScriptHashLength,
112 InvalidSliceLength(String),
114 /// Not an error, but used internally to signal that a part of the invoice should be ignored
115 /// according to BOLT11
119 /// Indicates that something went wrong while parsing or validating the invoice. Parsing errors
120 /// should be mostly seen as opaque and are only there for debugging reasons. Semantic errors
121 /// like wrong signatures, missing fields etc. could mean that someone tampered with the invoice.
122 #[derive(PartialEq, Debug, Clone)]
123 pub enum ParseOrSemanticError {
124 /// The invoice couldn't be decoded
125 ParseError(ParseError),
127 /// The invoice could be decoded but violates the BOLT11 standard
128 SemanticError(::SemanticError),
131 /// The number of bits used to represent timestamps as defined in BOLT 11.
132 const TIMESTAMP_BITS: usize = 35;
134 /// The maximum timestamp as [`Duration::as_secs`] since the Unix epoch allowed by [`BOLT 11`].
136 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
137 pub const MAX_TIMESTAMP: u64 = (1 << TIMESTAMP_BITS) - 1;
139 /// Default expiry time as defined by [BOLT 11].
141 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
142 pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
144 /// Default minimum final CLTV expiry as defined by [BOLT 11].
146 /// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
147 /// provided in [`MIN_FINAL_CLTV_EXPIRY`].
149 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
150 /// [`MIN_FINAL_CLTV_EXPIRY`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY
151 pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
153 /// Builder for `Invoice`s. It's the most convenient and advised way to use this library. It ensures
154 /// that only a semantically and syntactically correct Invoice can be built using it.
157 /// extern crate secp256k1;
158 /// extern crate lightning;
159 /// extern crate lightning_invoice;
160 /// extern crate bitcoin_hashes;
162 /// use bitcoin_hashes::Hash;
163 /// use bitcoin_hashes::sha256;
165 /// use secp256k1::Secp256k1;
166 /// use secp256k1::SecretKey;
168 /// use lightning::ln::PaymentSecret;
170 /// use lightning_invoice::{Currency, InvoiceBuilder};
172 /// # #[cfg(not(feature = "std"))]
174 /// # #[cfg(feature = "std")]
176 /// let private_key = SecretKey::from_slice(
178 /// 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f,
179 /// 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04,
180 /// 0xa8, 0xca, 0x3b, 0x2d, 0xb7, 0x34
184 /// let payment_hash = sha256::Hash::from_slice(&[0; 32][..]).unwrap();
185 /// let payment_secret = PaymentSecret([42u8; 32]);
187 /// let invoice = InvoiceBuilder::new(Currency::Bitcoin)
188 /// .description("Coins pls!".into())
189 /// .payment_hash(payment_hash)
190 /// .payment_secret(payment_secret)
191 /// .current_timestamp()
192 /// .min_final_cltv_expiry(144)
193 /// .build_signed(|hash| {
194 /// Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
198 /// assert!(invoice.to_string().starts_with("lnbc1"));
202 /// # Type parameters
203 /// The two parameters `D` and `H` signal if the builder already contains the correct amount of the
205 /// * `D`: exactly one `Description` or `DescriptionHash`
206 /// * `H`: exactly one `PaymentHash`
207 /// * `T`: the timestamp is set
209 /// (C-not exported) as we likely need to manually select one set of boolean type parameters.
210 #[derive(Eq, PartialEq, Debug, Clone)]
211 pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> {
214 si_prefix: Option<SiPrefix>,
215 timestamp: Option<PositiveTimestamp>,
216 tagged_fields: Vec<TaggedField>,
217 error: Option<CreationError>,
219 phantom_d: core::marker::PhantomData<D>,
220 phantom_h: core::marker::PhantomData<H>,
221 phantom_t: core::marker::PhantomData<T>,
222 phantom_c: core::marker::PhantomData<C>,
223 phantom_s: core::marker::PhantomData<S>,
226 /// Represents a syntactically and semantically correct lightning BOLT11 invoice.
228 /// There are three ways to construct an `Invoice`:
229 /// 1. using `InvoiceBuilder`
230 /// 2. using `Invoice::from_signed(SignedRawInvoice)`
231 /// 3. using `str::parse::<Invoice>(&str)`
232 #[derive(Eq, PartialEq, Debug, Clone)]
234 signed_invoice: SignedRawInvoice,
237 /// Represents the description of an invoice which has to be either a directly included string or
238 /// a hash of a description provided out of band.
240 /// (C-not exported) As we don't have a good way to map the reference lifetimes making this
241 /// practically impossible to use safely in languages like C.
242 #[derive(Eq, PartialEq, Debug, Clone)]
243 pub enum InvoiceDescription<'f> {
244 /// Reference to the directly supplied description in the invoice
245 Direct(&'f Description),
247 /// Reference to the description's hash included in the invoice
251 /// Represents a signed `RawInvoice` with cached hash. The signature is not checked and may be
255 /// The hash has to be either from the deserialized invoice or from the serialized `raw_invoice`.
256 #[derive(Eq, PartialEq, Debug, Clone)]
257 pub struct SignedRawInvoice {
258 /// The rawInvoice that the signature belongs to
259 raw_invoice: RawInvoice,
261 /// Hash of the `RawInvoice` that will be used to check the signature.
263 /// * if the `SignedRawInvoice` was deserialized the hash is of from the original encoded form,
264 /// since it's not guaranteed that encoding it again will lead to the same result since integers
265 /// could have been encoded with leading zeroes etc.
266 /// * if the `SignedRawInvoice` was constructed manually the hash will be the calculated hash
267 /// from the `RawInvoice`
270 /// signature of the payment request
271 signature: InvoiceSignature,
274 /// Represents an syntactically correct Invoice for a payment on the lightning network,
275 /// but without the signature information.
276 /// De- and encoding should not lead to information loss but may lead to different hashes.
278 /// For methods without docs see the corresponding methods in `Invoice`.
279 #[derive(Eq, PartialEq, Debug, Clone)]
280 pub struct RawInvoice {
281 /// human readable part
285 pub data: RawDataPart,
288 /// Data of the `RawInvoice` that is encoded in the human readable part
290 /// (C-not exported) As we don't yet support Option<Enum>
291 #[derive(Eq, PartialEq, Debug, Clone)]
293 /// The currency deferred from the 3rd and 4th character of the bech32 transaction
294 pub currency: Currency,
296 /// The amount that, multiplied by the SI prefix, has to be payed
297 pub raw_amount: Option<u64>,
299 /// SI prefix that gets multiplied with the `raw_amount`
300 pub si_prefix: Option<SiPrefix>,
303 /// Data of the `RawInvoice` that is encoded in the data part
304 #[derive(Eq, PartialEq, Debug, Clone)]
305 pub struct RawDataPart {
306 /// generation time of the invoice
307 pub timestamp: PositiveTimestamp,
309 /// tagged fields of the payment request
310 pub tagged_fields: Vec<RawTaggedField>,
313 /// A timestamp that refers to a date after 1 January 1970.
317 /// The Unix timestamp representing the stored time has to be positive and no greater than
318 /// [`MAX_TIMESTAMP`].
319 #[derive(Eq, PartialEq, Debug, Clone)]
320 pub struct PositiveTimestamp(Duration);
322 /// SI prefixes for the human readable part
323 #[derive(Eq, PartialEq, Debug, Clone, Copy)]
336 /// Returns the multiplier to go from a BTC value to picoBTC implied by this SiPrefix.
337 /// This is effectively 10^12 * the prefix multiplier
338 pub fn multiplier(&self) -> u64 {
340 SiPrefix::Milli => 1_000_000_000,
341 SiPrefix::Micro => 1_000_000,
342 SiPrefix::Nano => 1_000,
347 /// Returns all enum variants of `SiPrefix` sorted in descending order of their associated
350 /// (C-not exported) As we don't yet support a slice of enums, and also because this function
351 /// isn't the most critical to expose.
352 pub fn values_desc() -> &'static [SiPrefix] {
354 static VALUES: [SiPrefix; 4] = [Milli, Micro, Nano, Pico];
359 /// Enum representing the crypto currencies (or networks) supported by this library
360 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
378 /// Tagged field which may have an unknown tag
380 /// (C-not exported) as we don't currently support TaggedField
381 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
382 pub enum RawTaggedField {
383 /// Parsed tagged field with known tag
384 KnownSemantics(TaggedField),
385 /// tagged field which was not parsed due to an unknown tag or undefined field semantics
386 UnknownSemantics(Vec<u5>),
389 /// Tagged field with known tag
391 /// For descriptions of the enum values please refer to the enclosed type's docs.
393 /// (C-not exported) As we don't yet support enum variants with the same name the struct contained
395 #[allow(missing_docs)]
396 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
397 pub enum TaggedField {
399 Description(Description),
400 PayeePubKey(PayeePubKey),
401 DescriptionHash(Sha256),
402 ExpiryTime(ExpiryTime),
403 MinFinalCltvExpiry(MinFinalCltvExpiry),
405 PrivateRoute(PrivateRoute),
406 PaymentSecret(PaymentSecret),
407 Features(InvoiceFeatures),
411 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
412 pub struct Sha256(/// (C-not exported) as the native hash types are not currently mapped
415 /// Description string
418 /// The description can be at most 639 __bytes__ long
419 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
420 pub struct Description(String);
423 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
424 pub struct PayeePubKey(pub PublicKey);
426 /// Positive duration that defines when (relatively to the timestamp) in the future the invoice
428 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
429 pub struct ExpiryTime(Duration);
431 /// `min_final_cltv_expiry` to use for the last HTLC in the route
432 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
433 pub struct MinFinalCltvExpiry(pub u64);
435 // TODO: better types instead onf byte arrays
436 /// Fallback address in case no LN payment is possible
437 #[allow(missing_docs)]
438 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
444 PubKeyHash([u8; 20]),
445 ScriptHash([u8; 20]),
448 /// Recoverable signature
449 #[derive(Clone, Debug, Eq, PartialEq)]
450 pub struct InvoiceSignature(pub RecoverableSignature);
452 /// Private routing information
455 /// The encoded route has to be <1024 5bit characters long (<=639 bytes or <=12 hops)
457 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
458 pub struct PrivateRoute(RouteHint);
460 /// Tag constants as specified in BOLT11
461 #[allow(missing_docs)]
463 pub const TAG_PAYMENT_HASH: u8 = 1;
464 pub const TAG_DESCRIPTION: u8 = 13;
465 pub const TAG_PAYEE_PUB_KEY: u8 = 19;
466 pub const TAG_DESCRIPTION_HASH: u8 = 23;
467 pub const TAG_EXPIRY_TIME: u8 = 6;
468 pub const TAG_MIN_FINAL_CLTV_EXPIRY: u8 = 24;
469 pub const TAG_FALLBACK: u8 = 9;
470 pub const TAG_PRIVATE_ROUTE: u8 = 3;
471 pub const TAG_PAYMENT_SECRET: u8 = 16;
472 pub const TAG_FEATURES: u8 = 5;
475 impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False, tb::False> {
476 /// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
477 /// `InvoiceBuilder::build(self)` becomes available.
478 pub fn new(currrency: Currency) -> Self {
484 tagged_fields: Vec::new(),
487 phantom_d: core::marker::PhantomData,
488 phantom_h: core::marker::PhantomData,
489 phantom_t: core::marker::PhantomData,
490 phantom_c: core::marker::PhantomData,
491 phantom_s: core::marker::PhantomData,
496 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, C, S> {
497 /// Helper function to set the completeness flags.
498 fn set_flags<DN: tb::Bool, HN: tb::Bool, TN: tb::Bool, CN: tb::Bool, SN: tb::Bool>(self) -> InvoiceBuilder<DN, HN, TN, CN, SN> {
499 InvoiceBuilder::<DN, HN, TN, CN, SN> {
500 currency: self.currency,
502 si_prefix: self.si_prefix,
503 timestamp: self.timestamp,
504 tagged_fields: self.tagged_fields,
507 phantom_d: core::marker::PhantomData,
508 phantom_h: core::marker::PhantomData,
509 phantom_t: core::marker::PhantomData,
510 phantom_c: core::marker::PhantomData,
511 phantom_s: core::marker::PhantomData,
515 /// Sets the amount in millisatoshis. The optimal SI prefix is chosen automatically.
516 pub fn amount_milli_satoshis(mut self, amount_msat: u64) -> Self {
517 let amount = amount_msat * 10; // Invoices are denominated in "pico BTC"
518 let biggest_possible_si_prefix = SiPrefix::values_desc()
520 .find(|prefix| amount % prefix.multiplier() == 0)
521 .expect("Pico should always match");
522 self.amount = Some(amount / biggest_possible_si_prefix.multiplier());
523 self.si_prefix = Some(*biggest_possible_si_prefix);
527 /// Sets the payee's public key.
528 pub fn payee_pub_key(mut self, pub_key: PublicKey) -> Self {
529 self.tagged_fields.push(TaggedField::PayeePubKey(PayeePubKey(pub_key)));
533 /// Sets the expiry time
534 pub fn expiry_time(mut self, expiry_time: Duration) -> Self {
535 self.tagged_fields.push(TaggedField::ExpiryTime(ExpiryTime::from_duration(expiry_time)));
539 /// Adds a fallback address.
540 pub fn fallback(mut self, fallback: Fallback) -> Self {
541 self.tagged_fields.push(TaggedField::Fallback(fallback));
545 /// Adds a private route.
546 pub fn private_route(mut self, hint: RouteHint) -> Self {
547 match PrivateRoute::new(hint) {
548 Ok(r) => self.tagged_fields.push(TaggedField::PrivateRoute(r)),
549 Err(e) => self.error = Some(e),
555 impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb::True, C, S> {
556 /// Builds a `RawInvoice` if no `CreationError` occurred while construction any of the fields.
557 pub fn build_raw(self) -> Result<RawInvoice, CreationError> {
559 // If an error occurred at any time before, return it now
560 if let Some(e) = self.error {
565 currency: self.currency,
566 raw_amount: self.amount,
567 si_prefix: self.si_prefix,
570 let timestamp = self.timestamp.expect("ensured to be Some(t) by type T");
572 let tagged_fields = self.tagged_fields.into_iter().map(|tf| {
573 RawTaggedField::KnownSemantics(tf)
574 }).collect::<Vec<_>>();
576 let data = RawDataPart {
577 timestamp: timestamp,
578 tagged_fields: tagged_fields,
588 impl<H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<tb::False, H, T, C, S> {
589 /// Set the description. This function is only available if no description (hash) was set.
590 pub fn description(mut self, description: String) -> InvoiceBuilder<tb::True, H, T, C, S> {
591 match Description::new(description) {
592 Ok(d) => self.tagged_fields.push(TaggedField::Description(d)),
593 Err(e) => self.error = Some(e),
598 /// Set the description hash. This function is only available if no description (hash) was set.
599 pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder<tb::True, H, T, C, S> {
600 self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash)));
605 impl<D: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, tb::False, T, C, S> {
606 /// Set the payment hash. This function is only available if no payment hash was set.
607 pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder<D, tb::True, T, C, S> {
608 self.tagged_fields.push(TaggedField::PaymentHash(Sha256(hash)));
613 impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb::False, C, S> {
614 /// Sets the timestamp to a specific [`SystemTime`].
615 #[cfg(feature = "std")]
616 pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder<D, H, tb::True, C, S> {
617 match PositiveTimestamp::from_system_time(time) {
618 Ok(t) => self.timestamp = Some(t),
619 Err(e) => self.error = Some(e),
625 /// Sets the timestamp to a duration since the Unix epoch.
626 pub fn duration_since_epoch(mut self, time: Duration) -> InvoiceBuilder<D, H, tb::True, C, S> {
627 match PositiveTimestamp::from_duration_since_epoch(time) {
628 Ok(t) => self.timestamp = Some(t),
629 Err(e) => self.error = Some(e),
635 /// Sets the timestamp to the current system time.
636 #[cfg(feature = "std")]
637 pub fn current_timestamp(mut self) -> InvoiceBuilder<D, H, tb::True, C, S> {
638 let now = PositiveTimestamp::from_system_time(SystemTime::now());
639 self.timestamp = Some(now.expect("for the foreseeable future this shouldn't happen"));
644 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, tb::False, S> {
645 /// Sets `min_final_cltv_expiry`.
646 pub fn min_final_cltv_expiry(mut self, min_final_cltv_expiry: u64) -> InvoiceBuilder<D, H, T, tb::True, S> {
647 self.tagged_fields.push(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry(min_final_cltv_expiry)));
652 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, T, C, tb::False> {
653 /// Sets the payment secret and relevant features.
654 pub fn payment_secret(mut self, payment_secret: PaymentSecret) -> InvoiceBuilder<D, H, T, C, tb::True> {
655 let mut features = InvoiceFeatures::empty();
656 features.set_variable_length_onion_required();
657 features.set_payment_secret_required();
658 self.tagged_fields.push(TaggedField::PaymentSecret(payment_secret));
659 self.tagged_fields.push(TaggedField::Features(features));
664 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool> InvoiceBuilder<D, H, T, C, tb::True> {
665 /// Sets the `basic_mpp` feature as optional.
666 pub fn basic_mpp(mut self) -> Self {
667 for field in self.tagged_fields.iter_mut() {
668 if let TaggedField::Features(f) = field {
669 f.set_basic_mpp_optional();
676 impl InvoiceBuilder<tb::True, tb::True, tb::True, tb::True, tb::True> {
677 /// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
678 /// and MUST produce a recoverable signature valid for the given hash and if applicable also for
679 /// the included payee public key.
680 pub fn build_signed<F>(self, sign_function: F) -> Result<Invoice, CreationError>
681 where F: FnOnce(&Message) -> RecoverableSignature
683 let invoice = self.try_build_signed::<_, ()>(|hash| {
684 Ok(sign_function(hash))
689 Err(SignOrCreationError::CreationError(e)) => Err(e),
690 Err(SignOrCreationError::SignError(())) => unreachable!(),
694 /// Builds and signs an invoice using the supplied `sign_function`. This function MAY fail with
695 /// an error of type `E` and MUST produce a recoverable signature valid for the given hash and
696 /// if applicable also for the included payee public key.
697 pub fn try_build_signed<F, E>(self, sign_function: F) -> Result<Invoice, SignOrCreationError<E>>
698 where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
700 let raw = match self.build_raw() {
702 Err(e) => return Err(SignOrCreationError::CreationError(e)),
705 let signed = match raw.sign(sign_function) {
707 Err(e) => return Err(SignOrCreationError::SignError(e)),
710 let invoice = Invoice {
711 signed_invoice: signed,
714 invoice.check_field_counts().expect("should be ensured by type signature of builder");
715 invoice.check_feature_bits().expect("should be ensured by type signature of builder");
716 invoice.check_amount().expect("should be ensured by type signature of builder");
723 impl SignedRawInvoice {
724 /// Disassembles the `SignedRawInvoice` into its three parts:
726 /// 2. hash of the raw invoice
728 pub fn into_parts(self) -> (RawInvoice, [u8; 32], InvoiceSignature) {
729 (self.raw_invoice, self.hash, self.signature)
732 /// The `RawInvoice` which was signed.
733 pub fn raw_invoice(&self) -> &RawInvoice {
737 /// The hash of the `RawInvoice` that was signed.
738 pub fn hash(&self) -> &[u8; 32] {
742 /// InvoiceSignature for the invoice.
743 pub fn signature(&self) -> &InvoiceSignature {
747 /// Recovers the public key used for signing the invoice from the recoverable signature.
748 pub fn recover_payee_pub_key(&self) -> Result<PayeePubKey, secp256k1::Error> {
749 let hash = Message::from_slice(&self.hash[..])
750 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
752 Ok(PayeePubKey(Secp256k1::new().recover_ecdsa(
758 /// Checks if the signature is valid for the included payee public key or if none exists if it's
759 /// valid for the recovered signature (which should always be true?).
760 pub fn check_signature(&self) -> bool {
761 let included_pub_key = self.raw_invoice.payee_pub_key();
763 let mut recovered_pub_key = Option::None;
764 if recovered_pub_key.is_none() {
765 let recovered = match self.recover_payee_pub_key() {
767 Err(_) => return false,
769 recovered_pub_key = Some(recovered);
772 let pub_key = included_pub_key.or_else(|| recovered_pub_key.as_ref())
773 .expect("One is always present");
775 let hash = Message::from_slice(&self.hash[..])
776 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
778 let secp_context = Secp256k1::new();
779 let verification_result = secp_context.verify_ecdsa(
781 &self.signature.to_standard(),
785 match verification_result {
792 /// Finds the first element of an enum stream of a given variant and extracts one member of the
793 /// variant. If no element was found `None` gets returned.
795 /// The following example would extract the first B.
804 /// let elements = vec![A(1), A(2), B(3), A(4)]
806 /// assert_eq!(find_extract!(elements.iter(), Enum::B(ref x), x), Some(3u16))
808 macro_rules! find_extract {
809 ($iter:expr, $enm:pat, $enm_var:ident) => {
810 find_all_extract!($iter, $enm, $enm_var).next()
814 /// Finds the all elements of an enum stream of a given variant and extracts one member of the
815 /// variant through an iterator.
817 /// The following example would extract all A.
826 /// let elements = vec![A(1), A(2), B(3), A(4)]
829 /// find_all_extract!(elements.iter(), Enum::A(ref x), x).collect::<Vec<u8>>(),
830 /// vec![1u8, 2u8, 4u8])
832 macro_rules! find_all_extract {
833 ($iter:expr, $enm:pat, $enm_var:ident) => {
834 $iter.filter_map(|tf| match *tf {
835 $enm => Some($enm_var),
841 #[allow(missing_docs)]
843 /// Hash the HRP as bytes and signatureless data part.
844 fn hash_from_parts(hrp_bytes: &[u8], data_without_signature: &[u5]) -> [u8; 32] {
845 let preimage = construct_invoice_preimage(hrp_bytes, data_without_signature);
846 let mut hash: [u8; 32] = Default::default();
847 hash.copy_from_slice(&sha256::Hash::hash(&preimage)[..]);
851 /// Calculate the hash of the encoded `RawInvoice`
852 pub fn hash(&self) -> [u8; 32] {
853 use bech32::ToBase32;
855 RawInvoice::hash_from_parts(
856 self.hrp.to_string().as_bytes(),
857 &self.data.to_base32()
861 /// Signs the invoice using the supplied `sign_function`. This function MAY fail with an error
862 /// of type `E`. Since the signature of a `SignedRawInvoice` is not required to be valid there
863 /// are no constraints regarding the validity of the produced signature.
865 /// (C-not exported) As we don't currently support passing function pointers into methods
867 pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
868 where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
870 let raw_hash = self.hash();
871 let hash = Message::from_slice(&raw_hash[..])
872 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
873 let signature = sign_method(&hash)?;
875 Ok(SignedRawInvoice {
878 signature: InvoiceSignature(signature),
882 /// Returns an iterator over all tagged fields with known semantics.
884 /// (C-not exported) As there is not yet a manual mapping for a FilterMap
885 pub fn known_tagged_fields(&self)
886 -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>>
888 // For 1.14.0 compatibility: closures' types can't be written an fn()->() in the
889 // function's type signature.
890 // TODO: refactor once impl Trait is available
891 fn match_raw(raw: &RawTaggedField) -> Option<&TaggedField> {
893 RawTaggedField::KnownSemantics(ref tf) => Some(tf),
898 self.data.tagged_fields.iter().filter_map(match_raw )
901 pub fn payment_hash(&self) -> Option<&Sha256> {
902 find_extract!(self.known_tagged_fields(), TaggedField::PaymentHash(ref x), x)
905 pub fn description(&self) -> Option<&Description> {
906 find_extract!(self.known_tagged_fields(), TaggedField::Description(ref x), x)
909 pub fn payee_pub_key(&self) -> Option<&PayeePubKey> {
910 find_extract!(self.known_tagged_fields(), TaggedField::PayeePubKey(ref x), x)
913 pub fn description_hash(&self) -> Option<&Sha256> {
914 find_extract!(self.known_tagged_fields(), TaggedField::DescriptionHash(ref x), x)
917 pub fn expiry_time(&self) -> Option<&ExpiryTime> {
918 find_extract!(self.known_tagged_fields(), TaggedField::ExpiryTime(ref x), x)
921 pub fn min_final_cltv_expiry(&self) -> Option<&MinFinalCltvExpiry> {
922 find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiry(ref x), x)
925 pub fn payment_secret(&self) -> Option<&PaymentSecret> {
926 find_extract!(self.known_tagged_fields(), TaggedField::PaymentSecret(ref x), x)
929 pub fn features(&self) -> Option<&InvoiceFeatures> {
930 find_extract!(self.known_tagged_fields(), TaggedField::Features(ref x), x)
933 /// (C-not exported) as we don't support Vec<&NonOpaqueType>
934 pub fn fallbacks(&self) -> Vec<&Fallback> {
935 find_all_extract!(self.known_tagged_fields(), TaggedField::Fallback(ref x), x).collect()
938 pub fn private_routes(&self) -> Vec<&PrivateRoute> {
939 find_all_extract!(self.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x).collect()
942 pub fn amount_pico_btc(&self) -> Option<u64> {
943 self.hrp.raw_amount.map(|v| {
944 v * self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| { si.multiplier() })
948 pub fn currency(&self) -> Currency {
949 self.hrp.currency.clone()
953 impl PositiveTimestamp {
954 /// Creates a `PositiveTimestamp` from a Unix timestamp in the range `0..=MAX_TIMESTAMP`.
956 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
957 pub fn from_unix_timestamp(unix_seconds: u64) -> Result<Self, CreationError> {
958 Self::from_duration_since_epoch(Duration::from_secs(unix_seconds))
961 /// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding Unix timestamp in
962 /// the range `0..=MAX_TIMESTAMP`.
964 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
965 #[cfg(feature = "std")]
966 pub fn from_system_time(time: SystemTime) -> Result<Self, CreationError> {
967 time.duration_since(SystemTime::UNIX_EPOCH)
968 .map(Self::from_duration_since_epoch)
969 .unwrap_or(Err(CreationError::TimestampOutOfBounds))
972 /// Creates a `PositiveTimestamp` from a [`Duration`] since the Unix epoch in the range
973 /// `0..=MAX_TIMESTAMP`.
975 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
976 pub fn from_duration_since_epoch(duration: Duration) -> Result<Self, CreationError> {
977 if duration.as_secs() <= MAX_TIMESTAMP {
978 Ok(PositiveTimestamp(duration))
980 Err(CreationError::TimestampOutOfBounds)
984 /// Returns the Unix timestamp representing the stored time
985 pub fn as_unix_timestamp(&self) -> u64 {
989 /// Returns the duration of the stored time since the Unix epoch
990 pub fn as_duration_since_epoch(&self) -> Duration {
994 /// Returns the [`SystemTime`] representing the stored time
995 #[cfg(feature = "std")]
996 pub fn as_time(&self) -> SystemTime {
997 SystemTime::UNIX_EPOCH + self.0
1001 #[cfg(feature = "std")]
1002 impl Into<SystemTime> for PositiveTimestamp {
1003 fn into(self) -> SystemTime {
1004 SystemTime::UNIX_EPOCH + self.0
1009 /// Transform the `Invoice` into it's unchecked version
1010 pub fn into_signed_raw(self) -> SignedRawInvoice {
1014 /// Check that all mandatory fields are present
1015 fn check_field_counts(&self) -> Result<(), SemanticError> {
1016 // "A writer MUST include exactly one p field […]."
1017 let payment_hash_cnt = self.tagged_fields().filter(|&tf| match *tf {
1018 TaggedField::PaymentHash(_) => true,
1021 if payment_hash_cnt < 1 {
1022 return Err(SemanticError::NoPaymentHash);
1023 } else if payment_hash_cnt > 1 {
1024 return Err(SemanticError::MultiplePaymentHashes);
1027 // "A writer MUST include either exactly one d or exactly one h field."
1028 let description_cnt = self.tagged_fields().filter(|&tf| match *tf {
1029 TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true,
1032 if description_cnt < 1 {
1033 return Err(SemanticError::NoDescription);
1034 } else if description_cnt > 1 {
1035 return Err(SemanticError::MultipleDescriptions);
1038 self.check_payment_secret()?;
1043 /// Checks that there is exactly one payment secret field
1044 fn check_payment_secret(&self) -> Result<(), SemanticError> {
1045 // "A writer MUST include exactly one `s` field."
1046 let payment_secret_count = self.tagged_fields().filter(|&tf| match *tf {
1047 TaggedField::PaymentSecret(_) => true,
1050 if payment_secret_count < 1 {
1051 return Err(SemanticError::NoPaymentSecret);
1052 } else if payment_secret_count > 1 {
1053 return Err(SemanticError::MultiplePaymentSecrets);
1059 /// Check that amount is a whole number of millisatoshis
1060 fn check_amount(&self) -> Result<(), SemanticError> {
1061 if let Some(amount_pico_btc) = self.amount_pico_btc() {
1062 if amount_pico_btc % 10 != 0 {
1063 return Err(SemanticError::ImpreciseAmount);
1069 /// Check that feature bits are set as required
1070 fn check_feature_bits(&self) -> Result<(), SemanticError> {
1071 self.check_payment_secret()?;
1073 // "A writer MUST set an s field if and only if the payment_secret feature is set."
1074 // (this requirement has been since removed, and we now require the payment secret
1075 // feature bit always).
1076 let features = self.tagged_fields().find(|&tf| match *tf {
1077 TaggedField::Features(_) => true,
1081 None => Err(SemanticError::InvalidFeatures),
1082 Some(TaggedField::Features(features)) => {
1083 if features.requires_unknown_bits() {
1084 Err(SemanticError::InvalidFeatures)
1085 } else if !features.supports_payment_secret() {
1086 Err(SemanticError::InvalidFeatures)
1091 Some(_) => unreachable!(),
1095 /// Check that the invoice is signed correctly and that key recovery works
1096 pub fn check_signature(&self) -> Result<(), SemanticError> {
1097 match self.signed_invoice.recover_payee_pub_key() {
1098 Err(secp256k1::Error::InvalidRecoveryId) =>
1099 return Err(SemanticError::InvalidRecoveryId),
1100 Err(secp256k1::Error::InvalidSignature) =>
1101 return Err(SemanticError::InvalidSignature),
1102 Err(e) => panic!("no other error may occur, got {:?}", e),
1106 if !self.signed_invoice.check_signature() {
1107 return Err(SemanticError::InvalidSignature);
1113 /// Constructs an `Invoice` from a `SignedRawInvoice` by checking all its invariants.
1115 /// use lightning_invoice::*;
1117 /// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
1118 /// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
1119 /// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
1120 /// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
1121 /// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
1122 /// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
1123 /// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
1124 /// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
1125 /// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
1126 /// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
1127 /// j5r6drg6k6zcqj0fcwg";
1129 /// let signed = invoice.parse::<SignedRawInvoice>().unwrap();
1131 /// assert!(Invoice::from_signed(signed).is_ok());
1133 pub fn from_signed(signed_invoice: SignedRawInvoice) -> Result<Self, SemanticError> {
1134 let invoice = Invoice {
1135 signed_invoice: signed_invoice,
1137 invoice.check_field_counts()?;
1138 invoice.check_feature_bits()?;
1139 invoice.check_signature()?;
1140 invoice.check_amount()?;
1145 /// Returns the `Invoice`'s timestamp (should equal its creation time)
1146 #[cfg(feature = "std")]
1147 pub fn timestamp(&self) -> SystemTime {
1148 self.signed_invoice.raw_invoice().data.timestamp.as_time()
1151 /// Returns the `Invoice`'s timestamp as a duration since the Unix epoch
1152 pub fn duration_since_epoch(&self) -> Duration {
1153 self.signed_invoice.raw_invoice().data.timestamp.0
1156 /// Returns an iterator over all tagged fields of this Invoice.
1158 /// (C-not exported) As there is not yet a manual mapping for a FilterMap
1159 pub fn tagged_fields(&self)
1160 -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
1161 self.signed_invoice.raw_invoice().known_tagged_fields()
1164 /// Returns the hash to which we will receive the preimage on completion of the payment
1165 pub fn payment_hash(&self) -> &sha256::Hash {
1166 &self.signed_invoice.payment_hash().expect("checked by constructor").0
1169 /// Return the description or a hash of it for longer ones
1171 /// (C-not exported) because we don't yet export InvoiceDescription
1172 pub fn description(&self) -> InvoiceDescription {
1173 if let Some(ref direct) = self.signed_invoice.description() {
1174 return InvoiceDescription::Direct(direct);
1175 } else if let Some(ref hash) = self.signed_invoice.description_hash() {
1176 return InvoiceDescription::Hash(hash);
1178 unreachable!("ensured by constructor");
1181 /// Get the payee's public key if one was included in the invoice
1182 pub fn payee_pub_key(&self) -> Option<&PublicKey> {
1183 self.signed_invoice.payee_pub_key().map(|x| &x.0)
1186 /// Get the payment secret if one was included in the invoice
1187 pub fn payment_secret(&self) -> &PaymentSecret {
1188 self.signed_invoice.payment_secret().expect("was checked by constructor")
1191 /// Get the invoice features if they were included in the invoice
1192 pub fn features(&self) -> Option<&InvoiceFeatures> {
1193 self.signed_invoice.features()
1196 /// Recover the payee's public key (only to be used if none was included in the invoice)
1197 pub fn recover_payee_pub_key(&self) -> PublicKey {
1198 self.signed_invoice.recover_payee_pub_key().expect("was checked by constructor").0
1201 /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`].
1202 pub fn expiry_time(&self) -> Duration {
1203 self.signed_invoice.expiry_time()
1205 .unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
1208 /// Returns whether the invoice has expired.
1209 #[cfg(feature = "std")]
1210 pub fn is_expired(&self) -> bool {
1211 Self::is_expired_from_epoch(&self.timestamp(), self.expiry_time())
1214 /// Returns whether the expiry time from the given epoch has passed.
1215 #[cfg(feature = "std")]
1216 pub(crate) fn is_expired_from_epoch(epoch: &SystemTime, expiry_time: Duration) -> bool {
1217 match epoch.elapsed() {
1218 Ok(elapsed) => elapsed > expiry_time,
1223 /// Returns whether the expiry time would pass at the given point in time.
1224 /// `at_time` is the timestamp as a duration since the Unix epoch.
1225 pub fn would_expire(&self, at_time: Duration) -> bool {
1226 self.duration_since_epoch()
1227 .checked_add(self.expiry_time())
1228 .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time
1231 /// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
1232 /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
1233 pub fn min_final_cltv_expiry(&self) -> u64 {
1234 self.signed_invoice.min_final_cltv_expiry()
1236 .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY)
1239 /// Returns a list of all fallback addresses
1241 /// (C-not exported) as we don't support Vec<&NonOpaqueType>
1242 pub fn fallbacks(&self) -> Vec<&Fallback> {
1243 self.signed_invoice.fallbacks()
1246 /// Returns a list of all routes included in the invoice
1247 pub fn private_routes(&self) -> Vec<&PrivateRoute> {
1248 self.signed_invoice.private_routes()
1251 /// Returns a list of all routes included in the invoice as the underlying hints
1252 pub fn route_hints(&self) -> Vec<RouteHint> {
1254 self.signed_invoice.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x
1255 ).map(|route| (**route).clone()).collect()
1258 /// Returns the currency for which the invoice was issued
1259 pub fn currency(&self) -> Currency {
1260 self.signed_invoice.currency()
1263 /// Returns the amount if specified in the invoice as millisatoshis.
1264 pub fn amount_milli_satoshis(&self) -> Option<u64> {
1265 self.signed_invoice.amount_pico_btc().map(|v| v / 10)
1268 /// Returns the amount if specified in the invoice as pico <currency>.
1269 fn amount_pico_btc(&self) -> Option<u64> {
1270 self.signed_invoice.amount_pico_btc()
1274 impl From<TaggedField> for RawTaggedField {
1275 fn from(tf: TaggedField) -> Self {
1276 RawTaggedField::KnownSemantics(tf)
1281 /// Numeric representation of the field's tag
1282 pub fn tag(&self) -> u5 {
1283 let tag = match *self {
1284 TaggedField::PaymentHash(_) => constants::TAG_PAYMENT_HASH,
1285 TaggedField::Description(_) => constants::TAG_DESCRIPTION,
1286 TaggedField::PayeePubKey(_) => constants::TAG_PAYEE_PUB_KEY,
1287 TaggedField::DescriptionHash(_) => constants::TAG_DESCRIPTION_HASH,
1288 TaggedField::ExpiryTime(_) => constants::TAG_EXPIRY_TIME,
1289 TaggedField::MinFinalCltvExpiry(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY,
1290 TaggedField::Fallback(_) => constants::TAG_FALLBACK,
1291 TaggedField::PrivateRoute(_) => constants::TAG_PRIVATE_ROUTE,
1292 TaggedField::PaymentSecret(_) => constants::TAG_PAYMENT_SECRET,
1293 TaggedField::Features(_) => constants::TAG_FEATURES,
1296 u5::try_from_u8(tag).expect("all tags defined are <32")
1302 /// Creates a new `Description` if `description` is at most 1023 __bytes__ long,
1303 /// returns `CreationError::DescriptionTooLong` otherwise
1305 /// Please note that single characters may use more than one byte due to UTF8 encoding.
1306 pub fn new(description: String) -> Result<Description, CreationError> {
1307 if description.len() > 639 {
1308 Err(CreationError::DescriptionTooLong)
1310 Ok(Description(description))
1314 /// Returns the underlying description `String`
1315 pub fn into_inner(self) -> String {
1320 impl Into<String> for Description {
1321 fn into(self) -> String {
1326 impl Deref for Description {
1329 fn deref(&self) -> &str {
1334 impl From<PublicKey> for PayeePubKey {
1335 fn from(pk: PublicKey) -> Self {
1340 impl Deref for PayeePubKey {
1341 type Target = PublicKey;
1343 fn deref(&self) -> &PublicKey {
1349 /// Construct an `ExpiryTime` from seconds.
1350 pub fn from_seconds(seconds: u64) -> ExpiryTime {
1351 ExpiryTime(Duration::from_secs(seconds))
1354 /// Construct an `ExpiryTime` from a `Duration`.
1355 pub fn from_duration(duration: Duration) -> ExpiryTime {
1356 ExpiryTime(duration)
1359 /// Returns the expiry time in seconds
1360 pub fn as_seconds(&self) -> u64 {
1364 /// Returns a reference to the underlying `Duration` (=expiry time)
1365 pub fn as_duration(&self) -> &Duration {
1371 /// Creates a new (partial) route from a list of hops
1372 pub fn new(hops: RouteHint) -> Result<PrivateRoute, CreationError> {
1373 if hops.0.len() <= 12 {
1374 Ok(PrivateRoute(hops))
1376 Err(CreationError::RouteTooLong)
1380 /// Returns the underlying list of hops
1381 pub fn into_inner(self) -> RouteHint {
1386 impl Into<RouteHint> for PrivateRoute {
1387 fn into(self) -> RouteHint {
1392 impl Deref for PrivateRoute {
1393 type Target = RouteHint;
1395 fn deref(&self) -> &RouteHint {
1400 impl Deref for InvoiceSignature {
1401 type Target = RecoverableSignature;
1403 fn deref(&self) -> &RecoverableSignature {
1408 impl Deref for SignedRawInvoice {
1409 type Target = RawInvoice;
1411 fn deref(&self) -> &RawInvoice {
1416 /// Errors that may occur when constructing a new `RawInvoice` or `Invoice`
1417 #[derive(Eq, PartialEq, Debug, Clone)]
1418 pub enum CreationError {
1419 /// The supplied description string was longer than 639 __bytes__ (see [`Description::new(…)`](./struct.Description.html#method.new))
1422 /// The specified route has too many hops and can't be encoded
1425 /// The Unix timestamp of the supplied date is less than zero or greater than 35-bits
1426 TimestampOutOfBounds,
1428 /// The supplied millisatoshi amount was greater than the total bitcoin supply.
1431 /// Route hints were required for this invoice and were missing. Applies to
1432 /// [phantom invoices].
1434 /// [phantom invoices]: crate::utils::create_phantom_invoice
1438 impl Display for CreationError {
1439 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1441 CreationError::DescriptionTooLong => f.write_str("The supplied description string was longer than 639 bytes"),
1442 CreationError::RouteTooLong => f.write_str("The specified route has too many hops and can't be encoded"),
1443 CreationError::TimestampOutOfBounds => f.write_str("The Unix timestamp of the supplied date is less than zero or greater than 35-bits"),
1444 CreationError::InvalidAmount => f.write_str("The supplied millisatoshi amount was greater than the total bitcoin supply"),
1445 CreationError::MissingRouteHints => f.write_str("The invoice required route hints and they weren't provided"),
1450 #[cfg(feature = "std")]
1451 impl std::error::Error for CreationError { }
1453 /// Errors that may occur when converting a `RawInvoice` to an `Invoice`. They relate to the
1454 /// requirements sections in BOLT #11
1455 #[derive(Eq, PartialEq, Debug, Clone)]
1456 pub enum SemanticError {
1457 /// The invoice is missing the mandatory payment hash
1460 /// The invoice has multiple payment hashes which isn't allowed
1461 MultiplePaymentHashes,
1463 /// No description or description hash are part of the invoice
1466 /// The invoice contains multiple descriptions and/or description hashes which isn't allowed
1467 MultipleDescriptions,
1469 /// The invoice is missing the mandatory payment secret, which all modern lightning nodes
1473 /// The invoice contains multiple payment secrets
1474 MultiplePaymentSecrets,
1476 /// The invoice's features are invalid
1479 /// The recovery id doesn't fit the signature/pub key
1482 /// The invoice's signature is invalid
1485 /// The invoice's amount was not a whole number of millisatoshis
1489 impl Display for SemanticError {
1490 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1492 SemanticError::NoPaymentHash => f.write_str("The invoice is missing the mandatory payment hash"),
1493 SemanticError::MultiplePaymentHashes => f.write_str("The invoice has multiple payment hashes which isn't allowed"),
1494 SemanticError::NoDescription => f.write_str("No description or description hash are part of the invoice"),
1495 SemanticError::MultipleDescriptions => f.write_str("The invoice contains multiple descriptions and/or description hashes which isn't allowed"),
1496 SemanticError::NoPaymentSecret => f.write_str("The invoice is missing the mandatory payment secret"),
1497 SemanticError::MultiplePaymentSecrets => f.write_str("The invoice contains multiple payment secrets"),
1498 SemanticError::InvalidFeatures => f.write_str("The invoice's features are invalid"),
1499 SemanticError::InvalidRecoveryId => f.write_str("The recovery id doesn't fit the signature/pub key"),
1500 SemanticError::InvalidSignature => f.write_str("The invoice's signature is invalid"),
1501 SemanticError::ImpreciseAmount => f.write_str("The invoice's amount was not a whole number of millisatoshis"),
1506 #[cfg(feature = "std")]
1507 impl std::error::Error for SemanticError { }
1509 /// When signing using a fallible method either an user-supplied `SignError` or a `CreationError`
1511 #[derive(Eq, PartialEq, Debug, Clone)]
1512 pub enum SignOrCreationError<S = ()> {
1513 /// An error occurred during signing
1516 /// An error occurred while building the transaction
1517 CreationError(CreationError),
1520 impl<S> Display for SignOrCreationError<S> {
1521 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1523 SignOrCreationError::SignError(_) => f.write_str("An error occurred during signing"),
1524 SignOrCreationError::CreationError(err) => err.fmt(f),
1531 use bitcoin_hashes::hex::FromHex;
1532 use bitcoin_hashes::sha256;
1535 fn test_system_time_bounds_assumptions() {
1537 ::PositiveTimestamp::from_unix_timestamp(::MAX_TIMESTAMP + 1),
1538 Err(::CreationError::TimestampOutOfBounds)
1543 fn test_calc_invoice_hash() {
1544 use ::{RawInvoice, RawHrp, RawDataPart, Currency, PositiveTimestamp};
1545 use ::TaggedField::*;
1547 let invoice = RawInvoice {
1549 currency: Currency::Bitcoin,
1554 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1555 tagged_fields: vec![
1556 PaymentHash(::Sha256(sha256::Hash::from_hex(
1557 "0001020304050607080900010203040506070809000102030405060708090102"
1558 ).unwrap())).into(),
1559 Description(::Description::new(
1560 "Please consider supporting this project".to_owned()
1566 let expected_hash = [
1567 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d,
1568 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec,
1569 0xd5, 0x18, 0xe1, 0xc9
1572 assert_eq!(invoice.hash(), expected_hash)
1576 fn test_check_signature() {
1578 use secp256k1::Secp256k1;
1579 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
1580 use secp256k1::{SecretKey, PublicKey};
1581 use {SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
1584 let invoice = SignedRawInvoice {
1585 raw_invoice: RawInvoice {
1587 currency: Currency::Bitcoin,
1592 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1593 tagged_fields: vec ! [
1594 PaymentHash(Sha256(sha256::Hash::from_hex(
1595 "0001020304050607080900010203040506070809000102030405060708090102"
1596 ).unwrap())).into(),
1599 "Please consider supporting this project".to_owned()
1606 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27,
1607 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7,
1608 0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9
1610 signature: InvoiceSignature(RecoverableSignature::from_compact(
1612 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
1613 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
1614 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f,
1615 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad,
1616 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9,
1617 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f
1619 RecoveryId::from_i32(0).unwrap()
1623 assert!(invoice.check_signature());
1625 let private_key = SecretKey::from_slice(
1627 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2,
1628 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca,
1629 0x3b, 0x2d, 0xb7, 0x34
1632 let public_key = PublicKey::from_secret_key(&Secp256k1::new(), &private_key);
1634 assert_eq!(invoice.recover_payee_pub_key(), Ok(::PayeePubKey(public_key)));
1636 let (raw_invoice, _, _) = invoice.into_parts();
1637 let new_signed = raw_invoice.sign::<_, ()>(|hash| {
1638 Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))
1641 assert!(new_signed.check_signature());
1645 fn test_check_feature_bits() {
1647 use lightning::ln::features::InvoiceFeatures;
1648 use secp256k1::Secp256k1;
1649 use secp256k1::SecretKey;
1650 use {RawInvoice, RawHrp, RawDataPart, Currency, Sha256, PositiveTimestamp, Invoice,
1653 let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
1654 let payment_secret = lightning::ln::PaymentSecret([21; 32]);
1655 let invoice_template = RawInvoice {
1657 currency: Currency::Bitcoin,
1662 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1663 tagged_fields: vec ! [
1664 PaymentHash(Sha256(sha256::Hash::from_hex(
1665 "0001020304050607080900010203040506070809000102030405060708090102"
1666 ).unwrap())).into(),
1669 "Please consider supporting this project".to_owned()
1678 let mut invoice = invoice_template.clone();
1679 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1680 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1682 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::InvalidFeatures));
1684 // Missing feature bits
1686 let mut invoice = invoice_template.clone();
1687 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1688 invoice.data.tagged_fields.push(Features(InvoiceFeatures::empty()).into());
1689 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1691 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::InvalidFeatures));
1693 // Including payment secret and feature bits
1695 let mut invoice = invoice_template.clone();
1696 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1697 invoice.data.tagged_fields.push(Features(InvoiceFeatures::known()).into());
1698 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1700 assert!(Invoice::from_signed(invoice).is_ok());
1702 // No payment secret or features
1704 let invoice = invoice_template.clone();
1705 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1707 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1709 // No payment secret or feature bits
1711 let mut invoice = invoice_template.clone();
1712 invoice.data.tagged_fields.push(Features(InvoiceFeatures::empty()).into());
1713 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1715 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1717 // Missing payment secret
1719 let mut invoice = invoice_template.clone();
1720 invoice.data.tagged_fields.push(Features(InvoiceFeatures::known()).into());
1721 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1723 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1725 // Multiple payment secrets
1727 let mut invoice = invoice_template.clone();
1728 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1729 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1730 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1732 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::MultiplePaymentSecrets));
1736 fn test_builder_amount() {
1739 let builder = InvoiceBuilder::new(Currency::Bitcoin)
1740 .description("Test".into())
1741 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1742 .duration_since_epoch(Duration::from_secs(1234567));
1744 let invoice = builder.clone()
1745 .amount_milli_satoshis(1500)
1749 assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Nano));
1750 assert_eq!(invoice.hrp.raw_amount, Some(15));
1753 let invoice = builder.clone()
1754 .amount_milli_satoshis(150)
1758 assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Pico));
1759 assert_eq!(invoice.hrp.raw_amount, Some(1500));
1763 fn test_builder_fail() {
1765 use lightning::routing::router::RouteHintHop;
1766 use std::iter::FromIterator;
1767 use secp256k1::PublicKey;
1769 let builder = InvoiceBuilder::new(Currency::Bitcoin)
1770 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1771 .duration_since_epoch(Duration::from_secs(1234567))
1772 .min_final_cltv_expiry(144);
1774 let too_long_string = String::from_iter(
1775 (0..1024).map(|_| '?')
1778 let long_desc_res = builder.clone()
1779 .description(too_long_string)
1781 assert_eq!(long_desc_res, Err(CreationError::DescriptionTooLong));
1783 let route_hop = RouteHintHop {
1784 src_node_id: PublicKey::from_slice(
1786 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4,
1787 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a,
1788 0x95, 0xc3, 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
1791 short_channel_id: 0,
1794 proportional_millionths: 0,
1796 cltv_expiry_delta: 0,
1797 htlc_minimum_msat: None,
1798 htlc_maximum_msat: None,
1800 let too_long_route = RouteHint(vec![route_hop; 13]);
1801 let long_route_res = builder.clone()
1802 .description("Test".into())
1803 .private_route(too_long_route)
1805 assert_eq!(long_route_res, Err(CreationError::RouteTooLong));
1807 let sign_error_res = builder.clone()
1808 .description("Test".into())
1809 .payment_secret(PaymentSecret([0; 32]))
1810 .try_build_signed(|_| {
1811 Err("ImaginaryError")
1813 assert_eq!(sign_error_res, Err(SignOrCreationError::SignError("ImaginaryError")));
1817 fn test_builder_ok() {
1819 use lightning::routing::router::RouteHintHop;
1820 use secp256k1::Secp256k1;
1821 use secp256k1::{SecretKey, PublicKey};
1822 use std::time::{UNIX_EPOCH, Duration};
1824 let secp_ctx = Secp256k1::new();
1826 let private_key = SecretKey::from_slice(
1828 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2,
1829 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca,
1830 0x3b, 0x2d, 0xb7, 0x34
1833 let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key);
1835 let route_1 = RouteHint(vec![
1837 src_node_id: public_key.clone(),
1838 short_channel_id: de::parse_int_be(&[123; 8], 256).expect("short chan ID slice too big?"),
1841 proportional_millionths: 1,
1843 cltv_expiry_delta: 145,
1844 htlc_minimum_msat: None,
1845 htlc_maximum_msat: None,
1848 src_node_id: public_key.clone(),
1849 short_channel_id: de::parse_int_be(&[42; 8], 256).expect("short chan ID slice too big?"),
1852 proportional_millionths: 2,
1854 cltv_expiry_delta: 146,
1855 htlc_minimum_msat: None,
1856 htlc_maximum_msat: None,
1860 let route_2 = RouteHint(vec![
1862 src_node_id: public_key.clone(),
1863 short_channel_id: 0,
1866 proportional_millionths: 3,
1868 cltv_expiry_delta: 147,
1869 htlc_minimum_msat: None,
1870 htlc_maximum_msat: None,
1873 src_node_id: public_key.clone(),
1874 short_channel_id: de::parse_int_be(&[1; 8], 256).expect("short chan ID slice too big?"),
1877 proportional_millionths: 4,
1879 cltv_expiry_delta: 148,
1880 htlc_minimum_msat: None,
1881 htlc_maximum_msat: None,
1885 let builder = InvoiceBuilder::new(Currency::BitcoinTestnet)
1886 .amount_milli_satoshis(123)
1887 .duration_since_epoch(Duration::from_secs(1234567))
1888 .payee_pub_key(public_key.clone())
1889 .expiry_time(Duration::from_secs(54321))
1890 .min_final_cltv_expiry(144)
1891 .fallback(Fallback::PubKeyHash([0;20]))
1892 .private_route(route_1.clone())
1893 .private_route(route_2.clone())
1894 .description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap())
1895 .payment_hash(sha256::Hash::from_slice(&[21;32][..]).unwrap())
1896 .payment_secret(PaymentSecret([42; 32]))
1899 let invoice = builder.clone().build_signed(|hash| {
1900 secp_ctx.sign_ecdsa_recoverable(hash, &private_key)
1903 assert!(invoice.check_signature().is_ok());
1904 assert_eq!(invoice.tagged_fields().count(), 10);
1906 assert_eq!(invoice.amount_milli_satoshis(), Some(123));
1907 assert_eq!(invoice.amount_pico_btc(), Some(1230));
1908 assert_eq!(invoice.currency(), Currency::BitcoinTestnet);
1909 #[cfg(feature = "std")]
1911 invoice.timestamp().duration_since(UNIX_EPOCH).unwrap().as_secs(),
1914 assert_eq!(invoice.payee_pub_key(), Some(&public_key));
1915 assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
1916 assert_eq!(invoice.min_final_cltv_expiry(), 144);
1917 assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash([0;20])]);
1918 assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]);
1920 invoice.description(),
1921 InvoiceDescription::Hash(&Sha256(sha256::Hash::from_slice(&[3;32][..]).unwrap()))
1923 assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21;32][..]).unwrap());
1924 assert_eq!(invoice.payment_secret(), &PaymentSecret([42; 32]));
1925 assert_eq!(invoice.features(), Some(&InvoiceFeatures::known()));
1927 let raw_invoice = builder.build_raw().unwrap();
1928 assert_eq!(raw_invoice, *invoice.into_signed_raw().raw_invoice())
1932 fn test_default_values() {
1934 use secp256k1::Secp256k1;
1935 use secp256k1::SecretKey;
1937 let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
1938 .description("Test".into())
1939 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1940 .payment_secret(PaymentSecret([0; 32]))
1941 .duration_since_epoch(Duration::from_secs(1234567))
1944 .sign::<_, ()>(|hash| {
1945 let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
1946 let secp_ctx = Secp256k1::new();
1947 Ok(secp_ctx.sign_ecdsa_recoverable(hash, &privkey))
1950 let invoice = Invoice::from_signed(signed_invoice).unwrap();
1952 assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
1953 assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
1954 assert!(!invoice.would_expire(Duration::from_secs(1234568)));
1958 fn test_expiration() {
1960 use secp256k1::Secp256k1;
1961 use secp256k1::SecretKey;
1963 let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
1964 .description("Test".into())
1965 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1966 .payment_secret(PaymentSecret([0; 32]))
1967 .duration_since_epoch(Duration::from_secs(1234567))
1970 .sign::<_, ()>(|hash| {
1971 let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
1972 let secp_ctx = Secp256k1::new();
1973 Ok(secp_ctx.sign_ecdsa_recoverable(hash, &privkey))
1976 let invoice = Invoice::from_signed(signed_invoice).unwrap();
1978 assert!(invoice.would_expire(Duration::from_secs(1234567 + DEFAULT_EXPIRY_TIME + 1)));