Skip to content

Commit dbedf14

Browse files
committed
WIP: LockableScore
1 parent f7f3271 commit dbedf14

File tree

2 files changed

+87
-31
lines changed

2 files changed

+87
-31
lines changed

lightning-invoice/src/payment.rs

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -117,33 +117,36 @@ use lightning::ln::{PaymentHash, PaymentSecret};
117117
use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
118118
use lightning::ln::msgs::LightningError;
119119
use lightning::routing;
120+
use lightning::routing::Score;
120121
use lightning::routing::router::{Payee, Route, RouteParameters};
121122
use lightning::util::events::{Event, EventHandler};
122123
use lightning::util::logger::Logger;
124+
//use lightning::util::ser::{Writeable, Writer};
123125

124126
use secp256k1::key::PublicKey;
125127

126128
use std::collections::hash_map::{self, HashMap};
127129
use std::ops::Deref;
128-
use std::sync::{Mutex, RwLock};
130+
use std::sync::Mutex;
129131
use std::time::{Duration, SystemTime};
130132

131133
/// A utility for paying [`Invoice]`s.
132-
pub struct InvoicePayer<P: Deref, R, S, L: Deref, E>
134+
pub struct InvoicePayer<'a: 'b, 'b, P: Deref, R, S, L: Deref, E>
133135
where
134136
P::Target: Payer,
135137
R: Router,
136-
S: routing::Score,
138+
S: routing::LockableScore<'a, 'b>,
137139
L::Target: Logger,
138140
E: EventHandler,
139141
{
140142
payer: P,
141143
router: R,
142-
scorer: RwLock<S>,
144+
scorer: S,
143145
logger: L,
144146
event_handler: E,
145147
payment_cache: Mutex<HashMap<PaymentHash, usize>>,
146148
retry_attempts: RetryAttempts,
149+
phantom: std::marker::PhantomData<(&'a (), &'b ())>,
147150
}
148151

149152
/// A trait defining behavior of an [`Invoice`] payer.
@@ -187,22 +190,11 @@ pub enum PaymentError {
187190
Sending(PaymentSendFailure),
188191
}
189192

190-
/// A read-only version of the scorer.
191-
pub struct ReadOnlyScorer<'a, S: routing::Score>(std::sync::RwLockReadGuard<'a, S>);
192-
193-
impl<'a, S: routing::Score> Deref for ReadOnlyScorer<'a, S> {
194-
type Target = S;
195-
196-
fn deref(&self) -> &Self::Target {
197-
&*self.0
198-
}
199-
}
200-
201-
impl<P: Deref, R, S, L: Deref, E> InvoicePayer<P, R, S, L, E>
193+
impl<'a: 'b, 'b, P: Deref, R, S, L: Deref, E> InvoicePayer<'a, 'b, P, R, S, L, E>
202194
where
203195
P::Target: Payer,
204196
R: Router,
205-
S: routing::Score,
197+
S: routing::LockableScore<'a, 'b>,
206198
L::Target: Logger,
207199
E: EventHandler,
208200
{
@@ -216,22 +208,15 @@ where
216208
Self {
217209
payer,
218210
router,
219-
scorer: RwLock::new(scorer),
211+
scorer,
220212
logger,
221213
event_handler,
222214
payment_cache: Mutex::new(HashMap::new()),
223215
retry_attempts,
216+
phantom: std::marker::PhantomData,
224217
}
225218
}
226219

227-
/// Returns a read-only reference to the parameterized [`routing::Score`].
228-
///
229-
/// Useful if the scorer needs to be persisted. Be sure to drop the returned guard immediately
230-
/// after use since retrying failed payment paths require write access.
231-
pub fn scorer(&'_ self) -> ReadOnlyScorer<'_, S> {
232-
ReadOnlyScorer(self.scorer.read().unwrap())
233-
}
234-
235220
/// Pays the given [`Invoice`], caching it for later use in case a retry is needed.
236221
pub fn pay_invoice(&self, invoice: &Invoice) -> Result<PaymentId, PaymentError> {
237222
if invoice.amount_milli_satoshis().is_none() {
@@ -278,7 +263,7 @@ where
278263
&payer,
279264
&params,
280265
Some(&first_hops.iter().collect::<Vec<_>>()),
281-
&*self.scorer.read().unwrap(),
266+
&self.scorer.lock(),
282267
).map_err(|e| PaymentError::Routing(e))?;
283268

284269
let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
@@ -299,7 +284,7 @@ where
299284
let first_hops = self.payer.first_hops();
300285
let route = self.router.find_route(
301286
&payer, &params, Some(&first_hops.iter().collect::<Vec<_>>()),
302-
&*self.scorer.read().unwrap()
287+
&self.scorer.lock()
303288
).map_err(|e| PaymentError::Routing(e))?;
304289
self.payer.retry_payment(&route, payment_id).map_err(|e| PaymentError::Sending(e))
305290
}
@@ -322,11 +307,11 @@ fn has_expired(params: &RouteParameters) -> bool {
322307
Invoice::is_expired_from_epoch(&SystemTime::UNIX_EPOCH, expiry_time)
323308
}
324309

325-
impl<P: Deref, R, S, L: Deref, E> EventHandler for InvoicePayer<P, R, S, L, E>
310+
impl<'a: 'b, 'b, P: Deref, R, S, L: Deref, E> EventHandler for InvoicePayer<'a, 'b, P, R, S, L, E>
326311
where
327312
P::Target: Payer,
328313
R: Router,
329-
S: routing::Score,
314+
S: routing::LockableScore<'a, 'b>,
330315
L::Target: Logger,
331316
E: EventHandler,
332317
{
@@ -336,7 +321,7 @@ where
336321
payment_id, payment_hash, rejected_by_dest, path, short_channel_id, retry, ..
337322
} => {
338323
if let Some(short_channel_id) = short_channel_id {
339-
self.scorer.write().unwrap().payment_path_failed(path, *short_channel_id);
324+
self.scorer.lock().payment_path_failed(path, *short_channel_id);
340325
}
341326

342327
let mut payment_cache = self.payment_cache.lock().unwrap();
@@ -391,6 +376,51 @@ where
391376
}
392377
}
393378

379+
/////
380+
//pub trait WriteableScore: routing::Score + Writeable {}
381+
//
382+
/////
383+
//pub struct ScorePersister<I, P: Deref, R, S, L: Deref, E>
384+
//where
385+
// I: Deref<Target=InvoicePayer<P, R, S, L, E>>,
386+
// P::Target: Payer,
387+
// R: Router,
388+
// S: WriteableScore,
389+
// L::Target: Logger,
390+
// E: EventHandler,
391+
//{
392+
// invoice_payer: I,
393+
//}
394+
//
395+
//impl<I, P: Deref, R, S, L: Deref, E> ScorePersister<I, P, R, S, L, E>
396+
//where
397+
// I: Deref<Target=InvoicePayer<P, R, S, L, E>>,
398+
// P::Target: Payer,
399+
// R: Router,
400+
// S: WriteableScore,
401+
// L::Target: Logger,
402+
// E: EventHandler,
403+
//{
404+
// ///
405+
// pub fn new(invoice_payer: I) -> Self {
406+
// Self { invoice_payer }
407+
// }
408+
//}
409+
//
410+
//impl<I, P: Deref, R, S, L: Deref, E> Writeable for ScorePersister<I, P, R, S, L, E>
411+
//where
412+
// I: Deref<Target=InvoicePayer<P, R, S, L, E>>,
413+
// P::Target: Payer,
414+
// R: Router,
415+
// S: WriteableScore,
416+
// L::Target: Logger,
417+
// E: EventHandler,
418+
//{
419+
// fn write<W: Writer>(&self, writer: &mut W) -> Result<(), std::io::Error> {
420+
// self.invoice_payer.scorer.read().unwrap().write(writer)
421+
// }
422+
//}
423+
394424
#[cfg(test)]
395425
mod tests {
396426
use super::*;

lightning/src/routing/mod.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use routing::network_graph::NodeId;
1717
use routing::router::RouteHop;
1818

1919
use prelude::*;
20+
use core::ops::{Deref, DerefMut};
21+
use sync::{Mutex, MutexGuard};
2022

2123
/// An interface used to score payment channels for path finding.
2224
///
@@ -29,3 +31,27 @@ pub trait Score {
2931
/// Handles updating channel penalties after failing to route through a channel.
3032
fn payment_path_failed(&mut self, path: &Vec<RouteHop>, short_channel_id: u64);
3133
}
34+
35+
pub trait LockableScore<'a: 'b, 'b> {
36+
type Locked: Score;
37+
38+
fn lock(&'a self) -> Self::Locked;
39+
}
40+
41+
impl<'a: 'b, 'b, S: 'b + Score, T: Deref<Target=Mutex<S>>> LockableScore<'a, 'b> for T {
42+
type Locked = MutexGuard<'b, S>;
43+
44+
fn lock(&'a self) -> Self::Locked {
45+
self.deref().lock().unwrap()
46+
}
47+
}
48+
49+
impl<'a, S: Score> Score for MutexGuard<'a, S> {
50+
fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId) -> u64 {
51+
self.deref().channel_penalty_msat(short_channel_id, source, target)
52+
}
53+
54+
fn payment_path_failed(&mut self, path: &Vec<RouteHop>, short_channel_id: u64) {
55+
self.deref_mut().payment_path_failed(path, short_channel_id)
56+
}
57+
}

0 commit comments

Comments
 (0)