Fix compiling lightning-invoice for no-std + serde
[rust-lightning] / lightning-invoice / src / lib.rs
index c01dfa47ba0b086f8de39691de88df06ce3f2e91..8426db37c6481e03c16ea50f921d29634a47ec0b 100644 (file)
 //! invoices and functions to create, encode and decode these. If you just want to use the standard
 //! en-/decoding functionality this should get you started:
 //!
-//!   * For parsing use `str::parse::<Invoice>(&self)` (see the docs of `impl FromStr for Invoice`)
-//!   * For constructing invoices use the `InvoiceBuilder`
-//!   * For serializing invoices use the `Display`/`ToString` traits
+//!   * For parsing use `str::parse::<Invoice>(&self)` (see [`Invoice::from_str`])
+//!   * For constructing invoices use the [`InvoiceBuilder`]
+//!   * For serializing invoices use the [`Display`]/[`ToString`] traits
+//!
+//! [`Invoice::from_str`]: crate::Invoice#impl-FromStr
 
 #[cfg(not(any(feature = "std", feature = "no-std")))]
 compile_error!("at least one of the `std` or `no-std` features must be enabled");
@@ -45,8 +47,9 @@ extern crate serde;
 use std::time::SystemTime;
 
 use bech32::u5;
-use bitcoin_hashes::Hash;
-use bitcoin_hashes::sha256;
+use bitcoin::{Address, Network, PubkeyHash, ScriptHash};
+use bitcoin::util::address::{Payload, WitnessVersion};
+use bitcoin_hashes::{Hash, sha256};
 use lightning::ln::PaymentSecret;
 use lightning::ln::features::InvoiceFeatures;
 #[cfg(any(doc, test))]
@@ -154,13 +157,13 @@ pub const DEFAULT_EXPIRY_TIME: u64 = 3600;
 /// Default minimum final CLTV expiry as defined by [BOLT 11].
 ///
 /// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
-/// provided in [`MIN_FINAL_CLTV_EXPIRY`].
+/// provided in [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
 ///
 /// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
-/// [`MIN_FINAL_CLTV_EXPIRY`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY
-pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
+/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
+pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
 
-/// Builder for `Invoice`s. It's the most convenient and advised way to use this library. It ensures
+/// Builder for [`Invoice`]s. It's the most convenient and advised way to use this library. It ensures
 /// that only a semantically and syntactically correct Invoice can be built using it.
 ///
 /// ```
@@ -199,7 +202,7 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
 ///    .payment_hash(payment_hash)
 ///    .payment_secret(payment_secret)
 ///    .current_timestamp()
-///    .min_final_cltv_expiry(144)
+///    .min_final_cltv_expiry_delta(144)
 ///    .build_signed(|hash| {
 ///            Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)
 ///    })
@@ -212,11 +215,11 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = 18;
 /// # Type parameters
 /// The two parameters `D` and `H` signal if the builder already contains the correct amount of the
 /// given field:
-///  * `D`: exactly one `Description` or `DescriptionHash`
-///  * `H`: exactly one `PaymentHash`
+///  * `D`: exactly one [`TaggedField::Description`] or [`TaggedField::DescriptionHash`]
+///  * `H`: exactly one [`TaggedField::PaymentHash`]
 ///  * `T`: the timestamp is set
 ///
-/// (C-not exported) as we likely need to manually select one set of boolean type parameters.
+/// This is not exported to bindings users as we likely need to manually select one set of boolean type parameters.
 #[derive(Eq, PartialEq, Debug, Clone)]
 pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> {
        currency: Currency,
@@ -236,9 +239,11 @@ pub struct InvoiceBuilder<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S:
 /// Represents a syntactically and semantically correct lightning BOLT11 invoice.
 ///
 /// There are three ways to construct an `Invoice`:
-///  1. using `InvoiceBuilder`
-///  2. using `Invoice::from_signed(SignedRawInvoice)`
-///  3. using `str::parse::<Invoice>(&str)`
+///  1. using [`InvoiceBuilder`]
+///  2. using [`Invoice::from_signed`]
+///  3. using `str::parse::<Invoice>(&str)` (see [`Invoice::from_str`])
+///
+/// [`Invoice::from_str`]: crate::Invoice#impl-FromStr
 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
 pub struct Invoice {
        signed_invoice: SignedRawInvoice,
@@ -247,7 +252,7 @@ pub struct Invoice {
 /// Represents the description of an invoice which has to be either a directly included string or
 /// a hash of a description provided out of band.
 ///
-/// (C-not exported) As we don't have a good way to map the reference lifetimes making this
+/// This is not exported to bindings users as we don't have a good way to map the reference lifetimes making this
 /// practically impossible to use safely in languages like C.
 #[derive(Eq, PartialEq, Debug, Clone)]
 pub enum InvoiceDescription<'f> {
@@ -258,34 +263,34 @@ pub enum InvoiceDescription<'f> {
        Hash(&'f Sha256),
 }
 
-/// Represents a signed `RawInvoice` with cached hash. The signature is not checked and may be
+/// Represents a signed [`RawInvoice`] with cached hash. The signature is not checked and may be
 /// invalid.
 ///
 /// # Invariants
-/// The hash has to be either from the deserialized invoice or from the serialized `raw_invoice`.
+/// The hash has to be either from the deserialized invoice or from the serialized [`RawInvoice`].
 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
 pub struct SignedRawInvoice {
        /// The rawInvoice that the signature belongs to
        raw_invoice: RawInvoice,
 
-       /// Hash of the `RawInvoice` that will be used to check the signature.
+       /// Hash of the [`RawInvoice`] that will be used to check the signature.
        ///
        /// * if the `SignedRawInvoice` was deserialized the hash is of from the original encoded form,
        /// since it's not guaranteed that encoding it again will lead to the same result since integers
        /// could have been encoded with leading zeroes etc.
        /// * if the `SignedRawInvoice` was constructed manually the hash will be the calculated hash
-       /// from the `RawInvoice`
+       /// from the [`RawInvoice`]
        hash: [u8; 32],
 
        /// signature of the payment request
        signature: InvoiceSignature,
 }
 
-/// Represents an syntactically correct Invoice for a payment on the lightning network,
+/// Represents an syntactically correct [`Invoice`] for a payment on the lightning network,
 /// but without the signature information.
-/// De- and encoding should not lead to information loss but may lead to different hashes.
+/// Decoding and encoding should not lead to information loss but may lead to different hashes.
 ///
-/// For methods without docs see the corresponding methods in `Invoice`.
+/// For methods without docs see the corresponding methods in [`Invoice`].
 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
 pub struct RawInvoice {
        /// human readable part
@@ -295,9 +300,9 @@ pub struct RawInvoice {
        pub data: RawDataPart,
 }
 
-/// Data of the `RawInvoice` that is encoded in the human readable part
+/// Data of the [`RawInvoice`] that is encoded in the human readable part.
 ///
-/// (C-not exported) As we don't yet support `Option<Enum>`
+/// This is not exported to bindings users as we don't yet support `Option<Enum>`
 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
 pub struct RawHrp {
        /// The currency deferred from the 3rd and 4th character of the bech32 transaction
@@ -310,7 +315,7 @@ pub struct RawHrp {
        pub si_prefix: Option<SiPrefix>,
 }
 
-/// Data of the `RawInvoice` that is encoded in the data part
+/// Data of the [`RawInvoice`] that is encoded in the data part
 #[derive(Eq, PartialEq, Debug, Clone, Hash)]
 pub struct RawDataPart {
        /// generation time of the invoice
@@ -357,7 +362,7 @@ impl SiPrefix {
        /// Returns all enum variants of `SiPrefix` sorted in descending order of their associated
        /// multiplier.
        ///
-       /// (C-not exported) As we don't yet support a slice of enums, and also because this function
+       /// This is not exported to bindings users as we don't yet support a slice of enums, and also because this function
        /// isn't the most critical to expose.
        pub fn values_desc() -> &'static [SiPrefix] {
                use crate::SiPrefix::*;
@@ -385,9 +390,32 @@ pub enum Currency {
        Signet,
 }
 
+impl From<Network> for Currency {
+       fn from(network: Network) -> Self {
+               match network {
+                       Network::Bitcoin => Currency::Bitcoin,
+                       Network::Testnet => Currency::BitcoinTestnet,
+                       Network::Regtest => Currency::Regtest,
+                       Network::Signet => Currency::Signet,
+               }
+       }
+}
+
+impl From<Currency> for Network {
+       fn from(currency: Currency) -> Self {
+               match currency {
+                       Currency::Bitcoin => Network::Bitcoin,
+                       Currency::BitcoinTestnet => Network::Testnet,
+                       Currency::Regtest => Network::Regtest,
+                       Currency::Simnet => Network::Regtest,
+                       Currency::Signet => Network::Signet,
+               }
+       }
+}
+
 /// Tagged field which may have an unknown tag
 ///
-/// (C-not exported) as we don't currently support TaggedField
+/// This is not exported to bindings users as we don't currently support TaggedField
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
 pub enum RawTaggedField {
        /// Parsed tagged field with known tag
@@ -400,7 +428,7 @@ pub enum RawTaggedField {
 ///
 /// For descriptions of the enum values please refer to the enclosed type's docs.
 ///
-/// (C-not exported) As we don't yet support enum variants with the same name the struct contained
+/// This is not exported to bindings users as we don't yet support enum variants with the same name the struct contained
 /// in the variant.
 #[allow(missing_docs)]
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
@@ -410,7 +438,7 @@ pub enum TaggedField {
        PayeePubKey(PayeePubKey),
        DescriptionHash(Sha256),
        ExpiryTime(ExpiryTime),
-       MinFinalCltvExpiry(MinFinalCltvExpiry),
+       MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta),
        Fallback(Fallback),
        PrivateRoute(PrivateRoute),
        PaymentSecret(PaymentSecret),
@@ -419,7 +447,7 @@ pub enum TaggedField {
 
 /// SHA-256 hash
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
-pub struct Sha256(/// (C-not exported) as the native hash types are not currently mapped
+pub struct Sha256(/// This is not exported to bindings users as the native hash types are not currently mapped
        pub sha256::Hash);
 
 /// Description string
@@ -438,21 +466,20 @@ pub struct PayeePubKey(pub PublicKey);
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
 pub struct ExpiryTime(Duration);
 
-/// `min_final_cltv_expiry` to use for the last HTLC in the route
+/// `min_final_cltv_expiry_delta` to use for the last HTLC in the route
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
-pub struct MinFinalCltvExpiry(pub u64);
+pub struct MinFinalCltvExpiryDelta(pub u64);
 
-// TODO: better types instead onf byte arrays
 /// Fallback address in case no LN payment is possible
 #[allow(missing_docs)]
 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
 pub enum Fallback {
        SegWitProgram {
-               version: u5,
+               version: WitnessVersion,
                program: Vec<u8>,
        },
-       PubKeyHash([u8; 20]),
-       ScriptHash([u8; 20]),
+       PubKeyHash(PubkeyHash),
+       ScriptHash(ScriptHash),
 }
 
 /// Recoverable signature
@@ -475,7 +502,7 @@ pub mod constants {
        pub const TAG_PAYEE_PUB_KEY: u8 = 19;
        pub const TAG_DESCRIPTION_HASH: u8 = 23;
        pub const TAG_EXPIRY_TIME: u8 = 6;
-       pub const TAG_MIN_FINAL_CLTV_EXPIRY: u8 = 24;
+       pub const TAG_MIN_FINAL_CLTV_EXPIRY_DELTA: u8 = 24;
        pub const TAG_FALLBACK: u8 = 9;
        pub const TAG_PRIVATE_ROUTE: u8 = 3;
        pub const TAG_PAYMENT_SECRET: u8 = 16;
@@ -564,7 +591,8 @@ impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBui
 }
 
 impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb::True, C, S> {
-       /// Builds a `RawInvoice` if no `CreationError` occurred while construction any of the fields.
+       /// Builds a [`RawInvoice`] if no [`CreationError`] occurred while construction any of the
+       /// fields.
        pub fn build_raw(self) -> Result<RawInvoice, CreationError> {
 
                // If an error occurred at any time before, return it now
@@ -585,13 +613,13 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
                }).collect::<Vec<_>>();
 
                let data = RawDataPart {
-                       timestamp: timestamp,
-                       tagged_fields: tagged_fields,
+                       timestamp,
+                       tagged_fields,
                };
 
                Ok(RawInvoice {
-                       hrp: hrp,
-                       data: data,
+                       hrp,
+                       data,
                })
        }
 }
@@ -611,6 +639,18 @@ impl<H: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<tb::Fals
                self.tagged_fields.push(TaggedField::DescriptionHash(Sha256(description_hash)));
                self.set_flags()
        }
+
+       /// Set the description or description hash. This function is only available if no description (hash) was set.
+       pub fn invoice_description(self, description: InvoiceDescription) -> InvoiceBuilder<tb::True, H, T, C, S> {
+               match description {
+                       InvoiceDescription::Direct(desc) => {
+                               self.description(desc.clone().into_inner())
+                       }
+                       InvoiceDescription::Hash(hash) => {
+                               self.description_hash(hash.0)
+                       }
+               }
+       }
 }
 
 impl<D: tb::Bool, T: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, tb::False, T, C, S> {
@@ -654,9 +694,9 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
 }
 
 impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, tb::False, S> {
-       /// Sets `min_final_cltv_expiry`.
-       pub fn min_final_cltv_expiry(mut self, min_final_cltv_expiry: u64) -> InvoiceBuilder<D, H, T, tb::True, S> {
-               self.tagged_fields.push(TaggedField::MinFinalCltvExpiry(MinFinalCltvExpiry(min_final_cltv_expiry)));
+       /// Sets `min_final_cltv_expiry_delta`.
+       pub fn min_final_cltv_expiry_delta(mut self, min_final_cltv_expiry_delta: u64) -> InvoiceBuilder<D, H, T, tb::True, S> {
+               self.tagged_fields.push(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta(min_final_cltv_expiry_delta)));
                self.set_flags()
        }
 }
@@ -741,17 +781,17 @@ impl SignedRawInvoice {
                (self.raw_invoice, self.hash, self.signature)
        }
 
-       /// The `RawInvoice` which was signed.
+       /// The [`RawInvoice`] which was signed.
        pub fn raw_invoice(&self) -> &RawInvoice {
                &self.raw_invoice
        }
 
-       /// The hash of the `RawInvoice` that was signed.
+       /// The hash of the [`RawInvoice`] that was signed.
        pub fn signable_hash(&self) -> &[u8; 32] {
                &self.hash
        }
 
-       /// InvoiceSignature for the invoice.
+       /// Signature for the invoice.
        pub fn signature(&self) -> &InvoiceSignature {
                &self.signature
        }
@@ -781,7 +821,7 @@ impl SignedRawInvoice {
                        recovered_pub_key = Some(recovered);
                }
 
-               let pub_key = included_pub_key.or_else(|| recovered_pub_key.as_ref())
+               let pub_key = included_pub_key.or(recovered_pub_key.as_ref())
                        .expect("One is always present");
 
                let hash = Message::from_slice(&self.hash[..])
@@ -869,11 +909,11 @@ impl RawInvoice {
                )
        }
 
-       /// Signs the invoice using the supplied `sign_function`. This function MAY fail with an error
-       /// of type `E`. Since the signature of a `SignedRawInvoice` is not required to be valid there
+       /// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of
+       /// type `E`. Since the signature of a [`SignedRawInvoice`] is not required to be valid there
        /// are no constraints regarding the validity of the produced signature.
        ///
-       /// (C-not exported) As we don't currently support passing function pointers into methods
+       /// This is not exported to bindings users as we don't currently support passing function pointers into methods
        /// explicitly.
        pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
                where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
@@ -892,7 +932,7 @@ impl RawInvoice {
 
        /// Returns an iterator over all tagged fields with known semantics.
        ///
-       /// (C-not exported) As there is not yet a manual mapping for a FilterMap
+       /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap
        pub fn known_tagged_fields(&self)
                -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>>
        {
@@ -929,8 +969,8 @@ impl RawInvoice {
                find_extract!(self.known_tagged_fields(), TaggedField::ExpiryTime(ref x), x)
        }
 
-       pub fn min_final_cltv_expiry(&self) -> Option<&MinFinalCltvExpiry> {
-               find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiry(ref x), x)
+       pub fn min_final_cltv_expiry_delta(&self) -> Option<&MinFinalCltvExpiryDelta> {
+               find_extract!(self.known_tagged_fields(), TaggedField::MinFinalCltvExpiryDelta(ref x), x)
        }
 
        pub fn payment_secret(&self) -> Option<&PaymentSecret> {
@@ -941,7 +981,7 @@ impl RawInvoice {
                find_extract!(self.known_tagged_fields(), TaggedField::Features(ref x), x)
        }
 
-       /// (C-not exported) as we don't support Vec<&NonOpaqueType>
+       /// This is not exported to bindings users as we don't support Vec<&NonOpaqueType>
        pub fn fallbacks(&self) -> Vec<&Fallback> {
                find_all_extract!(self.known_tagged_fields(), TaggedField::Fallback(ref x), x).collect()
        }
@@ -1014,13 +1054,18 @@ impl PositiveTimestamp {
 }
 
 #[cfg(feature = "std")]
-impl Into<SystemTime> for PositiveTimestamp {
-       fn into(self) -> SystemTime {
-               SystemTime::UNIX_EPOCH + self.0
+impl From<PositiveTimestamp> for SystemTime {
+       fn from(val: PositiveTimestamp) -> Self {
+               SystemTime::UNIX_EPOCH + val.0
        }
 }
 
 impl Invoice {
+       /// The hash of the [`RawInvoice`] that was signed.
+       pub fn signable_hash(&self) -> [u8; 32] {
+               self.signed_invoice.hash
+       }
+
        /// Transform the `Invoice` into it's unchecked version
        pub fn into_signed_raw(self) -> SignedRawInvoice {
                self.signed_invoice
@@ -1125,7 +1170,7 @@ impl Invoice {
                Ok(())
        }
 
-       /// Constructs an `Invoice` from a `SignedRawInvoice` by checking all its invariants.
+       /// Constructs an `Invoice` from a [`SignedRawInvoice`] by checking all its invariants.
        /// ```
        /// use lightning_invoice::*;
        ///
@@ -1147,7 +1192,7 @@ impl Invoice {
        /// ```
        pub fn from_signed(signed_invoice: SignedRawInvoice) -> Result<Self, SemanticError> {
                let invoice = Invoice {
-                       signed_invoice: signed_invoice,
+                       signed_invoice,
                };
                invoice.check_field_counts()?;
                invoice.check_feature_bits()?;
@@ -1170,7 +1215,7 @@ impl Invoice {
 
        /// Returns an iterator over all tagged fields of this Invoice.
        ///
-       /// (C-not exported) As there is not yet a manual mapping for a FilterMap
+       /// This is not exported to bindings users as there is not yet a manual mapping for a FilterMap
        pub fn tagged_fields(&self)
                -> FilterMap<Iter<RawTaggedField>, fn(&RawTaggedField) -> Option<&TaggedField>> {
                self.signed_invoice.raw_invoice().known_tagged_fields()
@@ -1183,11 +1228,11 @@ impl Invoice {
 
        /// Return the description or a hash of it for longer ones
        ///
-       /// (C-not exported) because we don't yet export InvoiceDescription
+       /// This is not exported to bindings users because we don't yet export InvoiceDescription
        pub fn description(&self) -> InvoiceDescription {
-               if let Some(ref direct) = self.signed_invoice.description() {
+               if let Some(direct) = self.signed_invoice.description() {
                        return InvoiceDescription::Direct(direct);
-               } else if let Some(ref hash) = self.signed_invoice.description_hash() {
+               } else if let Some(hash) = self.signed_invoice.description_hash() {
                        return InvoiceDescription::Hash(hash);
                }
                unreachable!("ensured by constructor");
@@ -1213,6 +1258,12 @@ impl Invoice {
                self.signed_invoice.recover_payee_pub_key().expect("was checked by constructor").0
        }
 
+       /// Returns the Duration since the Unix epoch at which the invoice expires.
+       /// Returning None if overflow occurred.
+       pub fn expires_at(&self) -> Option<Duration> {
+               self.duration_since_epoch().checked_add(self.expiry_time())
+       }
+
        /// Returns the invoice's expiry time, if present, otherwise [`DEFAULT_EXPIRY_TIME`].
        pub fn expiry_time(&self) -> Duration {
                self.signed_invoice.expiry_time()
@@ -1235,6 +1286,20 @@ impl Invoice {
                }
        }
 
+       /// Returns the Duration remaining until the invoice expires.
+       #[cfg(feature = "std")]
+       pub fn duration_until_expiry(&self) -> Duration {
+               SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
+                       .map(|now| self.expiration_remaining_from_epoch(now))
+                       .unwrap_or(Duration::from_nanos(0))
+       }
+
+       /// Returns the Duration remaining until the invoice expires given the current time.
+       /// `time` is the timestamp as a duration since the Unix epoch.
+       pub fn expiration_remaining_from_epoch(&self, time: Duration) -> Duration {
+               self.expires_at().map(|x| x.checked_sub(time)).flatten().unwrap_or(Duration::from_nanos(0))
+       }
+
        /// Returns whether the expiry time would pass at the given point in time.
        /// `at_time` is the timestamp as a duration since the Unix epoch.
        pub fn would_expire(&self, at_time: Duration) -> bool {
@@ -1243,21 +1308,40 @@ impl Invoice {
                        .unwrap_or_else(|| Duration::new(u64::max_value(), 1_000_000_000 - 1)) < at_time
        }
 
-       /// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
-       /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
-       pub fn min_final_cltv_expiry(&self) -> u64 {
-               self.signed_invoice.min_final_cltv_expiry()
+       /// Returns the invoice's `min_final_cltv_expiry_delta` time, if present, otherwise
+       /// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA`].
+       pub fn min_final_cltv_expiry_delta(&self) -> u64 {
+               self.signed_invoice.min_final_cltv_expiry_delta()
                        .map(|x| x.0)
-                       .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY)
+                       .unwrap_or(DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA)
        }
 
        /// Returns a list of all fallback addresses
        ///
-       /// (C-not exported) as we don't support Vec<&NonOpaqueType>
+       /// This is not exported to bindings users as we don't support Vec<&NonOpaqueType>
        pub fn fallbacks(&self) -> Vec<&Fallback> {
                self.signed_invoice.fallbacks()
        }
 
+       /// Returns a list of all fallback addresses as [`Address`]es
+       pub fn fallback_addresses(&self) -> Vec<Address> {
+               self.fallbacks().iter().map(|fallback| {
+                       let payload = match fallback {
+                               Fallback::SegWitProgram { version, program } => {
+                                       Payload::WitnessProgram { version: *version, program: program.to_vec() }
+                               }
+                               Fallback::PubKeyHash(pkh) => {
+                                       Payload::PubkeyHash(*pkh)
+                               }
+                               Fallback::ScriptHash(sh) => {
+                                       Payload::ScriptHash(*sh)
+                               }
+                       };
+
+                       Address { payload, network: self.network() }
+               }).collect()
+       }
+
        /// Returns a list of all routes included in the invoice
        pub fn private_routes(&self) -> Vec<&PrivateRoute> {
                self.signed_invoice.private_routes()
@@ -1275,6 +1359,11 @@ impl Invoice {
                self.signed_invoice.currency()
        }
 
+       /// Returns the network for which the invoice was issued
+       pub fn network(&self) -> Network {
+               self.signed_invoice.currency().into()
+       }
+
        /// Returns the amount if specified in the invoice as millisatoshis.
        pub fn amount_milli_satoshis(&self) -> Option<u64> {
                self.signed_invoice.amount_pico_btc().map(|v| v / 10)
@@ -1301,7 +1390,7 @@ impl TaggedField {
                        TaggedField::PayeePubKey(_) => constants::TAG_PAYEE_PUB_KEY,
                        TaggedField::DescriptionHash(_) => constants::TAG_DESCRIPTION_HASH,
                        TaggedField::ExpiryTime(_) => constants::TAG_EXPIRY_TIME,
-                       TaggedField::MinFinalCltvExpiry(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY,
+                       TaggedField::MinFinalCltvExpiryDelta(_) => constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA,
                        TaggedField::Fallback(_) => constants::TAG_FALLBACK,
                        TaggedField::PrivateRoute(_) => constants::TAG_PRIVATE_ROUTE,
                        TaggedField::PaymentSecret(_) => constants::TAG_PAYMENT_SECRET,
@@ -1315,7 +1404,7 @@ impl TaggedField {
 impl Description {
 
        /// Creates a new `Description` if `description` is at most 1023 __bytes__ long,
-       /// returns `CreationError::DescriptionTooLong` otherwise
+       /// returns [`CreationError::DescriptionTooLong`] otherwise
        ///
        /// Please note that single characters may use more than one byte due to UTF8 encoding.
        pub fn new(description: String) -> Result<Description, CreationError> {
@@ -1326,15 +1415,15 @@ impl Description {
                }
        }
 
-       /// Returns the underlying description `String`
+       /// Returns the underlying description [`String`]
        pub fn into_inner(self) -> String {
                self.0
        }
 }
 
-impl Into<String> for Description {
-       fn into(self) -> String {
-               self.into_inner()
+impl From<Description> for String {
+       fn from(val: Description) -> Self {
+               val.into_inner()
        }
 }
 
@@ -1366,7 +1455,7 @@ impl ExpiryTime {
                ExpiryTime(Duration::from_secs(seconds))
        }
 
-       /// Construct an `ExpiryTime` from a `Duration`, dropping the sub-second part.
+       /// Construct an `ExpiryTime` from a [`Duration`], dropping the sub-second part.
        pub fn from_duration(duration: Duration) -> ExpiryTime {
                Self::from_seconds(duration.as_secs())
        }
@@ -1376,7 +1465,7 @@ impl ExpiryTime {
                self.0.as_secs()
        }
 
-       /// Returns a reference to the underlying `Duration` (=expiry time)
+       /// Returns a reference to the underlying [`Duration`] (=expiry time)
        pub fn as_duration(&self) -> &Duration {
                &self.0
        }
@@ -1398,9 +1487,9 @@ impl PrivateRoute {
        }
 }
 
-impl Into<RouteHint> for PrivateRoute {
-       fn into(self) -> RouteHint {
-               self.into_inner()
+impl From<PrivateRoute> for RouteHint {
+       fn from(val: PrivateRoute) -> Self {
+               val.into_inner()
        }
 }
 
@@ -1428,10 +1517,10 @@ impl Deref for SignedRawInvoice {
        }
 }
 
-/// Errors that may occur when constructing a new `RawInvoice` or `Invoice`
+/// Errors that may occur when constructing a new [`RawInvoice`] or [`Invoice`]
 #[derive(Eq, PartialEq, Debug, Clone)]
 pub enum CreationError {
-       /// The supplied description string was longer than 639 __bytes__ (see [`Description::new(…)`](./struct.Description.html#method.new))
+       /// The supplied description string was longer than 639 __bytes__ (see [`Description::new`])
        DescriptionTooLong,
 
        /// The specified route has too many hops and can't be encoded
@@ -1448,6 +1537,11 @@ pub enum CreationError {
        ///
        /// [phantom invoices]: crate::utils::create_phantom_invoice
        MissingRouteHints,
+
+       /// The provided `min_final_cltv_expiry_delta` was less than [`MIN_FINAL_CLTV_EXPIRY_DELTA`].
+       ///
+       /// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA
+       MinFinalCltvExpiryDeltaTooShort,
 }
 
 impl Display for CreationError {
@@ -1458,6 +1552,8 @@ impl Display for CreationError {
                        CreationError::TimestampOutOfBounds => f.write_str("The Unix timestamp of the supplied date is less than zero or greater than 35-bits"),
                        CreationError::InvalidAmount => f.write_str("The supplied millisatoshi amount was greater than the total bitcoin supply"),
                        CreationError::MissingRouteHints => f.write_str("The invoice required route hints and they weren't provided"),
+                       CreationError::MinFinalCltvExpiryDeltaTooShort => f.write_str(
+                               "The supplied final CLTV expiry delta was less than LDK's `MIN_FINAL_CLTV_EXPIRY_DELTA`"),
                }
        }
 }
@@ -1465,7 +1561,7 @@ impl Display for CreationError {
 #[cfg(feature = "std")]
 impl std::error::Error for CreationError { }
 
-/// Errors that may occur when converting a `RawInvoice` to an `Invoice`. They relate to the
+/// Errors that may occur when converting a [`RawInvoice`] to an [`Invoice`]. They relate to the
 /// requirements sections in BOLT #11
 #[derive(Eq, PartialEq, Debug, Clone)]
 pub enum SemanticError {
@@ -1521,7 +1617,7 @@ impl Display for SemanticError {
 #[cfg(feature = "std")]
 impl std::error::Error for SemanticError { }
 
-/// When signing using a fallible method either an user-supplied `SignError` or a `CreationError`
+/// When signing using a fallible method either an user-supplied `SignError` or a [`CreationError`]
 /// may occur.
 #[derive(Eq, PartialEq, Debug, Clone)]
 pub enum SignOrCreationError<S = ()> {
@@ -1552,7 +1648,7 @@ impl<'de> Deserialize<'de> for Invoice {
        fn deserialize<D>(deserializer: D) -> Result<Invoice, D::Error> where D: Deserializer<'de> {
                let bolt11 = String::deserialize(deserializer)?
                        .parse::<Invoice>()
-                       .map_err(|e| D::Error::custom(format!("{:?}", e)))?;
+                       .map_err(|e| D::Error::custom(alloc::format!("{:?}", e)))?;
 
                Ok(bolt11)
        }
@@ -1560,6 +1656,7 @@ impl<'de> Deserialize<'de> for Invoice {
 
 #[cfg(test)]
 mod test {
+       use bitcoin::Script;
        use bitcoin_hashes::hex::FromHex;
        use bitcoin_hashes::sha256;
 
@@ -1759,7 +1856,7 @@ mod test {
 
                // Multiple payment secrets
                let invoice = {
-                       let mut invoice = invoice_template.clone();
+                       let mut invoice = invoice_template;
                        invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
                        invoice.data.tagged_fields.push(PaymentSecret(payment_secret).into());
                        invoice.sign::<_, ()>(|hash| Ok(Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)))
@@ -1785,7 +1882,7 @@ mod test {
                assert_eq!(invoice.hrp.raw_amount, Some(15));
 
 
-               let invoice = builder.clone()
+               let invoice = builder
                        .amount_milli_satoshis(150)
                        .build_raw()
                        .unwrap();
@@ -1804,7 +1901,7 @@ mod test {
                let builder = InvoiceBuilder::new(Currency::Bitcoin)
                        .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
                        .duration_since_epoch(Duration::from_secs(1234567))
-                       .min_final_cltv_expiry(144);
+                       .min_final_cltv_expiry_delta(144);
 
                let too_long_string = String::from_iter(
                        (0..1024).map(|_| '?')
@@ -1839,7 +1936,7 @@ mod test {
                        .build_raw();
                assert_eq!(long_route_res, Err(CreationError::RouteTooLong));
 
-               let sign_error_res = builder.clone()
+               let sign_error_res = builder
                        .description("Test".into())
                        .payment_secret(PaymentSecret([0; 32]))
                        .try_build_signed(|_| {
@@ -1869,7 +1966,7 @@ mod test {
 
                let route_1 = RouteHint(vec![
                        RouteHintHop {
-                               src_node_id: public_key.clone(),
+                               src_node_id: public_key,
                                short_channel_id: de::parse_int_be(&[123; 8], 256).expect("short chan ID slice too big?"),
                                fees: RoutingFees {
                                        base_msat: 2,
@@ -1880,7 +1977,7 @@ mod test {
                                htlc_maximum_msat: None,
                        },
                        RouteHintHop {
-                               src_node_id: public_key.clone(),
+                               src_node_id: public_key,
                                short_channel_id: de::parse_int_be(&[42; 8], 256).expect("short chan ID slice too big?"),
                                fees: RoutingFees {
                                        base_msat: 3,
@@ -1894,7 +1991,7 @@ mod test {
 
                let route_2 = RouteHint(vec![
                        RouteHintHop {
-                               src_node_id: public_key.clone(),
+                               src_node_id: public_key,
                                short_channel_id: 0,
                                fees: RoutingFees {
                                        base_msat: 4,
@@ -1905,7 +2002,7 @@ mod test {
                                htlc_maximum_msat: None,
                        },
                        RouteHintHop {
-                               src_node_id: public_key.clone(),
+                               src_node_id: public_key,
                                short_channel_id: de::parse_int_be(&[1; 8], 256).expect("short chan ID slice too big?"),
                                fees: RoutingFees {
                                        base_msat: 5,
@@ -1920,10 +2017,10 @@ mod test {
                let builder = InvoiceBuilder::new(Currency::BitcoinTestnet)
                        .amount_milli_satoshis(123)
                        .duration_since_epoch(Duration::from_secs(1234567))
-                       .payee_pub_key(public_key.clone())
+                       .payee_pub_key(public_key)
                        .expiry_time(Duration::from_secs(54321))
-                       .min_final_cltv_expiry(144)
-                       .fallback(Fallback::PubKeyHash([0;20]))
+                       .min_final_cltv_expiry_delta(144)
+                       .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap()))
                        .private_route(route_1.clone())
                        .private_route(route_2.clone())
                        .description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap())
@@ -1948,8 +2045,10 @@ mod test {
                );
                assert_eq!(invoice.payee_pub_key(), Some(&public_key));
                assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
-               assert_eq!(invoice.min_final_cltv_expiry(), 144);
-               assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash([0;20])]);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), 144);
+               assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())]);
+               let address = Address::from_script(&Script::new_p2pkh(&PubkeyHash::from_slice(&[0;20]).unwrap()), Network::Testnet).unwrap();
+               assert_eq!(invoice.fallback_addresses(), vec![address]);
                assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]);
                assert_eq!(
                        invoice.description(),
@@ -1989,7 +2088,7 @@ mod test {
                        .unwrap();
                let invoice = Invoice::from_signed(signed_invoice).unwrap();
 
-               assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
+               assert_eq!(invoice.min_final_cltv_expiry_delta(), DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA);
                assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
                assert!(!invoice.would_expire(Duration::from_secs(1234568)));
        }