/// SHA-256 hash
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
-pub struct Sha256(pub sha256::Hash);
+pub struct Sha256(/// (C-not exported) as the native hash types are not currently mapped
+ pub sha256::Hash);
/// Description string
///
.unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
}
+ /// Returns whether the invoice has expired.
+ pub fn is_expired(&self) -> bool {
+ Self::is_expired_from_epoch(self.timestamp(), self.expiry_time())
+ }
+
+ /// Returns whether the expiry time from the given epoch has passed.
+ pub(crate) fn is_expired_from_epoch(epoch: &SystemTime, expiry_time: Duration) -> bool {
+ match epoch.elapsed() {
+ Ok(elapsed) => elapsed > expiry_time,
+ Err(_) => false,
+ }
+ }
+
/// 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 {
/// The supplied expiry time could cause an overflow if added to a `PositiveTimestamp`
ExpiryTimeOutOfBounds,
+
+ /// The supplied millisatoshi amount was greater than the total bitcoin supply.
+ InvalidAmount,
}
impl Display for CreationError {
CreationError::RouteTooLong => f.write_str("The specified route has too many hops and can't be encoded"),
CreationError::TimestampOutOfBounds => f.write_str("The unix timestamp of the supplied date is <0 or can't be represented as `SystemTime`"),
CreationError::ExpiryTimeOutOfBounds => f.write_str("The supplied expiry time could cause an overflow if added to a `PositiveTimestamp`"),
+ CreationError::InvalidAmount => f.write_str("The supplied millisatoshi amount was greater than the total bitcoin supply"),
}
}
}
assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
+ assert!(!invoice.is_expired());
+ }
+
+ #[test]
+ fn test_expiration() {
+ use ::*;
+ use secp256k1::Secp256k1;
+ use secp256k1::key::SecretKey;
+
+ let timestamp = SystemTime::now()
+ .checked_sub(Duration::from_secs(DEFAULT_EXPIRY_TIME * 2))
+ .unwrap();
+ let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
+ .description("Test".into())
+ .payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
+ .payment_secret(PaymentSecret([0; 32]))
+ .timestamp(timestamp)
+ .build_raw()
+ .unwrap()
+ .sign::<_, ()>(|hash| {
+ let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
+ let secp_ctx = Secp256k1::new();
+ Ok(secp_ctx.sign_recoverable(hash, &privkey))
+ })
+ .unwrap();
+ let invoice = Invoice::from_signed(signed_invoice).unwrap();
+
+ assert!(invoice.is_expired());
}
}