Skip to content

Commit 3e905f4

Browse files
committed
Remove std::SystemTime from create_phantom_invoice, ref #1978
Add a no-std timestamp function
1 parent d4de913 commit 3e905f4

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

lightning-invoice/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,13 @@ impl<D: tb::Bool, H: tb::Bool, C: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, tb
651651
self.timestamp = Some(now.expect("for the foreseeable future this shouldn't happen"));
652652
self.set_flags()
653653
}
654+
655+
/// Sets the timestamp to the time supplied by the caller.
656+
pub fn timestamp_no_std(mut self, duration_since_epoch: Duration) -> InvoiceBuilder<D, H, tb::True, C, S> {
657+
let now = PositiveTimestamp::from_duration_since_epoch(duration_since_epoch);
658+
self.timestamp = Some(now.expect("for the foreseeable future this shouldn't happen"));
659+
self.set_flags()
660+
}
654661
}
655662

656663
impl<D: tb::Bool, H: tb::Bool, T: tb::Bool, S: tb::Bool> InvoiceBuilder<D, H, T, tb::False, S> {

lightning-invoice/src/utils.rs

+24-22
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
1111
use lightning::chain::keysinterface::{Recipient, NodeSigner, SignerProvider, EntropySource};
1212
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1313
use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY_DELTA};
14-
#[cfg(feature = "std")]
1514
use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
1615
use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
1716
use lightning::routing::gossip::RoutingFees;
@@ -21,7 +20,6 @@ use secp256k1::PublicKey;
2120
use core::ops::Deref;
2221
use core::time::Duration;
2322

24-
#[cfg(feature = "std")]
2523
/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
2624
/// See [`PhantomKeysManager`] for more information on phantom node payments.
2725
///
@@ -41,6 +39,11 @@ use core::time::Duration;
4139
///
4240
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
4341
/// in excess of the current time.
42+
///
43+
/// 'duration_since_epoch' is the current time since epoch in seconds.
44+
///
45+
/// ['std::time::SystemTime'] has been removed to allow this function to be used in a 'no_std' environment,
46+
/// where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.
4447
///
4548
/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to
4649
/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`] - 3.
@@ -60,7 +63,7 @@ use core::time::Duration;
6063
pub fn create_phantom_invoice<ES: Deref, NS: Deref, L: Deref>(
6164
amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: String,
6265
invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
63-
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>,
66+
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
6467
) -> Result<Invoice, SignOrCreationError<()>>
6568
where
6669
ES::Target: EntropySource,
@@ -71,11 +74,10 @@ where
7174
let description = InvoiceDescription::Direct(&description,);
7275
_create_phantom_invoice::<ES, NS, L>(
7376
amt_msat, payment_hash, description, invoice_expiry_delta_secs, phantom_route_hints,
74-
entropy_source, node_signer, logger, network, min_final_cltv_expiry_delta,
77+
entropy_source, node_signer, logger, network, min_final_cltv_expiry_delta, duration_since_epoch,
7578
)
7679
}
7780

78-
#[cfg(feature = "std")]
7981
/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
8082
/// See [`PhantomKeysManager`] for more information on phantom node payments.
8183
///
@@ -97,6 +99,11 @@ where
9799
///
98100
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
99101
/// in excess of the current time.
102+
///
103+
/// 'duration_since_epoch' is the current time since epoch in seconds.
104+
///
105+
/// ['std::time::SystemTime'] has been removed to allow this function to be used in a 'no_std' environment,
106+
/// where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.
100107
///
101108
/// Note that the provided `keys_manager`'s `NodeSigner` implementation must support phantom
102109
/// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -110,7 +117,7 @@ where
110117
pub fn create_phantom_invoice_with_description_hash<ES: Deref, NS: Deref, L: Deref>(
111118
amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, invoice_expiry_delta_secs: u32,
112119
description_hash: Sha256, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
113-
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>,
120+
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
114121
) -> Result<Invoice, SignOrCreationError<()>>
115122
where
116123
ES::Target: EntropySource,
@@ -120,22 +127,20 @@ where
120127
_create_phantom_invoice::<ES, NS, L>(
121128
amt_msat, payment_hash, InvoiceDescription::Hash(&description_hash),
122129
invoice_expiry_delta_secs, phantom_route_hints, entropy_source, node_signer, logger, network,
123-
min_final_cltv_expiry_delta,
130+
min_final_cltv_expiry_delta, duration_since_epoch,
124131
)
125132
}
126133

127-
#[cfg(feature = "std")]
128134
fn _create_phantom_invoice<ES: Deref, NS: Deref, L: Deref>(
129135
amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: InvoiceDescription,
130136
invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, entropy_source: ES,
131-
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>,
137+
node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option<u16>, duration_since_epoch: Duration,
132138
) -> Result<Invoice, SignOrCreationError<()>>
133139
where
134140
ES::Target: EntropySource,
135141
NS::Target: NodeSigner,
136142
L::Target: Logger,
137143
{
138-
use std::time::{SystemTime, UNIX_EPOCH};
139144

140145
if phantom_route_hints.len() == 0 {
141146
return Err(SignOrCreationError::CreationError(
@@ -162,9 +167,7 @@ where
162167
amt_msat,
163168
payment_hash,
164169
invoice_expiry_delta_secs,
165-
SystemTime::now()
166-
.duration_since(UNIX_EPOCH)
167-
.expect("Time must be > 1970")
170+
duration_since_epoch
168171
.as_secs(),
169172
min_final_cltv_expiry_delta,
170173
)
@@ -176,9 +179,7 @@ where
176179
amt_msat,
177180
invoice_expiry_delta_secs,
178181
&entropy_source,
179-
SystemTime::now()
180-
.duration_since(UNIX_EPOCH)
181-
.expect("Time must be > 1970")
182+
duration_since_epoch
182183
.as_secs(),
183184
min_final_cltv_expiry_delta,
184185
)
@@ -189,7 +190,7 @@ where
189190
phantom_route_hints.len(), log_bytes!(payment_hash.0));
190191

191192
let mut invoice = invoice
192-
.current_timestamp()
193+
.timestamp_no_std(duration_since_epoch)
193194
.payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
194195
.payment_secret(payment_secret)
195196
.min_final_cltv_expiry_delta(
@@ -1072,7 +1073,7 @@ mod test {
10721073
crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>(
10731074
Some(payment_amt), payment_hash, "test".to_string(), non_default_invoice_expiry_secs,
10741075
route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger,
1075-
Currency::BitcoinTestnet, None,
1076+
Currency::BitcoinTestnet, None, Duration::from_secs(1234567)
10761077
).unwrap();
10771078
let (payment_hash, payment_secret) = (PaymentHash(invoice.payment_hash().into_inner()), *invoice.payment_secret());
10781079
let payment_preimage = if user_generated_pmt_hash {
@@ -1182,7 +1183,7 @@ mod test {
11821183
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
11831184
&test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), Some(payment_hash),
11841185
"test".to_string(), 3600, route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager,
1185-
&nodes[1].logger, Currency::BitcoinTestnet, None).unwrap();
1186+
&nodes[1].logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
11861187

11871188
let chan_0_1 = &nodes[1].node.list_usable_channels()[0];
11881189
assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat);
@@ -1214,7 +1215,7 @@ mod test {
12141215
>(
12151216
Some(payment_amt), None, non_default_invoice_expiry_secs, description_hash,
12161217
route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager, &nodes[1].logger,
1217-
Currency::BitcoinTestnet, None,
1218+
Currency::BitcoinTestnet, None, Duration::from_secs(1234567),
12181219
)
12191220
.unwrap();
12201221
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
@@ -1240,10 +1241,11 @@ mod test {
12401241
let payment_hash = Some(PaymentHash(Sha256::hash(&user_payment_preimage.0[..]).into_inner()));
12411242
let non_default_invoice_expiry_secs = 4200;
12421243
let min_final_cltv_expiry_delta = Some(100);
1244+
let duration_since_epoch = Duration::from_secs(1234567);
12431245
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
12441246
&test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), payment_hash,
12451247
"".to_string(), non_default_invoice_expiry_secs, route_hints, &nodes[1].keys_manager, &nodes[1].keys_manager,
1246-
&nodes[1].logger, Currency::BitcoinTestnet, min_final_cltv_expiry_delta).unwrap();
1248+
&nodes[1].logger, Currency::BitcoinTestnet, min_final_cltv_expiry_delta, duration_since_epoch).unwrap();
12471249
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
12481250
assert_eq!(invoice.min_final_cltv_expiry_delta(), (min_final_cltv_expiry_delta.unwrap() + 3) as u64);
12491251
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
@@ -1557,7 +1559,7 @@ mod test {
15571559
let invoice = crate::utils::create_phantom_invoice::<&test_utils::TestKeysInterface,
15581560
&test_utils::TestKeysInterface, &test_utils::TestLogger>(invoice_amt, None, "test".to_string(),
15591561
3600, phantom_route_hints, &invoice_node.keys_manager, &invoice_node.keys_manager,
1560-
&invoice_node.logger, Currency::BitcoinTestnet, None).unwrap();
1562+
&invoice_node.logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap();
15611563

15621564
let invoice_hints = invoice.private_routes();
15631565

0 commit comments

Comments
 (0)