Pipe the new `RecipientOnionFields` through send pipeline
[rust-lightning] / lightning-invoice / src / lib.rs
index c36aafd8b81bb36815538ec191bdab70da592b4a..593701cab458c85079dff3e135dcebbf63845277 100644 (file)
@@ -216,7 +216,7 @@ pub const DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA: u64 = 18;
 ///  * `H`: exactly one `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,
@@ -247,7 +247,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> {
@@ -297,7 +297,7 @@ pub struct RawInvoice {
 
 /// 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
@@ -357,7 +357,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::*;
@@ -387,7 +387,7 @@ pub enum Currency {
 
 /// 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 +400,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)]
@@ -419,7 +419,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
@@ -585,13 +585,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 +611,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> {
@@ -781,7 +793,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[..])
@@ -873,7 +885,7 @@ impl RawInvoice {
        /// 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 +904,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>>
        {
@@ -941,7 +953,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,9 +1026,9 @@ 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
        }
 }
 
@@ -1147,7 +1159,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 +1182,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 +1195,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 +1225,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 +1253,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 {
@@ -1253,7 +1285,7 @@ impl Invoice {
 
        /// 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()
        }
@@ -1332,9 +1364,9 @@ impl Description {
        }
 }
 
-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()
        }
 }
 
@@ -1398,9 +1430,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()
        }
 }
 
@@ -1448,6 +1480,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 +1495,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`"),
                }
        }
 }
@@ -1759,7 +1798,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 +1824,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();
@@ -1839,7 +1878,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 +1908,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 +1919,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 +1933,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 +1944,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,7 +1959,7 @@ 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_delta(144)
                        .fallback(Fallback::PubKeyHash([0;20]))