Make separate no-std version for invoice response
authorJeffrey Czyz <jkczyz@gmail.com>
Tue, 31 Jan 2023 20:35:49 +0000 (14:35 -0600)
committerJeffrey Czyz <jkczyz@gmail.com>
Fri, 3 Feb 2023 21:23:33 +0000 (15:23 -0600)
Both Refund::respond_with and InvoiceRequest::respond_with take a
created_at since the Unix epoch Duration in no-std. However, this can
cause problems if two downstream dependencies want to use the lightning
crate with different feature flags set. Instead, define
respond_with_no_std versions of each method in addition to a
respond_with version in std.

lightning/src/offers/invoice.rs
lightning/src/offers/invoice_request.rs
lightning/src/offers/refund.rs

index f82544913ed791753b224045490c30e3187b8a7a..66642dec7b2d30a6dc04643bcc19bea0c49838e8 100644 (file)
@@ -49,7 +49,7 @@
     .respond_with(payment_paths, payment_hash)?
 ")]
 #![cfg_attr(not(feature = "std"), doc = "
-    .respond_with(payment_paths, payment_hash, core::time::Duration::from_secs(0))?
+    .respond_with_no_std(payment_paths, payment_hash, core::time::Duration::from_secs(0))?
 ")]
 //!     .relative_expiry(3600)
 //!     .allow_mpp()
@@ -78,7 +78,7 @@
     .respond_with(payment_paths, payment_hash, pubkey)?
 ")]
 #![cfg_attr(not(feature = "std"), doc = "
-    .respond_with(payment_paths, payment_hash, pubkey, core::time::Duration::from_secs(0))?
+    .respond_with_no_std(payment_paths, payment_hash, pubkey, core::time::Duration::from_secs(0))?
 ")]
 //!     .relative_expiry(3600)
 //!     .allow_mpp()
@@ -886,7 +886,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths.clone(), payment_hash, now).unwrap()
+                       .respond_with_no_std(payment_paths.clone(), payment_hash, now).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -962,7 +962,8 @@ mod tests {
                let now = now();
                let invoice = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .build().unwrap()
-                       .respond_with(payment_paths.clone(), payment_hash, recipient_pubkey(), now).unwrap()
+                       .respond_with_no_std(payment_paths.clone(), payment_hash, recipient_pubkey(), now)
+                       .unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1040,7 +1041,8 @@ mod tests {
                if let Err(e) = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .absolute_expiry(future_expiry)
                        .build().unwrap()
-                       .respond_with(payment_paths(), payment_hash(), recipient_pubkey(), now()).unwrap()
+                       .respond_with(payment_paths(), payment_hash(), recipient_pubkey())
+                       .unwrap()
                        .build()
                {
                        panic!("error building invoice: {:?}", e);
@@ -1049,7 +1051,8 @@ mod tests {
                match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .absolute_expiry(past_expiry)
                        .build().unwrap()
-                       .respond_with(payment_paths(), payment_hash(), recipient_pubkey(), now()).unwrap()
+                       .respond_with(payment_paths(), payment_hash(), recipient_pubkey())
+                       .unwrap()
                        .build()
                {
                        Ok(_) => panic!("expected error"),
@@ -1068,7 +1071,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now).unwrap()
                        .relative_expiry(one_hour.as_secs() as u32)
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
@@ -1084,7 +1087,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now - one_hour).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now - one_hour).unwrap()
                        .relative_expiry(one_hour.as_secs() as u32 - 1)
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
@@ -1104,7 +1107,7 @@ mod tests {
                        .amount_msats(1001).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
                let (_, _, _, tlv_stream, _) = invoice.as_tlv_stream();
@@ -1125,7 +1128,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .fallback_v0_p2wsh(&script.wscript_hash())
                        .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap())
                        .fallback_v1_p2tr_tweaked(&tweaked_pubkey)
@@ -1170,7 +1173,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .allow_mpp()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
@@ -1187,7 +1190,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(|_| Err(()))
                {
@@ -1201,7 +1204,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign)
                {
@@ -1218,7 +1221,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1273,7 +1276,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1303,7 +1306,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .relative_expiry(3600)
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
@@ -1325,7 +1328,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1355,7 +1358,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1383,7 +1386,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .allow_mpp()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
@@ -1416,7 +1419,7 @@ mod tests {
                        .build().unwrap()
                        .sign(payer_sign).unwrap();
                let mut unsigned_invoice = invoice_request
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .fallback_v0_p2wsh(&script.wscript_hash())
                        .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap())
                        .fallback_v1_p2tr_tweaked(&tweaked_pubkey)
@@ -1473,7 +1476,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
@@ -1515,7 +1518,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .invoice
                        .write(&mut buffer).unwrap();
@@ -1534,7 +1537,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
                let last_signature_byte = invoice.bytes.last_mut().unwrap();
@@ -1559,7 +1562,7 @@ mod tests {
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build().unwrap()
                        .sign(payer_sign).unwrap()
-                       .respond_with(payment_paths(), payment_hash(), now()).unwrap()
+                       .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
                        .build().unwrap()
                        .sign(recipient_sign).unwrap();
 
index 5b15704ca5127f413a0a26f3958ada9899f6c3fc..b0a8540b2a70a28409547f49d5926adbfe73e941 100644 (file)
@@ -322,12 +322,30 @@ impl InvoiceRequest {
                self.signature
        }
 
+       /// Creates an [`Invoice`] for the request with the given required fields and using the
+       /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
+       ///
+       /// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
+       /// creation time is used for the `created_at` parameter.
+       ///
+       /// [`Invoice`]: crate::offers::invoice::Invoice
+       /// [`Duration`]: core::time::Duration
+       #[cfg(feature = "std")]
+       pub fn respond_with(
+               &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash
+       ) -> Result<InvoiceBuilder, SemanticError> {
+               let created_at = std::time::SystemTime::now()
+                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
+                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
+
+               self.respond_with_no_std(payment_paths, payment_hash, created_at)
+       }
+
        /// Creates an [`Invoice`] for the request with the given required fields.
        ///
        /// Unless [`InvoiceBuilder::relative_expiry`] is set, the invoice will expire two hours after
-       /// calling this method in `std` builds. For `no-std` builds, a final [`Duration`] parameter
-       /// must be given, which is used to set [`Invoice::created_at`] since [`std::time::SystemTime`]
-       /// is not available.
+       /// `created_at`, which is used to set [`Invoice::created_at`]. Useful for `no-std` builds where
+       /// [`std::time::SystemTime`] is not available.
        ///
        /// The caller is expected to remember the preimage of `payment_hash` in order to claim a payment
        /// for the invoice.
@@ -339,23 +357,16 @@ impl InvoiceRequest {
        ///
        /// Errors if the request contains unknown required features.
        ///
-       /// [`Duration`]: core::time::Duration
        /// [`Invoice`]: crate::offers::invoice::Invoice
        /// [`Invoice::created_at`]: crate::offers::invoice::Invoice::created_at
-       pub fn respond_with(
+       pub fn respond_with_no_std(
                &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
-               #[cfg(any(test, not(feature = "std")))]
                created_at: core::time::Duration
        ) -> Result<InvoiceBuilder, SemanticError> {
                if self.features().requires_unknown_bits() {
                        return Err(SemanticError::UnknownRequiredFeatures);
                }
 
-               #[cfg(all(not(test), feature = "std"))]
-               let created_at = std::time::SystemTime::now()
-                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
-                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
-
                InvoiceBuilder::for_offer(self, payment_paths, created_at, payment_hash)
        }
 
index fff33873954a6f92ab55ad2de8d326447dafd0ac..d64f19db06a9c479f583975283577d0cbbde38b5 100644 (file)
@@ -317,12 +317,31 @@ impl Refund {
                self.contents.payer_note.as_ref().map(|payer_note| PrintableString(payer_note.as_str()))
        }
 
+       /// Creates an [`Invoice`] for the refund with the given required fields and using the
+       /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
+       ///
+       /// See [`Refund::respond_with_no_std`] for further details where the aforementioned creation
+       /// time is used for the `created_at` parameter.
+       ///
+       /// [`Invoice`]: crate::offers::invoice::Invoice
+       /// [`Duration`]: core::time::Duration
+       #[cfg(feature = "std")]
+       pub fn respond_with(
+               &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
+               signing_pubkey: PublicKey,
+       ) -> Result<InvoiceBuilder, SemanticError> {
+               let created_at = std::time::SystemTime::now()
+                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
+                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
+
+               self.respond_with_no_std(payment_paths, payment_hash, signing_pubkey, created_at)
+       }
+
        /// Creates an [`Invoice`] for the refund with the given required fields.
        ///
        /// Unless [`InvoiceBuilder::relative_expiry`] is set, the invoice will expire two hours after
-       /// calling this method in `std` builds. For `no-std` builds, a final [`Duration`] parameter
-       /// must be given, which is used to set [`Invoice::created_at`] since [`std::time::SystemTime`]
-       /// is not available.
+       /// `created_at`, which is used to set [`Invoice::created_at`]. Useful for `no-std` builds where
+       /// [`std::time::SystemTime`] is not available.
        ///
        /// The caller is expected to remember the preimage of `payment_hash` in order to
        /// claim a payment for the invoice.
@@ -339,21 +358,14 @@ impl Refund {
        ///
        /// [`Invoice`]: crate::offers::invoice::Invoice
        /// [`Invoice::created_at`]: crate::offers::invoice::Invoice::created_at
-       pub fn respond_with(
+       pub fn respond_with_no_std(
                &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
-               signing_pubkey: PublicKey,
-               #[cfg(any(test, not(feature = "std")))]
-               created_at: Duration
+               signing_pubkey: PublicKey, created_at: Duration
        ) -> Result<InvoiceBuilder, SemanticError> {
                if self.features().requires_unknown_bits() {
                        return Err(SemanticError::UnknownRequiredFeatures);
                }
 
-               #[cfg(all(not(test), feature = "std"))]
-               let created_at = std::time::SystemTime::now()
-                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
-                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
-
                InvoiceBuilder::for_refund(self, payment_paths, created_at, payment_hash, signing_pubkey)
        }