Skip to content

Commit 4fd4815

Browse files
authored
Merge branch 'lightningdevkit:main' into issue1462
2 parents 071719e + b5a6307 commit 4fd4815

File tree

11 files changed

+794
-449
lines changed

11 files changed

+794
-449
lines changed

lightning-invoice/src/payment.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,7 @@ mod tests {
15581558

15591559
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
15601560
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1561-
duration_since_epoch()).unwrap())
1561+
duration_since_epoch(), 3600).unwrap())
15621562
.is_ok());
15631563
let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
15641564
assert_eq!(htlc_msgs.len(), 2);
@@ -1604,7 +1604,7 @@ mod tests {
16041604

16051605
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
16061606
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1607-
duration_since_epoch()).unwrap())
1607+
duration_since_epoch(), 3600).unwrap())
16081608
.is_ok());
16091609
let htlc_msgs = nodes[0].node.get_and_clear_pending_msg_events();
16101610
assert_eq!(htlc_msgs.len(), 2);
@@ -1686,7 +1686,7 @@ mod tests {
16861686

16871687
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
16881688
&nodes[1].node, nodes[1].keys_manager, Currency::Bitcoin, Some(100_010_000), "Invoice".to_string(),
1689-
duration_since_epoch()).unwrap())
1689+
duration_since_epoch(), 3600).unwrap())
16901690
.is_ok());
16911691
let htlc_updates = SendEvent::from_node(&nodes[0]);
16921692
check_added_monitors!(nodes[0], 1);

lightning-invoice/src/utils.rs

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Convenient utilities to create an invoice.
22
3-
use {CreationError, Currency, DEFAULT_EXPIRY_TIME, Invoice, InvoiceBuilder, SignOrCreationError};
3+
use {CreationError, Currency, Invoice, InvoiceBuilder, SignOrCreationError};
44
use payment::{Payer, Router};
55

66
use crate::{prelude::*, Description, InvoiceDescription, Sha256};
@@ -20,7 +20,6 @@ use lightning::routing::network_graph::{NetworkGraph, RoutingFees};
2020
use lightning::routing::router::{Route, RouteHint, RouteHintHop, RouteParameters, find_route};
2121
use lightning::util::logger::Logger;
2222
use secp256k1::PublicKey;
23-
use core::convert::TryInto;
2423
use core::ops::Deref;
2524
use core::time::Duration;
2625
use sync::Mutex;
@@ -162,7 +161,8 @@ fn _create_phantom_invoice<Signer: Sign, K: Deref>(
162161
.current_timestamp()
163162
.payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
164163
.payment_secret(payment_secret)
165-
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into());
164+
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
165+
.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
166166
if let Some(amt) = amt_msat {
167167
invoice = invoice.amount_milli_satoshis(amt);
168168
}
@@ -212,9 +212,12 @@ fn _create_phantom_invoice<Signer: Sign, K: Deref>(
212212
/// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user
213213
/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
214214
/// that the payment secret is valid when the invoice is paid.
215+
///
216+
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
217+
/// in excess of the current time.
215218
pub fn create_invoice_from_channelmanager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
216219
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
217-
amt_msat: Option<u64>, description: String
220+
amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32
218221
) -> Result<Invoice, SignOrCreationError<()>>
219222
where
220223
M::Target: chain::Watch<Signer>,
@@ -227,7 +230,8 @@ where
227230
let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
228231
.expect("for the foreseeable future this shouldn't happen");
229232
create_invoice_from_channelmanager_and_duration_since_epoch(
230-
channelmanager, keys_manager, network, amt_msat, description, duration
233+
channelmanager, keys_manager, network, amt_msat, description, duration,
234+
invoice_expiry_delta_secs
231235
)
232236
}
233237

@@ -238,9 +242,12 @@ where
238242
/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify
239243
/// that the payment secret is valid when the invoice is paid.
240244
/// Use this variant if you want to pass the `description_hash` to the invoice.
245+
///
246+
/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
247+
/// in excess of the current time.
241248
pub fn create_invoice_from_channelmanager_with_description_hash<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
242249
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
243-
amt_msat: Option<u64>, description_hash: Sha256,
250+
amt_msat: Option<u64>, description_hash: Sha256, invoice_expiry_delta_secs: u32
244251
) -> Result<Invoice, SignOrCreationError<()>>
245252
where
246253
M::Target: chain::Watch<Signer>,
@@ -256,7 +263,8 @@ where
256263
.expect("for the foreseeable future this shouldn't happen");
257264

258265
create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
259-
channelmanager, keys_manager, network, amt_msat, description_hash, duration,
266+
channelmanager, keys_manager, network, amt_msat,
267+
description_hash, duration, invoice_expiry_delta_secs
260268
)
261269
}
262270

@@ -266,6 +274,7 @@ where
266274
pub fn create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
267275
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
268276
amt_msat: Option<u64>, description_hash: Sha256, duration_since_epoch: Duration,
277+
invoice_expiry_delta_secs: u32
269278
) -> Result<Invoice, SignOrCreationError<()>>
270279
where
271280
M::Target: chain::Watch<Signer>,
@@ -277,7 +286,7 @@ where
277286
_create_invoice_from_channelmanager_and_duration_since_epoch(
278287
channelmanager, keys_manager, network, amt_msat,
279288
InvoiceDescription::Hash(&description_hash),
280-
duration_since_epoch,
289+
duration_since_epoch, invoice_expiry_delta_secs
281290
)
282291
}
283292

@@ -287,6 +296,7 @@ where
287296
pub fn create_invoice_from_channelmanager_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
288297
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
289298
amt_msat: Option<u64>, description: String, duration_since_epoch: Duration,
299+
invoice_expiry_delta_secs: u32
290300
) -> Result<Invoice, SignOrCreationError<()>>
291301
where
292302
M::Target: chain::Watch<Signer>,
@@ -300,13 +310,14 @@ where
300310
InvoiceDescription::Direct(
301311
&Description::new(description).map_err(SignOrCreationError::CreationError)?,
302312
),
303-
duration_since_epoch,
313+
duration_since_epoch, invoice_expiry_delta_secs
304314
)
305315
}
306316

307317
fn _create_invoice_from_channelmanager_and_duration_since_epoch<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
308318
channelmanager: &ChannelManager<Signer, M, T, K, F, L>, keys_manager: K, network: Currency,
309319
amt_msat: Option<u64>, description: InvoiceDescription, duration_since_epoch: Duration,
320+
invoice_expiry_delta_secs: u32
310321
) -> Result<Invoice, SignOrCreationError<()>>
311322
where
312323
M::Target: chain::Watch<Signer>,
@@ -320,7 +331,7 @@ where
320331
// `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin
321332
// supply.
322333
let (payment_hash, payment_secret) = channelmanager
323-
.create_inbound_payment(amt_msat, DEFAULT_EXPIRY_TIME.try_into().unwrap())
334+
.create_inbound_payment(amt_msat, invoice_expiry_delta_secs)
324335
.map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
325336
let our_node_pubkey = channelmanager.get_our_node_id();
326337

@@ -337,7 +348,8 @@ where
337348
.payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
338349
.payment_secret(payment_secret)
339350
.basic_mpp()
340-
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into());
351+
.min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into())
352+
.expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into()));
341353
if let Some(amt) = amt_msat {
342354
invoice = invoice.amount_milli_satoshis(amt);
343355
}
@@ -526,12 +538,14 @@ mod test {
526538
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
527539
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
528540
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
541+
let non_default_invoice_expiry_secs = 4200;
529542
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
530543
&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string(),
531-
Duration::from_secs(1234567)).unwrap();
544+
Duration::from_secs(1234567), non_default_invoice_expiry_secs).unwrap();
532545
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
533546
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
534547
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
548+
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
535549

536550
// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
537551
// available.
@@ -592,7 +606,7 @@ mod test {
592606
let description_hash = crate::Sha256(Hash::hash("Testing description_hash".as_bytes()));
593607
let invoice = ::utils::create_invoice_from_channelmanager_with_description_hash_and_duration_since_epoch(
594608
&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000),
595-
description_hash, Duration::from_secs(1234567),
609+
description_hash, Duration::from_secs(1234567), 3600
596610
).unwrap();
597611
assert_eq!(invoice.amount_pico_btc(), Some(100_000));
598612
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
@@ -752,7 +766,7 @@ mod test {
752766
) {
753767
let invoice = create_invoice_from_channelmanager_and_duration_since_epoch(
754768
&invoice_node.node, invoice_node.keys_manager, Currency::BitcoinTestnet, invoice_amt, "test".to_string(),
755-
Duration::from_secs(1234567)).unwrap();
769+
Duration::from_secs(1234567), 3600).unwrap();
756770
let hints = invoice.private_routes();
757771

758772
for hint in hints {
@@ -799,8 +813,13 @@ mod test {
799813
} else {
800814
None
801815
};
816+
let non_default_invoice_expiry_secs = 4200;
802817

803-
let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), payment_hash, "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
818+
let invoice =
819+
::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(
820+
Some(payment_amt), payment_hash, "test".to_string(), non_default_invoice_expiry_secs,
821+
route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet
822+
).unwrap();
804823
let (payment_hash, payment_secret) = (PaymentHash(invoice.payment_hash().into_inner()), *invoice.payment_secret());
805824
let payment_preimage = if user_generated_pmt_hash {
806825
user_payment_preimage
@@ -811,6 +830,7 @@ mod test {
811830
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
812831
assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
813832
assert_eq!(invoice.route_hints().len(), 2);
833+
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
814834
assert!(!invoice.features().unwrap().supports_basic_mpp());
815835

816836
let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
@@ -931,10 +951,17 @@ mod test {
931951
];
932952

933953
let description_hash = crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes()));
934-
let invoice = ::utils::create_phantom_invoice_with_description_hash::<EnforcingSigner,&test_utils::TestKeysInterface>(Some(payment_amt), None, 3600, description_hash, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
935-
954+
let non_default_invoice_expiry_secs = 4200;
955+
let invoice = ::utils::create_phantom_invoice_with_description_hash::<
956+
EnforcingSigner, &test_utils::TestKeysInterface,
957+
>(
958+
Some(payment_amt), None, non_default_invoice_expiry_secs, description_hash,
959+
route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet
960+
)
961+
.unwrap();
936962
assert_eq!(invoice.amount_pico_btc(), Some(200_000));
937963
assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
964+
assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into()));
938965
assert_eq!(invoice.description(), InvoiceDescription::Hash(&crate::Sha256(Sha256::hash("Description hash phantom invoice".as_bytes()))));
939966
}
940967

lightning-net-tokio/src/lib.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,28 @@ struct Connection {
120120
id: u64,
121121
}
122122
impl Connection {
123+
async fn poll_event_process<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, mut event_receiver: mpsc::Receiver<()>) where
124+
CMH: ChannelMessageHandler + 'static + Send + Sync,
125+
RMH: RoutingMessageHandler + 'static + Send + Sync,
126+
L: Logger + 'static + ?Sized + Send + Sync,
127+
UMH: CustomMessageHandler + 'static + Send + Sync {
128+
loop {
129+
if event_receiver.recv().await.is_none() {
130+
return;
131+
}
132+
peer_manager.process_events();
133+
}
134+
}
135+
123136
async fn schedule_read<CMH, RMH, L, UMH>(peer_manager: Arc<peer_handler::PeerManager<SocketDescriptor, Arc<CMH>, Arc<RMH>, Arc<L>, Arc<UMH>>>, us: Arc<Mutex<Self>>, mut reader: io::ReadHalf<TcpStream>, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where
124-
CMH: ChannelMessageHandler + 'static,
125-
RMH: RoutingMessageHandler + 'static,
126-
L: Logger + 'static + ?Sized,
127-
UMH: CustomMessageHandler + 'static {
137+
CMH: ChannelMessageHandler + 'static + Send + Sync,
138+
RMH: RoutingMessageHandler + 'static + Send + Sync,
139+
L: Logger + 'static + ?Sized + Send + Sync,
140+
UMH: CustomMessageHandler + 'static + Send + Sync {
141+
// Create a waker to wake up poll_event_process, above
142+
let (event_waker, event_receiver) = mpsc::channel(1);
143+
tokio::spawn(Self::poll_event_process(Arc::clone(&peer_manager), event_receiver));
144+
128145
// 8KB is nice and big but also should never cause any issues with stack overflowing.
129146
let mut buf = [0; 8192];
130147

@@ -175,7 +192,14 @@ impl Connection {
175192
Err(_) => break Disconnect::PeerDisconnected,
176193
},
177194
}
178-
peer_manager.process_events();
195+
let _ = event_waker.try_send(());
196+
197+
// At this point we've processed a message or two, and reset the ping timer for this
198+
// peer, at least in the "are we still receiving messages" context, if we don't give up
199+
// our timeslice to another task we may just spin on this peer, starving other peers
200+
// and eventually disconnecting them for ping timeouts. Instead, we explicitly yield
201+
// here.
202+
tokio::task::yield_now().await;
179203
};
180204
let writer_option = us.lock().unwrap().writer.take();
181205
if let Some(mut writer) = writer_option {
@@ -443,6 +467,9 @@ impl peer_handler::SocketDescriptor for SocketDescriptor {
443467
// pause read given we're now waiting on the remote end to ACK (and in
444468
// accordance with the send_data() docs).
445469
us.read_paused = true;
470+
// Further, to avoid any current pending read causing a `read_event` call, wake
471+
// up the read_waker and restart its loop.
472+
let _ = us.read_waker.try_send(());
446473
return written_len;
447474
},
448475
}

lightning/src/debug_sync.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,5 @@ fn read_write_lockorder_fail() {
362362
let _a = a.write().unwrap();
363363
}
364364
}
365+
366+
pub type FairRwLock<T> = RwLock<T>;

lightning/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ mod sync {
193193
pub use debug_sync::*;
194194
#[cfg(not(test))]
195195
pub use ::std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard};
196+
#[cfg(not(test))]
197+
pub use crate::util::fairrwlock::FairRwLock;
196198
}
197199

198200
#[cfg(not(feature = "std"))]

0 commit comments

Comments
 (0)