15
15
//! and payee using information provided by the payer and from the payee's [`Invoice`], when
16
16
//! applicable.
17
17
//!
18
+ //! [`InvoicePayer`] is parameterized by a [`LockableScore`], which it uses for scoring failed and
19
+ //! successful payment paths upon receiving [`Event::PaymentPathFailed`] and
20
+ //! [`Event::PaymentPathSuccessful`] events, respectively.
21
+ //!
18
22
//! [`InvoicePayer`] is capable of retrying failed payments. It accomplishes this by implementing
19
23
//! [`EventHandler`] which decorates a user-provided handler. It will intercept any
20
24
//! [`Event::PaymentPathFailed`] events and retry the failed paths for a fixed number of total
80
84
//! # &self, _short_channel_id: u64, _send_amt: u64, _chan_amt: Option<u64>, _source: &NodeId, _target: &NodeId
81
85
//! # ) -> u64 { 0 }
82
86
//! # fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
87
+ //! # fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
83
88
//! # }
84
89
//! #
85
90
//! # struct FakeLogger {}
@@ -140,6 +145,10 @@ use std::sync::Mutex;
140
145
use std:: time:: { Duration , SystemTime } ;
141
146
142
147
/// A utility for paying [`Invoice`]s and sending spontaneous payments.
148
+ ///
149
+ /// See [module-level documentation] for details.
150
+ ///
151
+ /// [module-level documentation]: crate::payment
143
152
pub struct InvoicePayer < P : Deref , R , S : Deref , L : Deref , E >
144
153
where
145
154
P :: Target : Payer ,
@@ -474,6 +483,10 @@ where
474
483
475
484
if * all_paths_failed { self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ; }
476
485
} ,
486
+ Event :: PaymentPathSuccessful { path, .. } => {
487
+ let path = path. iter ( ) . collect :: < Vec < _ > > ( ) ;
488
+ self . scorer . lock ( ) . payment_path_successful ( & path) ;
489
+ } ,
477
490
Event :: PaymentSent { payment_hash, .. } => {
478
491
let mut payment_cache = self . payment_cache . lock ( ) . unwrap ( ) ;
479
492
let attempts = payment_cache
@@ -1128,7 +1141,9 @@ mod tests {
1128
1141
. expect_send ( Amount :: ForInvoice ( final_value_msat) )
1129
1142
. expect_send ( Amount :: OnRetry ( final_value_msat / 2 ) ) ;
1130
1143
let router = TestRouter { } ;
1131
- let scorer = RefCell :: new ( TestScorer :: new ( ) . expect_channel_failure ( short_channel_id. unwrap ( ) ) ) ;
1144
+ let scorer = RefCell :: new ( TestScorer :: new ( ) . expect ( PaymentPath :: Failure {
1145
+ path : path. clone ( ) , short_channel_id : path[ 0 ] . short_channel_id ,
1146
+ } ) ) ;
1132
1147
let logger = TestLogger :: new ( ) ;
1133
1148
let invoice_payer =
1134
1149
InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
@@ -1147,6 +1162,39 @@ mod tests {
1147
1162
invoice_payer. handle_event ( & event) ;
1148
1163
}
1149
1164
1165
+ #[ test]
1166
+ fn scores_successful_channels ( ) {
1167
+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
1168
+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1169
+
1170
+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1171
+ let invoice = invoice ( payment_preimage) ;
1172
+ let payment_hash = Some ( PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1173
+ let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1174
+ let route = TestRouter :: route_for_value ( final_value_msat) ;
1175
+
1176
+ // Expect that scorer is given short_channel_id upon handling the event.
1177
+ let payer = TestPayer :: new ( ) . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1178
+ let router = TestRouter { } ;
1179
+ let scorer = RefCell :: new ( TestScorer :: new ( )
1180
+ . expect ( PaymentPath :: Success { path : route. paths [ 0 ] . clone ( ) } )
1181
+ . expect ( PaymentPath :: Success { path : route. paths [ 1 ] . clone ( ) } )
1182
+ ) ;
1183
+ let logger = TestLogger :: new ( ) ;
1184
+ let invoice_payer =
1185
+ InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
1186
+
1187
+ let payment_id = invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1188
+ let event = Event :: PaymentPathSuccessful {
1189
+ payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1190
+ } ;
1191
+ invoice_payer. handle_event ( & event) ;
1192
+ let event = Event :: PaymentPathSuccessful {
1193
+ payment_id, payment_hash, path : route. paths [ 1 ] . clone ( )
1194
+ } ;
1195
+ invoice_payer. handle_event ( & event) ;
1196
+ }
1197
+
1150
1198
struct TestRouter ;
1151
1199
1152
1200
impl TestRouter {
@@ -1213,18 +1261,24 @@ mod tests {
1213
1261
}
1214
1262
1215
1263
struct TestScorer {
1216
- expectations : VecDeque < u64 > ,
1264
+ expectations : Option < VecDeque < PaymentPath > > ,
1265
+ }
1266
+
1267
+ #[ derive( Debug ) ]
1268
+ enum PaymentPath {
1269
+ Failure { path : Vec < RouteHop > , short_channel_id : u64 } ,
1270
+ Success { path : Vec < RouteHop > } ,
1217
1271
}
1218
1272
1219
1273
impl TestScorer {
1220
1274
fn new ( ) -> Self {
1221
1275
Self {
1222
- expectations : VecDeque :: new ( ) ,
1276
+ expectations : None ,
1223
1277
}
1224
1278
}
1225
1279
1226
- fn expect_channel_failure ( mut self , short_channel_id : u64 ) -> Self {
1227
- self . expectations . push_back ( short_channel_id ) ;
1280
+ fn expect ( mut self , expectation : PaymentPath ) -> Self {
1281
+ self . expectations . get_or_insert_with ( || VecDeque :: new ( ) ) . push_back ( expectation ) ;
1228
1282
self
1229
1283
}
1230
1284
}
@@ -1233,14 +1287,38 @@ mod tests {
1233
1287
impl lightning:: util:: ser:: Writeable for TestScorer {
1234
1288
fn write < W : lightning:: util:: ser:: Writer > ( & self , _: & mut W ) -> Result < ( ) , std:: io:: Error > { unreachable ! ( ) ; }
1235
1289
}
1290
+
1236
1291
impl Score for TestScorer {
1237
1292
fn channel_penalty_msat (
1238
1293
& self , _short_channel_id : u64 , _send_amt : u64 , _chan_amt : Option < u64 > , _source : & NodeId , _target : & NodeId
1239
1294
) -> u64 { 0 }
1240
1295
1241
- fn payment_path_failed ( & mut self , _path : & [ & RouteHop ] , short_channel_id : u64 ) {
1242
- if let Some ( expected_short_channel_id) = self . expectations . pop_front ( ) {
1243
- assert_eq ! ( short_channel_id, expected_short_channel_id) ;
1296
+ fn payment_path_failed ( & mut self , actual_path : & [ & RouteHop ] , actual_short_channel_id : u64 ) {
1297
+ if let Some ( expectations) = & mut self . expectations {
1298
+ match expectations. pop_front ( ) {
1299
+ Some ( PaymentPath :: Failure { path, short_channel_id } ) => {
1300
+ assert_eq ! ( actual_path, & path. iter( ) . collect:: <Vec <_>>( ) [ ..] ) ;
1301
+ assert_eq ! ( actual_short_channel_id, short_channel_id) ;
1302
+ } ,
1303
+ Some ( PaymentPath :: Success { path } ) => {
1304
+ panic ! ( "Unexpected successful payment path: {:?}" , path)
1305
+ } ,
1306
+ None => panic ! ( "Unexpected payment_path_failed call: {:?}" , actual_path) ,
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ fn payment_path_successful ( & mut self , actual_path : & [ & RouteHop ] ) {
1312
+ if let Some ( expectations) = & mut self . expectations {
1313
+ match expectations. pop_front ( ) {
1314
+ Some ( PaymentPath :: Failure { path, .. } ) => {
1315
+ panic ! ( "Unexpected payment path failure: {:?}" , path)
1316
+ } ,
1317
+ Some ( PaymentPath :: Success { path } ) => {
1318
+ assert_eq ! ( actual_path, & path. iter( ) . collect:: <Vec <_>>( ) [ ..] ) ;
1319
+ } ,
1320
+ None => panic ! ( "Unexpected payment_path_successful call: {:?}" , actual_path) ,
1321
+ }
1244
1322
}
1245
1323
}
1246
1324
}
@@ -1251,8 +1329,10 @@ mod tests {
1251
1329
return ;
1252
1330
}
1253
1331
1254
- if !self . expectations . is_empty ( ) {
1255
- panic ! ( "Unsatisfied channel failure expectations: {:?}" , self . expectations) ;
1332
+ if let Some ( expectations) = & self . expectations {
1333
+ if !expectations. is_empty ( ) {
1334
+ panic ! ( "Unsatisfied scorer expectations: {:?}" , expectations) ;
1335
+ }
1256
1336
}
1257
1337
}
1258
1338
}
0 commit comments