1 // Prefix these with `rustdoc::` when we update our MSRV to be >= 1.52 to remove warnings.
2 #![deny(broken_intra_doc_links)]
3 #![deny(private_intra_doc_links)]
6 #![deny(non_upper_case_globals)]
7 #![deny(non_camel_case_types)]
8 #![deny(non_snake_case)]
11 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
13 #![cfg_attr(feature = "strict", deny(warnings))]
14 #![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
16 //! This crate provides data structures to represent
17 //! [lightning BOLT11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md)
18 //! invoices and functions to create, encode and decode these. If you just want to use the standard
19 //! en-/decoding functionality this should get you started:
21 //! * For parsing use `str::parse::<Invoice>(&self)` (see [`Invoice::from_str`])
22 //! * For constructing invoices use the [`InvoiceBuilder`]
23 //! * For serializing invoices use the [`Display`]/[`ToString`] traits
25 //! [`Invoice::from_str`]: crate::Invoice#impl-FromStr
27 #[cfg(not(any(feature = "std", feature = "no-std")))]
28 compile_error!("at least one of the `std` or `no-std` features must be enabled");
33 pub(crate) mod time_utils;
36 extern crate bitcoin_hashes;
37 #[macro_use] extern crate lightning;
38 extern crate num_traits;
39 extern crate secp256k1;
41 #[cfg(any(test, feature = "std"))]
43 #[cfg(feature = "serde")]
46 #[cfg(feature = "std")]
47 use std::time::SystemTime;
50 use bitcoin::{Address, Network, PubkeyHash, ScriptHash};
51 use bitcoin::util::address::{Payload, WitnessVersion};
52 use bitcoin_hashes::{Hash, sha256};
53 use lightning::ln::PaymentSecret;
54 use lightning::ln::features::InvoiceFeatures;
55 #[cfg(any(doc, test))]
56 use lightning::routing::gossip::RoutingFees;
57 use lightning::routing::router::RouteHint;
58 use lightning::util::invoice::construct_invoice_preimage;
60 use secp256k1::PublicKey;
61 use secp256k1::{Message, Secp256k1};
62 use secp256k1::ecdsa::RecoverableSignature;
64 use core::fmt::{Display, Formatter, self};
65 use core::iter::FilterMap;
66 use core::num::ParseIntError;
68 use core::slice::Iter;
69 use core::time::Duration;
72 #[cfg(feature = "serde")]
73 use serde::{Deserialize, Deserializer,Serialize, Serializer, de::Error};
80 #[cfg(feature = "hashbrown")]
81 extern crate hashbrown;
83 pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque, boxed::Box};
84 #[cfg(not(feature = "hashbrown"))]
85 pub use std::collections::{HashMap, HashSet, hash_map};
86 #[cfg(feature = "hashbrown")]
87 pub use self::hashbrown::{HashMap, HashSet, hash_map};
89 pub use alloc::string::ToString;
92 use crate::prelude::*;
94 /// Sync compat for std/no_std
95 #[cfg(feature = "std")]
97 pub use ::std::sync::{Mutex, MutexGuard};
100 /// Sync compat for std/no_std
101 #[cfg(not(feature = "std"))]
104 /// Errors that indicate what is wrong with the invoice. They have some granularity for debug
105 /// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
106 #[allow(missing_docs)]
107 #[derive(PartialEq, Eq, Debug, Clone)]
108 pub enum ParseError {
109 Bech32Error(bech32::Error),
110 ParseAmountError(ParseIntError),
111 MalformedSignature(secp256k1::Error),
117 UnexpectedEndOfTaggedFields,
118 DescriptionDecodeError(str::Utf8Error),
120 IntegerOverflowError,
121 InvalidSegWitProgramLength,
122 InvalidPubKeyHashLength,
123 InvalidScriptHashLength,
125 InvalidSliceLength(String),
127 /// Not an error, but used internally to signal that a part of the invoice should be ignored
128 /// according to BOLT11
132 /// Indicates that something went wrong while parsing or validating the invoice. Parsing errors
133 /// should be mostly seen as opaque and are only there for debugging reasons. Semantic errors
134 /// like wrong signatures, missing fields etc. could mean that someone tampered with the invoice.
135 #[derive(PartialEq, Eq, Debug, Clone)]
136 pub enum ParseOrSemanticError {
137 /// The invoice couldn't be decoded
138 ParseError(ParseError),
140 /// The invoice could be decoded but violates the BOLT11 standard
141 SemanticError(crate::SemanticError),
144 /// The number of bits used to represent timestamps as defined in BOLT 11.
145 const TIMESTAMP_BITS: usize = 35;
147 /// The maximum timestamp as [`Duration::as_secs`] since the Unix epoch allowed by [`BOLT 11`].
149 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
150 pub const MAX_TIMESTAMP: u64 = (1 << TIMESTAMP_BITS) - 1;
152 /// Default expiry time as defined by [BOLT 11].
154 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
155 pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
157 /// Default minimum final CLTV expiry as defined by [BOLT 11].
159 /// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
160 /// provided in [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
162 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
163 /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
164 pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
166 /// Builder for [`Invoice`]s. It's the most convenient and advised way to use this library. It ensures
167 /// that only a semantically and syntactically correct Invoice can be built using it.
170 /// extern crate secp256k1;
171 /// extern crate lightning;
172 /// extern crate lightning_invoice;
173 /// extern crate bitcoin_hashes;
175 /// use bitcoin_hashes::Hash;
176 /// use bitcoin_hashes::sha256;
178 /// use secp256k1::Secp256k1;
179 /// use secp256k1::SecretKey;
181 /// use lightning::ln::PaymentSecret;
183 /// use lightning_invoice::{Currency, InvoiceBuilder};
185 /// # #[cfg(not(feature = "std"))]
187 /// # #[cfg(feature = "std")]
189 /// let private_key = SecretKey::from_slice(
191 /// 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f,
192 /// 0xe2, 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04,
193 /// 0xa8, 0xca, 0x3b, 0x2d, 0xb7, 0x34
197 /// let payment_hash = sha256::Hash::from_slice(&[0; 32][..]).unwrap();
198 /// let payment_secret = PaymentSecret([42u8; 32]);
200 /// let invoice = InvoiceBuilder::new(Currency::Bitcoin)
201 /// .description("Coins pls!".into())
202 /// .payment_hash(payment_hash)
203 /// .payment_secret(payment_secret)
204 /// .current_timestamp()
205 /// .min_final_cltv_expiry_delta(144)
206 /// .build_signed(|hash| {
207 /// Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
211 /// assert!(invoice.to_string().starts_with("lnbc1"));
215 /// # Type parameters
216 /// The two parameters `D` and `H` signal if the builder already contains the correct amount of the
218 /// * `D`: exactly one [`TaggedField::Description`] or [`TaggedField::DescriptionHash`]
219 /// * `H`: exactly one [`TaggedField::PaymentHash`]
220 /// * `T`: the timestamp is set
221 /// * `C`: the CLTV expiry is set
222 /// * `S`: the payment secret is set
223 /// * `M`: payment metadata is set
225 /// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters.
226 #[derive(Eq, PartialEq, Debug, Clone)]
227 pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> {
230 si_prefix: Option<SiPrefix>,
231 timestamp: Option<PositiveTimestamp>,
232 tagged_fields: Vec<TaggedField>,
233 error: Option<CreationError>,
235 phantom_d: core::marker::PhantomData<D>,
236 phantom_h: core::marker::PhantomData<H>,
237 phantom_t: core::marker::PhantomData<T>,
238 phantom_c: core::marker::PhantomData<C>,
239 phantom_s: core::marker::PhantomData<S>,
240 phantom_m: core::marker::PhantomData<M>,
243 /// Represents a syntactically and semantically correct lightning BOLT11 invoice.
245 /// There are three ways to construct an `Invoice`:
246 /// 1. using [`InvoiceBuilder`]
247 /// 2. using [`Invoice::from_signed`]
248 /// 3. using `str::parse::<Invoice>(&str)` (see [`Invoice::from_str`])
250 /// [`Invoice::from_str`]: crate::Invoice#impl-FromStr
251 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
253 signed_invoice: SignedRawInvoice,
256 /// Represents the description of an invoice which has to be either a directly included string or
257 /// a hash of a description provided out of band.
259 /// This is not exported to bindings users as we don't have a good way to map the reference lifetimes making this
260 /// practically impossible to use safely in languages like C.
261 #[derive(Eq, PartialEq, Debug, Clone)]
262 pub enum InvoiceDescription<'f> {
263 /// Reference to the directly supplied description in the invoice
264 Direct(&'f Description),
266 /// Reference to the description's hash included in the invoice
270 /// Represents a signed [`RawInvoice`] with cached hash. The signature is not checked and may be
274 /// The hash has to be either from the deserialized invoice or from the serialized [`RawInvoice`].
275 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
276 pub struct SignedRawInvoice {
277 /// The rawInvoice that the signature belongs to
278 raw_invoice: RawInvoice,
280 /// Hash of the [`RawInvoice`] that will be used to check the signature.
282 /// * if the `SignedRawInvoice` was deserialized the hash is of from the original encoded form,
283 /// since it's not guaranteed that encoding it again will lead to the same result since integers
284 /// could have been encoded with leading zeroes etc.
285 /// * if the `SignedRawInvoice` was constructed manually the hash will be the calculated hash
286 /// from the [`RawInvoice`]
289 /// signature of the payment request
290 signature: InvoiceSignature,
293 /// Represents an syntactically correct [`Invoice`] for a payment on the lightning network,
294 /// but without the signature information.
295 /// Decoding and encoding should not lead to information loss but may lead to different hashes.
297 /// For methods without docs see the corresponding methods in [`Invoice`].
298 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
299 pub struct RawInvoice {
300 /// human readable part
304 pub data: RawDataPart,
307 /// Data of the [`RawInvoice`] that is encoded in the human readable part.
309 /// This is not exported to bindings users as we don't yet support `Option<Enum>`
310 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
312 /// The currency deferred from the 3rd and 4th character of the bech32 transaction
313 pub currency: Currency,
315 /// The amount that, multiplied by the SI prefix, has to be payed
316 pub raw_amount: Option<u64>,
318 /// SI prefix that gets multiplied with the `raw_amount`
319 pub si_prefix: Option<SiPrefix>,
322 /// Data of the [`RawInvoice`] that is encoded in the data part
323 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
324 pub struct RawDataPart {
325 /// generation time of the invoice
326 pub timestamp: PositiveTimestamp,
328 /// tagged fields of the payment request
329 pub tagged_fields: Vec<RawTaggedField>,
332 /// A timestamp that refers to a date after 1 January 1970.
336 /// The Unix timestamp representing the stored time has to be positive and no greater than
337 /// [`MAX_TIMESTAMP`].
338 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
339 pub struct PositiveTimestamp(Duration);
341 /// SI prefixes for the human readable part
342 #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
355 /// Returns the multiplier to go from a BTC value to picoBTC implied by this SiPrefix.
356 /// This is effectively 10^12 * the prefix multiplier
357 pub fn multiplier(&self) -> u64 {
359 SiPrefix::Milli => 1_000_000_000,
360 SiPrefix::Micro => 1_000_000,
361 SiPrefix::Nano => 1_000,
366 /// Returns all enum variants of `SiPrefix` sorted in descending order of their associated
369 /// This is not exported to bindings users as we don't yet support a slice of enums, and also because this function
370 /// isn't the most critical to expose.
371 pub fn values_desc() -> &'static [SiPrefix] {
372 use crate::SiPrefix::*;
373 static VALUES: [SiPrefix; 4] = [Milli, Micro, Nano, Pico];
378 /// Enum representing the crypto currencies (or networks) supported by this library
379 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
397 impl From<Network> for Currency {
398 fn from(network: Network) -> Self {
400 Network::Bitcoin => Currency::Bitcoin,
401 Network::Testnet => Currency::BitcoinTestnet,
402 Network::Regtest => Currency::Regtest,
403 Network::Signet => Currency::Signet,
408 impl From<Currency> for Network {
409 fn from(currency: Currency) -> Self {
411 Currency::Bitcoin => Network::Bitcoin,
412 Currency::BitcoinTestnet => Network::Testnet,
413 Currency::Regtest => Network::Regtest,
414 Currency::Simnet => Network::Regtest,
415 Currency::Signet => Network::Signet,
420 /// Tagged field which may have an unknown tag
422 /// This is not exported to bindings users as we don't currently support TaggedField
423 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
424 pub enum RawTaggedField {
425 /// Parsed tagged field with known tag
426 KnownSemantics(TaggedField),
427 /// tagged field which was not parsed due to an unknown tag or undefined field semantics
428 UnknownSemantics(Vec<u5>),
431 /// Tagged field with known tag
433 /// For descriptions of the enum values please refer to the enclosed type's docs.
435 /// This is not exported to bindings users as we don't yet support enum variants with the same name the struct contained
437 #[allow(missing_docs)]
438 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
439 pub enum TaggedField {
441 Description(Description),
442 PayeePubKey(PayeePubKey),
443 DescriptionHash(Sha256),
444 ExpiryTime(ExpiryTime),
445 MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta),
447 PrivateRoute(PrivateRoute),
448 PaymentSecret(PaymentSecret),
449 PaymentMetadata(Vec<u8>),
450 Features(InvoiceFeatures),
454 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
455 pub struct Sha256(/// This is not exported to bindings users as the native hash types are not currently mapped
459 /// Constructs a new [`Sha256`] from the given bytes, which are assumed to be the output of a
460 /// single sha256 hash.
462 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
463 Self(sha256::Hash::from_slice(bytes).expect("from_slice only fails if len is not 32"))
467 /// Description string
470 /// The description can be at most 639 __bytes__ long
471 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
472 pub struct Description(String);
475 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
476 pub struct PayeePubKey(pub PublicKey);
478 /// Positive duration that defines when (relatively to the timestamp) in the future the invoice
480 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
481 pub struct ExpiryTime(Duration);
483 /// `min_final_cltv_expiry_delta` to use for the last HTLC in the route
484 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
485 pub struct MinFinalCltvExpiryDelta(pub u64);
487 /// Fallback address in case no LN payment is possible
488 #[allow(missing_docs)]
489 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
492 version: WitnessVersion,
495 PubKeyHash(PubkeyHash),
496 ScriptHash(ScriptHash),
499 /// Recoverable signature
500 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
501 pub struct InvoiceSignature(pub RecoverableSignature);
503 /// Private routing information
506 /// The encoded route has to be <1024 5bit characters long (<=639 bytes or <=12 hops)
508 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
509 pub struct PrivateRoute(RouteHint);
511 /// Tag constants as specified in BOLT11
512 #[allow(missing_docs)]
514 pub const TAG_PAYMENT_HASH: u8 = 1;
515 pub const TAG_DESCRIPTION: u8 = 13;
516 pub const TAG_PAYEE_PUB_KEY: u8 = 19;
517 pub const TAG_DESCRIPTION_HASH: u8 = 23;
518 pub const TAG_EXPIRY_TIME: u8 = 6;
519 pub const TAG_MIN_FINAL_CLTV_EXPIRY_DELTA: u8 = 24;
520 pub const TAG_FALLBACK: u8 = 9;
521 pub const TAG_PRIVATE_ROUTE: u8 = 3;
522 pub const TAG_PAYMENT_SECRET: u8 = 16;
523 pub const TAG_PAYMENT_METADATA: u8 = 27;
524 pub const TAG_FEATURES: u8 = 5;
527 impl InvoiceBuilder<tb::False, tb::False, tb::False, tb::False, tb::False, tb::False> {
528 /// Construct new, empty `InvoiceBuilder`. All necessary fields have to be filled first before
529 /// `InvoiceBuilder::build(self)` becomes available.
530 pub fn new(currency: Currency) -> Self {
536 tagged_fields: Vec::new(),
539 phantom_d: core::marker::PhantomData,
540 phantom_h: core::marker::PhantomData,
541 phantom_t: core::marker::PhantomData,
542 phantom_c: core::marker::PhantomData,
543 phantom_s: core::marker::PhantomData,
544 phantom_m: core::marker::PhantomData,
549 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, T, C, S, M> {
550 /// Helper function to set the completeness flags.
551 fn set_flags<DN: tb::Bool, HN: tb::Bool, TN: tb::Bool, CN: tb::Bool, SN: tb::Bool, MN: tb::Bool>(self) -> InvoiceBuilder<DN, HN, TN, CN, SN, MN> {
552 InvoiceBuilder::<DN, HN, TN, CN, SN, MN> {
553 currency: self.currency,
555 si_prefix: self.si_prefix,
556 timestamp: self.timestamp,
557 tagged_fields: self.tagged_fields,
560 phantom_d: core::marker::PhantomData,
561 phantom_h: core::marker::PhantomData,
562 phantom_t: core::marker::PhantomData,
563 phantom_c: core::marker::PhantomData,
564 phantom_s: core::marker::PhantomData,
565 phantom_m: core::marker::PhantomData,
569 /// Sets the amount in millisatoshis. The optimal SI prefix is chosen automatically.
570 pub fn amount_milli_satoshis(mut self, amount_msat: u64) -> Self {
571 let amount = amount_msat * 10; // Invoices are denominated in "pico BTC"
572 let biggest_possible_si_prefix = SiPrefix::values_desc()
574 .find(|prefix| amount % prefix.multiplier() == 0)
575 .expect("Pico should always match");
576 self.amount = Some(amount / biggest_possible_si_prefix.multiplier());
577 self.si_prefix = Some(*biggest_possible_si_prefix);
581 /// Sets the payee's public key.
582 pub fn payee_pub_key(mut self, pub_key: PublicKey) -> Self {
583 self.tagged_fields.push(TaggedField::PayeePubKey(PayeePubKey(pub_key)));
587 /// Sets the expiry time, dropping the subsecond part (which is not representable in BOLT 11
589 pub fn expiry_time(mut self, expiry_time: Duration) -> Self {
590 self.tagged_fields.push(TaggedField::ExpiryTime(ExpiryTime::from_duration(expiry_time)));
594 /// Adds a fallback address.
595 pub fn fallback(mut self, fallback: Fallback) -> Self {
596 self.tagged_fields.push(TaggedField::Fallback(fallback));
600 /// Adds a private route.
601 pub fn private_route(mut self, hint: RouteHint) -> Self {
602 match PrivateRoute::new(hint) {
603 Ok(r) => self.tagged_fields.push(TaggedField::PrivateRoute(r)),
604 Err(e) => self.error = Some(e),
610 impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, tb::True, C, S, M> {
611 /// Builds a [`RawInvoice`] if no [`CreationError`] occurred while construction any of the
613 pub fn build_raw(self) -> Result<RawInvoice, CreationError> {
615 // If an error occurred at any time before, return it now
616 if let Some(e) = self.error {
621 currency: self.currency,
622 raw_amount: self.amount,
623 si_prefix: self.si_prefix,
626 let timestamp = self.timestamp.expect("ensured to be Some(t) by type T");
628 let tagged_fields = self.tagged_fields.into_iter().map(|tf| {
629 RawTaggedField::KnownSemantics(tf)
630 }).collect::<Vec<_>>();
632 let data = RawDataPart {
644 impl<H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<tb::False, H, T, C, S, M> {
645 /// Set the description. This function is only available if no description (hash) was set.
646 pub fn description(mut self, description: String) -> InvoiceBuilder<tb::True, H, T, C, S, M> {
647 match Description::new(description) {
648 Ok(d) => self.tagged_fields.push(TaggedField::Description(d)),
649 Err(e) => self.error = Some(e),
654 /// Set the description hash. This function is only available if no description (hash) was set.
655 pub fn description_hash(mut self, description_hash: sha256::Hash) -> InvoiceBuilder<tb::True, H, T, C, S, M> {
656 self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash)));
660 /// Set the description or description hash. This function is only available if no description (hash) was set.
661 pub fn invoice_description(self, description: InvoiceDescription) -> InvoiceBuilder<tb::True, H, T, C, S, M> {
663 InvoiceDescription::Direct(desc) => {
664 self.description(desc.clone().into_inner())
666 InvoiceDescription::Hash(hash) => {
667 self.description_hash(hash.0)
673 impl<D: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<D, tb::False, T, C, S, M> {
674 /// Set the payment hash. This function is only available if no payment hash was set.
675 pub fn payment_hash(mut self, hash: sha256::Hash) -> InvoiceBuilder<D, tb::True, T, C, S, M> {
676 self.tagged_fields.push(TaggedField::PaymentHash(Sha256(hash)));
681 impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, tb::False, C, S, M> {
682 /// Sets the timestamp to a specific [`SystemTime`].
683 #[cfg(feature = "std")]
684 pub fn timestamp(mut self, time: SystemTime) -> InvoiceBuilder<D, H, tb::True, C, S, M> {
685 match PositiveTimestamp::from_system_time(time) {
686 Ok(t) => self.timestamp = Some(t),
687 Err(e) => self.error = Some(e),
693 /// Sets the timestamp to a duration since the Unix epoch, dropping the subsecond part (which
694 /// is not representable in BOLT 11 invoices).
695 pub fn duration_since_epoch(mut self, time: Duration) -> InvoiceBuilder<D, H, tb::True, C, S, M> {
696 match PositiveTimestamp::from_duration_since_epoch(time) {
697 Ok(t) => self.timestamp = Some(t),
698 Err(e) => self.error = Some(e),
704 /// Sets the timestamp to the current system time.
705 #[cfg(feature = "std")]
706 pub fn current_timestamp(mut self) -> InvoiceBuilder<D, H, tb::True, C, S, M> {
707 let now = PositiveTimestamp::from_system_time(SystemTime::now());
708 self.timestamp = Some(now.expect("for the foreseeable future this shouldn't happen"));
713 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, S: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, T, tb::False, S, M> {
714 /// Sets `min_final_cltv_expiry_delta`.
715 pub fn min_final_cltv_expiry_delta(mut self, min_final_cltv_expiry_delta: u64) -> InvoiceBuilder<D, H, T, tb::True, S, M> {
716 self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta(min_final_cltv_expiry_delta)));
721 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, T, C, tb::False, M> {
722 /// Sets the payment secret and relevant features.
723 pub fn payment_secret(mut self, payment_secret: PaymentSecret) -> InvoiceBuilder<D, H, T, C, tb::True, M> {
724 let mut found_features = false;
725 for field in self.tagged_fields.iter_mut() {
726 if let TaggedField::Features(f) = field {
727 found_features = true;
728 f.set_variable_length_onion_required();
729 f.set_payment_secret_required();
732 self.tagged_fields.push(TaggedField::PaymentSecret(payment_secret));
734 let mut features = InvoiceFeatures::empty();
735 features.set_variable_length_onion_required();
736 features.set_payment_secret_required();
737 self.tagged_fields.push(TaggedField::Features(features));
743 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, C, S, tb::False> {
744 /// Sets the payment metadata.
746 /// By default features are set to *optionally* allow the sender to include the payment metadata.
747 /// If you wish to require that the sender include the metadata (and fail to parse the invoice if
748 /// they don't support payment metadata fields), you need to call
749 /// [`InvoiceBuilder::require_payment_metadata`] after this.
750 pub fn payment_metadata(mut self, payment_metadata: Vec<u8>) -> InvoiceBuilder<D, H, T, C, S, tb::True> {
751 self.tagged_fields.push(TaggedField::PaymentMetadata(payment_metadata));
752 let mut found_features = false;
753 for field in self.tagged_fields.iter_mut() {
754 if let TaggedField::Features(f) = field {
755 found_features = true;
756 f.set_payment_metadata_optional();
760 let mut features = InvoiceFeatures::empty();
761 features.set_payment_metadata_optional();
762 self.tagged_fields.push(TaggedField::Features(features));
768 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, C, S, tb::True> {
769 /// Sets forwarding of payment metadata as required. A reader of the invoice which does not
770 /// support sending payment metadata will fail to read the invoice.
771 pub fn require_payment_metadata(mut self) -> InvoiceBuilder<D, H, T, C, S, tb::True> {
772 for field in self.tagged_fields.iter_mut() {
773 if let TaggedField::Features(f) = field {
774 f.set_payment_metadata_required();
781 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, M: tb::Bool> InvoiceBuilder<D, H, T, C, tb::True, M> {
782 /// Sets the `basic_mpp` feature as optional.
783 pub fn basic_mpp(mut self) -> Self {
784 for field in self.tagged_fields.iter_mut() {
785 if let TaggedField::Features(f) = field {
786 f.set_basic_mpp_optional();
793 impl<M: tb::Bool> InvoiceBuilder<tb::True, tb::True, tb::True, tb::True, tb::True, M> {
794 /// Builds and signs an invoice using the supplied `sign_function`. This function MAY NOT fail
795 /// and MUST produce a recoverable signature valid for the given hash and if applicable also for
796 /// the included payee public key.
797 pub fn build_signed<F>(self, sign_function: F) -> Result<Invoice, CreationError>
798 where F: FnOnce(&Message) -> RecoverableSignature
800 let invoice = self.try_build_signed::<_, ()>(|hash| {
801 Ok(sign_function(hash))
806 Err(SignOrCreationError::CreationError(e)) => Err(e),
807 Err(SignOrCreationError::SignError(())) => unreachable!(),
811 /// Builds and signs an invoice using the supplied `sign_function`. This function MAY fail with
812 /// an error of type `E` and MUST produce a recoverable signature valid for the given hash and
813 /// if applicable also for the included payee public key.
814 pub fn try_build_signed<F, E>(self, sign_function: F) -> Result<Invoice, SignOrCreationError<E>>
815 where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
817 let raw = match self.build_raw() {
819 Err(e) => return Err(SignOrCreationError::CreationError(e)),
822 let signed = match raw.sign(sign_function) {
824 Err(e) => return Err(SignOrCreationError::SignError(e)),
827 let invoice = Invoice {
828 signed_invoice: signed,
831 invoice.check_field_counts().expect("should be ensured by type signature of builder");
832 invoice.check_feature_bits().expect("should be ensured by type signature of builder");
833 invoice.check_amount().expect("should be ensured by type signature of builder");
840 impl SignedRawInvoice {
841 /// Disassembles the `SignedRawInvoice` into its three parts:
843 /// 2. hash of the raw invoice
845 pub fn into_parts(self) -> (RawInvoice, [u8; 32], InvoiceSignature) {
846 (self.raw_invoice, self.hash, self.signature)
849 /// The [`RawInvoice`] which was signed.
850 pub fn raw_invoice(&self) -> &RawInvoice {
854 /// The hash of the [`RawInvoice`] that was signed.
855 pub fn signable_hash(&self) -> &[u8; 32] {
859 /// Signature for the invoice.
860 pub fn signature(&self) -> &InvoiceSignature {
864 /// Recovers the public key used for signing the invoice from the recoverable signature.
865 pub fn recover_payee_pub_key(&self) -> Result<PayeePubKey, secp256k1::Error> {
866 let hash = Message::from_slice(&self.hash[..])
867 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
869 Ok(PayeePubKey(Secp256k1::new().recover_ecdsa(
875 /// Checks if the signature is valid for the included payee public key or if none exists if it's
876 /// valid for the recovered signature (which should always be true?).
877 pub fn check_signature(&self) -> bool {
878 let included_pub_key = self.raw_invoice.payee_pub_key();
880 let mut recovered_pub_key = Option::None;
881 if recovered_pub_key.is_none() {
882 let recovered = match self.recover_payee_pub_key() {
884 Err(_) => return false,
886 recovered_pub_key = Some(recovered);
889 let pub_key = included_pub_key.or(recovered_pub_key.as_ref())
890 .expect("One is always present");
892 let hash = Message::from_slice(&self.hash[..])
893 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
895 let secp_context = Secp256k1::new();
896 let verification_result = secp_context.verify_ecdsa(
898 &self.signature.to_standard(),
902 match verification_result {
909 /// Finds the first element of an enum stream of a given variant and extracts one member of the
910 /// variant. If no element was found `None` gets returned.
912 /// The following example would extract the first B.
920 /// let elements = vec![Enum::A(1), Enum::A(2), Enum::B(3), Enum::A(4)];
922 /// assert_eq!(find_extract!(elements.iter(), Enum::B(x), x), Some(3u16));
924 macro_rules! find_extract {
925 ($iter:expr, $enm:pat, $enm_var:ident) => {
926 find_all_extract!($iter, $enm, $enm_var).next()
930 /// Finds the all elements of an enum stream of a given variant and extracts one member of the
931 /// variant through an iterator.
933 /// The following example would extract all A.
941 /// let elements = vec![Enum::A(1), Enum::A(2), Enum::B(3), Enum::A(4)];
944 /// find_all_extract!(elements.iter(), Enum::A(x), x).collect::<Vec<u8>>(),
945 /// vec![1u8, 2u8, 4u8]
948 macro_rules! find_all_extract {
949 ($iter:expr, $enm:pat, $enm_var:ident) => {
950 $iter.filter_map(|tf| match *tf {
951 $enm => Some($enm_var),
957 #[allow(missing_docs)]
959 /// Hash the HRP as bytes and signatureless data part.
960 fn hash_from_parts(hrp_bytes: &[u8], data_without_signature: &[u5]) -> [u8; 32] {
961 let preimage = construct_invoice_preimage(hrp_bytes, data_without_signature);
962 let mut hash: [u8; 32] = Default::default();
963 hash.copy_from_slice(&sha256::Hash::hash(&preimage)[..]);
967 /// Calculate the hash of the encoded `RawInvoice` which should be signed.
968 pub fn signable_hash(&self) -> [u8; 32] {
969 use bech32::ToBase32;
971 RawInvoice::hash_from_parts(
972 self.hrp.to_string().as_bytes(),
973 &self.data.to_base32()
977 /// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of
978 /// type `E`. Since the signature of a [`SignedRawInvoice`] is not required to be valid there
979 /// are no constraints regarding the validity of the produced signature.
981 /// This is not exported to bindings users as we don't currently support passing function pointers into methods
983 pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
984 where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
986 let raw_hash = self.signable_hash();
987 let hash = Message::from_slice(&raw_hash[..])
988 .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
989 let signature = sign_method(&hash)?;
991 Ok(SignedRawInvoice {
994 signature: InvoiceSignature(signature),
998 /// Returns an iterator over all tagged fields with known semantics.
1000 /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap
1001 pub fn known_tagged_fields(&self)
1002 -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>>
1004 // For 1.14.0 compatibility: closures' types can't be written an fn()->() in the
1005 // function's type signature.
1006 // TODO: refactor once impl Trait is available
1007 fn match_raw(raw: &RawTaggedField) -> Option<&TaggedField> {
1009 RawTaggedField::KnownSemantics(ref tf) => Some(tf),
1014 self.data.tagged_fields.iter().filter_map(match_raw )
1017 pub fn payment_hash(&self) -> Option<&Sha256> {
1018 find_extract!(self.known_tagged_fields(), TaggedField::PaymentHash(ref x), x)
1021 pub fn description(&self) -> Option<&Description> {
1022 find_extract!(self.known_tagged_fields(), TaggedField::Description(ref x), x)
1025 pub fn payee_pub_key(&self) -> Option<&PayeePubKey> {
1026 find_extract!(self.known_tagged_fields(), TaggedField::PayeePubKey(ref x), x)
1029 pub fn description_hash(&self) -> Option<&Sha256> {
1030 find_extract!(self.known_tagged_fields(), TaggedField::DescriptionHash(ref x), x)
1033 pub fn expiry_time(&self) -> Option<&ExpiryTime> {
1034 find_extract!(self.known_tagged_fields(), TaggedField::ExpiryTime(ref x), x)
1037 pub fn min_final_cltv_expiry_delta(&self) -> Option<&MinFinalCltvExpiryDelta> {
1038 find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiryDelta(ref x), x)
1041 pub fn payment_secret(&self) -> Option<&PaymentSecret> {
1042 find_extract!(self.known_tagged_fields(), TaggedField::PaymentSecret(ref x), x)
1045 pub fn payment_metadata(&self) -> Option<&Vec<u8>> {
1046 find_extract!(self.known_tagged_fields(), TaggedField::PaymentMetadata(ref x), x)
1049 pub fn features(&self) -> Option<&InvoiceFeatures> {
1050 find_extract!(self.known_tagged_fields(), TaggedField::Features(ref x), x)
1053 /// This is not exported to bindings users as we don't support Vec<&NonOpaqueType>
1054 pub fn fallbacks(&self) -> Vec<&Fallback> {
1055 find_all_extract!(self.known_tagged_fields(), TaggedField::Fallback(ref x), x).collect()
1058 pub fn private_routes(&self) -> Vec<&PrivateRoute> {
1059 find_all_extract!(self.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x).collect()
1062 pub fn amount_pico_btc(&self) -> Option<u64> {
1063 self.hrp.raw_amount.map(|v| {
1064 v * self.hrp.si_prefix.as_ref().map_or(1_000_000_000_000, |si| { si.multiplier() })
1068 pub fn currency(&self) -> Currency {
1069 self.hrp.currency.clone()
1073 impl PositiveTimestamp {
1074 /// Creates a `PositiveTimestamp` from a Unix timestamp in the range `0..=MAX_TIMESTAMP`.
1076 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
1077 pub fn from_unix_timestamp(unix_seconds: u64) -> Result<Self, CreationError> {
1078 if unix_seconds <= MAX_TIMESTAMP {
1079 Ok(Self(Duration::from_secs(unix_seconds)))
1081 Err(CreationError::TimestampOutOfBounds)
1085 /// Creates a `PositiveTimestamp` from a [`SystemTime`] with a corresponding Unix timestamp in
1086 /// the range `0..=MAX_TIMESTAMP`.
1088 /// Note that the subsecond part is dropped as it is not representable in BOLT 11 invoices.
1090 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
1091 #[cfg(feature = "std")]
1092 pub fn from_system_time(time: SystemTime) -> Result<Self, CreationError> {
1093 time.duration_since(SystemTime::UNIX_EPOCH)
1094 .map(Self::from_duration_since_epoch)
1095 .unwrap_or(Err(CreationError::TimestampOutOfBounds))
1098 /// Creates a `PositiveTimestamp` from a [`Duration`] since the Unix epoch in the range
1099 /// `0..=MAX_TIMESTAMP`.
1101 /// Note that the subsecond part is dropped as it is not representable in BOLT 11 invoices.
1103 /// Otherwise, returns a [`CreationError::TimestampOutOfBounds`].
1104 pub fn from_duration_since_epoch(duration: Duration) -> Result<Self, CreationError> {
1105 Self::from_unix_timestamp(duration.as_secs())
1108 /// Returns the Unix timestamp representing the stored time
1109 pub fn as_unix_timestamp(&self) -> u64 {
1113 /// Returns the duration of the stored time since the Unix epoch
1114 pub fn as_duration_since_epoch(&self) -> Duration {
1118 /// Returns the [`SystemTime`] representing the stored time
1119 #[cfg(feature = "std")]
1120 pub fn as_time(&self) -> SystemTime {
1121 SystemTime::UNIX_EPOCH + self.0
1125 #[cfg(feature = "std")]
1126 impl From<PositiveTimestamp> for SystemTime {
1127 fn from(val: PositiveTimestamp) -> Self {
1128 SystemTime::UNIX_EPOCH + val.0
1133 /// The hash of the [`RawInvoice`] that was signed.
1134 pub fn signable_hash(&self) -> [u8; 32] {
1135 self.signed_invoice.hash
1138 /// Transform the `Invoice` into it's unchecked version
1139 pub fn into_signed_raw(self) -> SignedRawInvoice {
1143 /// Check that all mandatory fields are present
1144 fn check_field_counts(&self) -> Result<(), SemanticError> {
1145 // "A writer MUST include exactly one p field […]."
1146 let payment_hash_cnt = self.tagged_fields().filter(|&tf| match *tf {
1147 TaggedField::PaymentHash(_) => true,
1150 if payment_hash_cnt < 1 {
1151 return Err(SemanticError::NoPaymentHash);
1152 } else if payment_hash_cnt > 1 {
1153 return Err(SemanticError::MultiplePaymentHashes);
1156 // "A writer MUST include either exactly one d or exactly one h field."
1157 let description_cnt = self.tagged_fields().filter(|&tf| match *tf {
1158 TaggedField::Description(_) | TaggedField::DescriptionHash(_) => true,
1161 if description_cnt < 1 {
1162 return Err(SemanticError::NoDescription);
1163 } else if description_cnt > 1 {
1164 return Err(SemanticError::MultipleDescriptions);
1167 self.check_payment_secret()?;
1172 /// Checks that there is exactly one payment secret field
1173 fn check_payment_secret(&self) -> Result<(), SemanticError> {
1174 // "A writer MUST include exactly one `s` field."
1175 let payment_secret_count = self.tagged_fields().filter(|&tf| match *tf {
1176 TaggedField::PaymentSecret(_) => true,
1179 if payment_secret_count < 1 {
1180 return Err(SemanticError::NoPaymentSecret);
1181 } else if payment_secret_count > 1 {
1182 return Err(SemanticError::MultiplePaymentSecrets);
1188 /// Check that amount is a whole number of millisatoshis
1189 fn check_amount(&self) -> Result<(), SemanticError> {
1190 if let Some(amount_pico_btc) = self.amount_pico_btc() {
1191 if amount_pico_btc % 10 != 0 {
1192 return Err(SemanticError::ImpreciseAmount);
1198 /// Check that feature bits are set as required
1199 fn check_feature_bits(&self) -> Result<(), SemanticError> {
1200 self.check_payment_secret()?;
1202 // "A writer MUST set an s field if and only if the payment_secret feature is set."
1203 // (this requirement has been since removed, and we now require the payment secret
1204 // feature bit always).
1205 let features = self.tagged_fields().find(|&tf| match *tf {
1206 TaggedField::Features(_) => true,
1210 None => Err(SemanticError::InvalidFeatures),
1211 Some(TaggedField::Features(features)) => {
1212 if features.requires_unknown_bits() {
1213 Err(SemanticError::InvalidFeatures)
1214 } else if !features.supports_payment_secret() {
1215 Err(SemanticError::InvalidFeatures)
1220 Some(_) => unreachable!(),
1224 /// Check that the invoice is signed correctly and that key recovery works
1225 pub fn check_signature(&self) -> Result<(), SemanticError> {
1226 match self.signed_invoice.recover_payee_pub_key() {
1227 Err(secp256k1::Error::InvalidRecoveryId) =>
1228 return Err(SemanticError::InvalidRecoveryId),
1229 Err(secp256k1::Error::InvalidSignature) =>
1230 return Err(SemanticError::InvalidSignature),
1231 Err(e) => panic!("no other error may occur, got {:?}", e),
1235 if !self.signed_invoice.check_signature() {
1236 return Err(SemanticError::InvalidSignature);
1242 /// Constructs an `Invoice` from a [`SignedRawInvoice`] by checking all its invariants.
1244 /// use lightning_invoice::*;
1246 /// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
1247 /// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
1248 /// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
1249 /// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
1250 /// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
1251 /// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
1252 /// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
1253 /// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
1254 /// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
1255 /// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
1256 /// j5r6drg6k6zcqj0fcwg";
1258 /// let signed = invoice.parse::<SignedRawInvoice>().unwrap();
1260 /// assert!(Invoice::from_signed(signed).is_ok());
1262 pub fn from_signed(signed_invoice: SignedRawInvoice) -> Result<Self, SemanticError> {
1263 let invoice = Invoice {
1266 invoice.check_field_counts()?;
1267 invoice.check_feature_bits()?;
1268 invoice.check_signature()?;
1269 invoice.check_amount()?;
1274 /// Returns the `Invoice`'s timestamp (should equal its creation time)
1275 #[cfg(feature = "std")]
1276 pub fn timestamp(&self) -> SystemTime {
1277 self.signed_invoice.raw_invoice().data.timestamp.as_time()
1280 /// Returns the `Invoice`'s timestamp as a duration since the Unix epoch
1281 pub fn duration_since_epoch(&self) -> Duration {
1282 self.signed_invoice.raw_invoice().data.timestamp.0
1285 /// Returns an iterator over all tagged fields of this Invoice.
1287 /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap
1288 pub fn tagged_fields(&self)
1289 -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
1290 self.signed_invoice.raw_invoice().known_tagged_fields()
1293 /// Returns the hash to which we will receive the preimage on completion of the payment
1294 pub fn payment_hash(&self) -> &sha256::Hash {
1295 &self.signed_invoice.payment_hash().expect("checked by constructor").0
1298 /// Return the description or a hash of it for longer ones
1300 /// This is not exported to bindings users because we don't yet export InvoiceDescription
1301 pub fn description(&self) -> InvoiceDescription {
1302 if let Some(direct) = self.signed_invoice.description() {
1303 return InvoiceDescription::Direct(direct);
1304 } else if let Some(hash) = self.signed_invoice.description_hash() {
1305 return InvoiceDescription::Hash(hash);
1307 unreachable!("ensured by constructor");
1310 /// Get the payee's public key if one was included in the invoice
1311 pub fn payee_pub_key(&self) -> Option<&PublicKey> {
1312 self.signed_invoice.payee_pub_key().map(|x| &x.0)
1315 /// Get the payment secret if one was included in the invoice
1316 pub fn payment_secret(&self) -> &PaymentSecret {
1317 self.signed_invoice.payment_secret().expect("was checked by constructor")
1320 /// Get the payment metadata blob if one was included in the invoice
1321 pub fn payment_metadata(&self) -> Option<&Vec<u8>> {
1322 self.signed_invoice.payment_metadata()
1325 /// Get the invoice features if they were included in the invoice
1326 pub fn features(&self) -> Option<&InvoiceFeatures> {
1327 self.signed_invoice.features()
1330 /// Recover the payee's public key (only to be used if none was included in the invoice)
1331 pub fn recover_payee_pub_key(&self) -> PublicKey {
1332 self.signed_invoice.recover_payee_pub_key().expect("was checked by constructor").0
1335 /// Returns the Duration since the Unix epoch at which the invoice expires.
1336 /// Returning None if overflow occurred.
1337 pub fn expires_at(&self) -> Option<Duration> {
1338 self.duration_since_epoch().checked_add(self.expiry_time())
1341 /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`].
1342 pub fn expiry_time(&self) -> Duration {
1343 self.signed_invoice.expiry_time()
1345 .unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
1348 /// Returns whether the invoice has expired.
1349 #[cfg(feature = "std")]
1350 pub fn is_expired(&self) -> bool {
1351 Self::is_expired_from_epoch(&self.timestamp(), self.expiry_time())
1354 /// Returns whether the expiry time from the given epoch has passed.
1355 #[cfg(feature = "std")]
1356 pub(crate) fn is_expired_from_epoch(epoch: &SystemTime, expiry_time: Duration) -> bool {
1357 match epoch.elapsed() {
1358 Ok(elapsed) => elapsed > expiry_time,
1363 /// Returns the Duration remaining until the invoice expires.
1364 #[cfg(feature = "std")]
1365 pub fn duration_until_expiry(&self) -> Duration {
1366 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
1367 .map(|now| self.expiration_remaining_from_epoch(now))
1368 .unwrap_or(Duration::from_nanos(0))
1371 /// Returns the Duration remaining until the invoice expires given the current time.
1372 /// `time` is the timestamp as a duration since the Unix epoch.
1373 pub fn expiration_remaining_from_epoch(&self, time: Duration) -> Duration {
1374 self.expires_at().map(|x| x.checked_sub(time)).flatten().unwrap_or(Duration::from_nanos(0))
1377 /// Returns whether the expiry time would pass at the given point in time.
1378 /// `at_time` is the timestamp as a duration since the Unix epoch.
1379 pub fn would_expire(&self, at_time: Duration) -> bool {
1380 self.duration_since_epoch()
1381 .checked_add(self.expiry_time())
1382 .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time
1385 /// Returns the invoice's `min_final_cltv_expiry_delta` time, if present, otherwise
1386 /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA`].
1387 pub fn min_final_cltv_expiry_delta(&self) -> u64 {
1388 self.signed_invoice.min_final_cltv_expiry_delta()
1390 .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA)
1393 /// Returns a list of all fallback addresses
1395 /// This is not exported to bindings users as we don't support Vec<&NonOpaqueType>
1396 pub fn fallbacks(&self) -> Vec<&Fallback> {
1397 self.signed_invoice.fallbacks()
1400 /// Returns a list of all fallback addresses as [`Address`]es
1401 pub fn fallback_addresses(&self) -> Vec<Address> {
1402 self.fallbacks().iter().map(|fallback| {
1403 let payload = match fallback {
1404 Fallback::SegWitProgram { version, program } => {
1405 Payload::WitnessProgram { version: *version, program: program.to_vec() }
1407 Fallback::PubKeyHash(pkh) => {
1408 Payload::PubkeyHash(*pkh)
1410 Fallback::ScriptHash(sh) => {
1411 Payload::ScriptHash(*sh)
1415 Address { payload, network: self.network() }
1419 /// Returns a list of all routes included in the invoice
1420 pub fn private_routes(&self) -> Vec<&PrivateRoute> {
1421 self.signed_invoice.private_routes()
1424 /// Returns a list of all routes included in the invoice as the underlying hints
1425 pub fn route_hints(&self) -> Vec<RouteHint> {
1427 self.signed_invoice.known_tagged_fields(), TaggedField::PrivateRoute(ref x), x
1428 ).map(|route| (**route).clone()).collect()
1431 /// Returns the currency for which the invoice was issued
1432 pub fn currency(&self) -> Currency {
1433 self.signed_invoice.currency()
1436 /// Returns the network for which the invoice was issued
1438 /// This is not exported to bindings users, see [`Self::currency`] instead.
1439 pub fn network(&self) -> Network {
1440 self.signed_invoice.currency().into()
1443 /// Returns the amount if specified in the invoice as millisatoshis.
1444 pub fn amount_milli_satoshis(&self) -> Option<u64> {
1445 self.signed_invoice.amount_pico_btc().map(|v| v / 10)
1448 /// Returns the amount if specified in the invoice as pico BTC.
1449 fn amount_pico_btc(&self) -> Option<u64> {
1450 self.signed_invoice.amount_pico_btc()
1454 impl From<TaggedField> for RawTaggedField {
1455 fn from(tf: TaggedField) -> Self {
1456 RawTaggedField::KnownSemantics(tf)
1461 /// Numeric representation of the field's tag
1462 pub fn tag(&self) -> u5 {
1463 let tag = match *self {
1464 TaggedField::PaymentHash(_) => constants::TAG_PAYMENT_HASH,
1465 TaggedField::Description(_) => constants::TAG_DESCRIPTION,
1466 TaggedField::PayeePubKey(_) => constants::TAG_PAYEE_PUB_KEY,
1467 TaggedField::DescriptionHash(_) => constants::TAG_DESCRIPTION_HASH,
1468 TaggedField::ExpiryTime(_) => constants::TAG_EXPIRY_TIME,
1469 TaggedField::MinFinalCltvExpiryDelta(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA,
1470 TaggedField::Fallback(_) => constants::TAG_FALLBACK,
1471 TaggedField::PrivateRoute(_) => constants::TAG_PRIVATE_ROUTE,
1472 TaggedField::PaymentSecret(_) => constants::TAG_PAYMENT_SECRET,
1473 TaggedField::PaymentMetadata(_) => constants::TAG_PAYMENT_METADATA,
1474 TaggedField::Features(_) => constants::TAG_FEATURES,
1477 u5::try_from_u8(tag).expect("all tags defined are <32")
1483 /// Creates a new `Description` if `description` is at most 1023 __bytes__ long,
1484 /// returns [`CreationError::DescriptionTooLong`] otherwise
1486 /// Please note that single characters may use more than one byte due to UTF8 encoding.
1487 pub fn new(description: String) -> Result<Description, CreationError> {
1488 if description.len() > 639 {
1489 Err(CreationError::DescriptionTooLong)
1491 Ok(Description(description))
1495 /// Returns the underlying description [`String`]
1496 pub fn into_inner(self) -> String {
1501 impl From<Description> for String {
1502 fn from(val: Description) -> Self {
1507 impl Deref for Description {
1510 fn deref(&self) -> &str {
1515 impl From<PublicKey> for PayeePubKey {
1516 fn from(pk: PublicKey) -> Self {
1521 impl Deref for PayeePubKey {
1522 type Target = PublicKey;
1524 fn deref(&self) -> &PublicKey {
1530 /// Construct an `ExpiryTime` from seconds.
1531 pub fn from_seconds(seconds: u64) -> ExpiryTime {
1532 ExpiryTime(Duration::from_secs(seconds))
1535 /// Construct an `ExpiryTime` from a [`Duration`], dropping the sub-second part.
1536 pub fn from_duration(duration: Duration) -> ExpiryTime {
1537 Self::from_seconds(duration.as_secs())
1540 /// Returns the expiry time in seconds
1541 pub fn as_seconds(&self) -> u64 {
1545 /// Returns a reference to the underlying [`Duration`] (=expiry time)
1546 pub fn as_duration(&self) -> &Duration {
1552 /// Creates a new (partial) route from a list of hops
1553 pub fn new(hops: RouteHint) -> Result<PrivateRoute, CreationError> {
1554 if hops.0.len() <= 12 {
1555 Ok(PrivateRoute(hops))
1557 Err(CreationError::RouteTooLong)
1561 /// Returns the underlying list of hops
1562 pub fn into_inner(self) -> RouteHint {
1567 impl From<PrivateRoute> for RouteHint {
1568 fn from(val: PrivateRoute) -> Self {
1573 impl Deref for PrivateRoute {
1574 type Target = RouteHint;
1576 fn deref(&self) -> &RouteHint {
1581 impl Deref for InvoiceSignature {
1582 type Target = RecoverableSignature;
1584 fn deref(&self) -> &RecoverableSignature {
1589 impl Deref for SignedRawInvoice {
1590 type Target = RawInvoice;
1592 fn deref(&self) -> &RawInvoice {
1597 /// Errors that may occur when constructing a new [`RawInvoice`] or [`Invoice`]
1598 #[derive(Eq, PartialEq, Debug, Clone)]
1599 pub enum CreationError {
1600 /// The supplied description string was longer than 639 __bytes__ (see [`Description::new`])
1603 /// The specified route has too many hops and can't be encoded
1606 /// The Unix timestamp of the supplied date is less than zero or greater than 35-bits
1607 TimestampOutOfBounds,
1609 /// The supplied millisatoshi amount was greater than the total bitcoin supply.
1612 /// Route hints were required for this invoice and were missing. Applies to
1613 /// [phantom invoices].
1615 /// [phantom invoices]: crate::utils::create_phantom_invoice
1618 /// The provided `min_final_cltv_expiry_delta` was less than [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
1620 /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
1621 MinFinalCltvExpiryDeltaTooShort,
1624 impl Display for CreationError {
1625 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1627 CreationError::DescriptionTooLong => f.write_str("The supplied description string was longer than 639 bytes"),
1628 CreationError::RouteTooLong => f.write_str("The specified route has too many hops and can't be encoded"),
1629 CreationError::TimestampOutOfBounds => f.write_str("The Unix timestamp of the supplied date is less than zero or greater than 35-bits"),
1630 CreationError::InvalidAmount => f.write_str("The supplied millisatoshi amount was greater than the total bitcoin supply"),
1631 CreationError::MissingRouteHints => f.write_str("The invoice required route hints and they weren't provided"),
1632 CreationError::MinFinalCltvExpiryDeltaTooShort => f.write_str(
1633 "The supplied final CLTV expiry delta was less than LDK's `MIN_FINAL_CLTV_EXPIRY_DELTA`"),
1638 #[cfg(feature = "std")]
1639 impl std::error::Error for CreationError { }
1641 /// Errors that may occur when converting a [`RawInvoice`] to an [`Invoice`]. They relate to the
1642 /// requirements sections in BOLT #11
1643 #[derive(Eq, PartialEq, Debug, Clone)]
1644 pub enum SemanticError {
1645 /// The invoice is missing the mandatory payment hash
1648 /// The invoice has multiple payment hashes which isn't allowed
1649 MultiplePaymentHashes,
1651 /// No description or description hash are part of the invoice
1654 /// The invoice contains multiple descriptions and/or description hashes which isn't allowed
1655 MultipleDescriptions,
1657 /// The invoice is missing the mandatory payment secret, which all modern lightning nodes
1661 /// The invoice contains multiple payment secrets
1662 MultiplePaymentSecrets,
1664 /// The invoice's features are invalid
1667 /// The recovery id doesn't fit the signature/pub key
1670 /// The invoice's signature is invalid
1673 /// The invoice's amount was not a whole number of millisatoshis
1677 impl Display for SemanticError {
1678 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1680 SemanticError::NoPaymentHash => f.write_str("The invoice is missing the mandatory payment hash"),
1681 SemanticError::MultiplePaymentHashes => f.write_str("The invoice has multiple payment hashes which isn't allowed"),
1682 SemanticError::NoDescription => f.write_str("No description or description hash are part of the invoice"),
1683 SemanticError::MultipleDescriptions => f.write_str("The invoice contains multiple descriptions and/or description hashes which isn't allowed"),
1684 SemanticError::NoPaymentSecret => f.write_str("The invoice is missing the mandatory payment secret"),
1685 SemanticError::MultiplePaymentSecrets => f.write_str("The invoice contains multiple payment secrets"),
1686 SemanticError::InvalidFeatures => f.write_str("The invoice's features are invalid"),
1687 SemanticError::InvalidRecoveryId => f.write_str("The recovery id doesn't fit the signature/pub key"),
1688 SemanticError::InvalidSignature => f.write_str("The invoice's signature is invalid"),
1689 SemanticError::ImpreciseAmount => f.write_str("The invoice's amount was not a whole number of millisatoshis"),
1694 #[cfg(feature = "std")]
1695 impl std::error::Error for SemanticError { }
1697 /// When signing using a fallible method either an user-supplied `SignError` or a [`CreationError`]
1699 #[derive(Eq, PartialEq, Debug, Clone)]
1700 pub enum SignOrCreationError<S = ()> {
1701 /// An error occurred during signing
1704 /// An error occurred while building the transaction
1705 CreationError(CreationError),
1708 impl<S> Display for SignOrCreationError<S> {
1709 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1711 SignOrCreationError::SignError(_) => f.write_str("An error occurred during signing"),
1712 SignOrCreationError::CreationError(err) => err.fmt(f),
1717 #[cfg(feature = "serde")]
1718 impl Serialize for Invoice {
1719 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
1720 serializer.serialize_str(self.to_string().as_str())
1723 #[cfg(feature = "serde")]
1724 impl<'de> Deserialize<'de> for Invoice {
1725 fn deserialize<D>(deserializer: D) -> Result<Invoice, D::Error> where D: Deserializer<'de> {
1726 let bolt11 = String::deserialize(deserializer)?
1728 .map_err(|e| D::Error::custom(alloc::format!("{:?}", e)))?;
1736 use bitcoin::Script;
1737 use bitcoin_hashes::hex::FromHex;
1738 use bitcoin_hashes::sha256;
1741 fn test_system_time_bounds_assumptions() {
1743 crate::PositiveTimestamp::from_unix_timestamp(crate::MAX_TIMESTAMP + 1),
1744 Err(crate::CreationError::TimestampOutOfBounds)
1749 fn test_calc_invoice_hash() {
1750 use crate::{RawInvoice, RawHrp, RawDataPart, Currency, PositiveTimestamp};
1751 use crate::TaggedField::*;
1753 let invoice = RawInvoice {
1755 currency: Currency::Bitcoin,
1760 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1761 tagged_fields: vec![
1762 PaymentHash(crate::Sha256(sha256::Hash::from_hex(
1763 "0001020304050607080900010203040506070809000102030405060708090102"
1764 ).unwrap())).into(),
1765 Description(crate::Description::new(
1766 "Please consider supporting this project".to_owned()
1772 let expected_hash = [
1773 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d,
1774 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec,
1775 0xd5, 0x18, 0xe1, 0xc9
1778 assert_eq!(invoice.signable_hash(), expected_hash)
1782 fn test_check_signature() {
1783 use crate::TaggedField::*;
1784 use secp256k1::Secp256k1;
1785 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
1786 use secp256k1::{SecretKey, PublicKey};
1787 use crate::{SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
1790 let invoice = SignedRawInvoice {
1791 raw_invoice: RawInvoice {
1793 currency: Currency::Bitcoin,
1798 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1799 tagged_fields: vec ! [
1800 PaymentHash(Sha256(sha256::Hash::from_hex(
1801 "0001020304050607080900010203040506070809000102030405060708090102"
1802 ).unwrap())).into(),
1804 crate::Description::new(
1805 "Please consider supporting this project".to_owned()
1812 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27,
1813 0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7,
1814 0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9
1816 signature: InvoiceSignature(RecoverableSignature::from_compact(
1818 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
1819 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
1820 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f,
1821 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad,
1822 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9,
1823 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f
1825 RecoveryId::from_i32(0).unwrap()
1829 assert!(invoice.check_signature());
1831 let private_key = SecretKey::from_slice(
1833 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2,
1834 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca,
1835 0x3b, 0x2d, 0xb7, 0x34
1838 let public_key = PublicKey::from_secret_key(&Secp256k1::new(), &private_key);
1840 assert_eq!(invoice.recover_payee_pub_key(), Ok(crate::PayeePubKey(public_key)));
1842 let (raw_invoice, _, _) = invoice.into_parts();
1843 let new_signed = raw_invoice.sign::<_, ()>(|hash| {
1844 Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))
1847 assert!(new_signed.check_signature());
1851 fn test_check_feature_bits() {
1852 use crate::TaggedField::*;
1853 use lightning::ln::features::InvoiceFeatures;
1854 use secp256k1::Secp256k1;
1855 use secp256k1::SecretKey;
1856 use crate::{RawInvoice, RawHrp, RawDataPart, Currency, Sha256, PositiveTimestamp, Invoice,
1859 let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
1860 let payment_secret = lightning::ln::PaymentSecret([21; 32]);
1861 let invoice_template = RawInvoice {
1863 currency: Currency::Bitcoin,
1868 timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1869 tagged_fields: vec ! [
1870 PaymentHash(Sha256(sha256::Hash::from_hex(
1871 "0001020304050607080900010203040506070809000102030405060708090102"
1872 ).unwrap())).into(),
1874 crate::Description::new(
1875 "Please consider supporting this project".to_owned()
1884 let mut invoice = invoice_template.clone();
1885 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1886 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1888 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::InvalidFeatures));
1890 // Missing feature bits
1892 let mut invoice = invoice_template.clone();
1893 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1894 invoice.data.tagged_fields.push(Features(InvoiceFeatures::empty()).into());
1895 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1897 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::InvalidFeatures));
1899 let mut payment_secret_features = InvoiceFeatures::empty();
1900 payment_secret_features.set_payment_secret_required();
1902 // Including payment secret and feature bits
1904 let mut invoice = invoice_template.clone();
1905 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1906 invoice.data.tagged_fields.push(Features(payment_secret_features.clone()).into());
1907 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1909 assert!(Invoice::from_signed(invoice).is_ok());
1911 // No payment secret or features
1913 let invoice = invoice_template.clone();
1914 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1916 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1918 // No payment secret or feature bits
1920 let mut invoice = invoice_template.clone();
1921 invoice.data.tagged_fields.push(Features(InvoiceFeatures::empty()).into());
1922 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1924 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1926 // Missing payment secret
1928 let mut invoice = invoice_template.clone();
1929 invoice.data.tagged_fields.push(Features(payment_secret_features).into());
1930 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1932 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::NoPaymentSecret));
1934 // Multiple payment secrets
1936 let mut invoice = invoice_template;
1937 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1938 invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
1939 invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
1941 assert_eq!(Invoice::from_signed(invoice), Err(SemanticError::MultiplePaymentSecrets));
1945 fn test_builder_amount() {
1948 let builder = InvoiceBuilder::new(Currency::Bitcoin)
1949 .description("Test".into())
1950 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1951 .duration_since_epoch(Duration::from_secs(1234567));
1953 let invoice = builder.clone()
1954 .amount_milli_satoshis(1500)
1958 assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Nano));
1959 assert_eq!(invoice.hrp.raw_amount, Some(15));
1962 let invoice = builder
1963 .amount_milli_satoshis(150)
1967 assert_eq!(invoice.hrp.si_prefix, Some(SiPrefix::Pico));
1968 assert_eq!(invoice.hrp.raw_amount, Some(1500));
1972 fn test_builder_fail() {
1974 use lightning::routing::router::RouteHintHop;
1975 use std::iter::FromIterator;
1976 use secp256k1::PublicKey;
1978 let builder = InvoiceBuilder::new(Currency::Bitcoin)
1979 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1980 .duration_since_epoch(Duration::from_secs(1234567))
1981 .min_final_cltv_expiry_delta(144);
1983 let too_long_string = String::from_iter(
1984 (0..1024).map(|_| '?')
1987 let long_desc_res = builder.clone()
1988 .description(too_long_string)
1990 assert_eq!(long_desc_res, Err(CreationError::DescriptionTooLong));
1992 let route_hop = RouteHintHop {
1993 src_node_id: PublicKey::from_slice(
1995 0x03, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4,
1996 0x3c, 0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a,
1997 0x95, 0xc3, 0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
2000 short_channel_id: 0,
2003 proportional_millionths: 0,
2005 cltv_expiry_delta: 0,
2006 htlc_minimum_msat: None,
2007 htlc_maximum_msat: None,
2009 let too_long_route = RouteHint(vec![route_hop; 13]);
2010 let long_route_res = builder.clone()
2011 .description("Test".into())
2012 .private_route(too_long_route)
2014 assert_eq!(long_route_res, Err(CreationError::RouteTooLong));
2016 let sign_error_res = builder
2017 .description("Test".into())
2018 .payment_secret(PaymentSecret([0; 32]))
2019 .try_build_signed(|_| {
2020 Err("ImaginaryError")
2022 assert_eq!(sign_error_res, Err(SignOrCreationError::SignError("ImaginaryError")));
2026 fn test_builder_ok() {
2028 use lightning::routing::router::RouteHintHop;
2029 use secp256k1::Secp256k1;
2030 use secp256k1::{SecretKey, PublicKey};
2031 use std::time::{UNIX_EPOCH, Duration};
2033 let secp_ctx = Secp256k1::new();
2035 let private_key = SecretKey::from_slice(
2037 0xe1, 0x26, 0xf6, 0x8f, 0x7e, 0xaf, 0xcc, 0x8b, 0x74, 0xf5, 0x4d, 0x26, 0x9f, 0xe2,
2038 0x06, 0xbe, 0x71, 0x50, 0x00, 0xf9, 0x4d, 0xac, 0x06, 0x7d, 0x1c, 0x04, 0xa8, 0xca,
2039 0x3b, 0x2d, 0xb7, 0x34
2042 let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key);
2044 let route_1 = RouteHint(vec![
2046 src_node_id: public_key,
2047 short_channel_id: de::parse_int_be(&[123; 8], 256).expect("short chan ID slice too big?"),
2050 proportional_millionths: 1,
2052 cltv_expiry_delta: 145,
2053 htlc_minimum_msat: None,
2054 htlc_maximum_msat: None,
2057 src_node_id: public_key,
2058 short_channel_id: de::parse_int_be(&[42; 8], 256).expect("short chan ID slice too big?"),
2061 proportional_millionths: 2,
2063 cltv_expiry_delta: 146,
2064 htlc_minimum_msat: None,
2065 htlc_maximum_msat: None,
2069 let route_2 = RouteHint(vec![
2071 src_node_id: public_key,
2072 short_channel_id: 0,
2075 proportional_millionths: 3,
2077 cltv_expiry_delta: 147,
2078 htlc_minimum_msat: None,
2079 htlc_maximum_msat: None,
2082 src_node_id: public_key,
2083 short_channel_id: de::parse_int_be(&[1; 8], 256).expect("short chan ID slice too big?"),
2086 proportional_millionths: 4,
2088 cltv_expiry_delta: 148,
2089 htlc_minimum_msat: None,
2090 htlc_maximum_msat: None,
2094 let builder = InvoiceBuilder::new(Currency::BitcoinTestnet)
2095 .amount_milli_satoshis(123)
2096 .duration_since_epoch(Duration::from_secs(1234567))
2097 .payee_pub_key(public_key)
2098 .expiry_time(Duration::from_secs(54321))
2099 .min_final_cltv_expiry_delta(144)
2100 .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap()))
2101 .private_route(route_1.clone())
2102 .private_route(route_2.clone())
2103 .description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap())
2104 .payment_hash(sha256::Hash::from_slice(&[21;32][..]).unwrap())
2105 .payment_secret(PaymentSecret([42; 32]))
2108 let invoice = builder.clone().build_signed(|hash| {
2109 secp_ctx.sign_ecdsa_recoverable(hash, &private_key)
2112 assert!(invoice.check_signature().is_ok());
2113 assert_eq!(invoice.tagged_fields().count(), 10);
2115 assert_eq!(invoice.amount_milli_satoshis(), Some(123));
2116 assert_eq!(invoice.amount_pico_btc(), Some(1230));
2117 assert_eq!(invoice.currency(), Currency::BitcoinTestnet);
2118 #[cfg(feature = "std")]
2120 invoice.timestamp().duration_since(UNIX_EPOCH).unwrap().as_secs(),
2123 assert_eq!(invoice.payee_pub_key(), Some(&public_key));
2124 assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
2125 assert_eq!(invoice.min_final_cltv_expiry_delta(), 144);
2126 assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())]);
2127 let address = Address::from_script(&Script::new_p2pkh(&PubkeyHash::from_slice(&[0;20]).unwrap()), Network::Testnet).unwrap();
2128 assert_eq!(invoice.fallback_addresses(), vec![address]);
2129 assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]);
2131 invoice.description(),
2132 InvoiceDescription::Hash(&Sha256(sha256::Hash::from_slice(&[3;32][..]).unwrap()))
2134 assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&[21;32][..]).unwrap());
2135 assert_eq!(invoice.payment_secret(), &PaymentSecret([42; 32]));
2137 let mut expected_features = InvoiceFeatures::empty();
2138 expected_features.set_variable_length_onion_required();
2139 expected_features.set_payment_secret_required();
2140 expected_features.set_basic_mpp_optional();
2141 assert_eq!(invoice.features(), Some(&expected_features));
2143 let raw_invoice = builder.build_raw().unwrap();
2144 assert_eq!(raw_invoice, *invoice.into_signed_raw().raw_invoice())
2148 fn test_default_values() {
2150 use secp256k1::Secp256k1;
2151 use secp256k1::SecretKey;
2153 let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
2154 .description("Test".into())
2155 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
2156 .payment_secret(PaymentSecret([0; 32]))
2157 .duration_since_epoch(Duration::from_secs(1234567))
2160 .sign::<_, ()>(|hash| {
2161 let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
2162 let secp_ctx = Secp256k1::new();
2163 Ok(secp_ctx.sign_ecdsa_recoverable(hash, &privkey))
2166 let invoice = Invoice::from_signed(signed_invoice).unwrap();
2168 assert_eq!(invoice.min_final_cltv_expiry_delta(), DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA);
2169 assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
2170 assert!(!invoice.would_expire(Duration::from_secs(1234568)));
2174 fn test_expiration() {
2176 use secp256k1::Secp256k1;
2177 use secp256k1::SecretKey;
2179 let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
2180 .description("Test".into())
2181 .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
2182 .payment_secret(PaymentSecret([0; 32]))
2183 .duration_since_epoch(Duration::from_secs(1234567))
2186 .sign::<_, ()>(|hash| {
2187 let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
2188 let secp_ctx = Secp256k1::new();
2189 Ok(secp_ctx.sign_ecdsa_recoverable(hash, &privkey))
2192 let invoice = Invoice::from_signed(signed_invoice).unwrap();
2194 assert!(invoice.would_expire(Duration::from_secs(1234567 + DEFAULT_EXPIRY_TIME + 1)));
2197 #[cfg(feature = "serde")]
2200 let invoice_str = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
2201 h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
2202 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
2203 h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
2204 j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
2205 ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
2206 guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
2207 ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
2208 p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
2209 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
2210 j5r6drg6k6zcqj0fcwg";
2211 let invoice = invoice_str.parse::<super::Invoice>().unwrap();
2212 let serialized_invoice = serde_json::to_string(&invoice).unwrap();
2213 let deserialized_invoice: super::Invoice = serde_json::from_str(serialized_invoice.as_str()).unwrap();
2214 assert_eq!(invoice, deserialized_invoice);
2215 assert_eq!(invoice_str, deserialized_invoice.to_string().as_str());
2216 assert_eq!(invoice_str, serialized_invoice.as_str().trim_matches('\"'));