1515//! and payee using information provided by the payer and from the payee's [`Invoice`], when
1616//! applicable.
1717//!
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+ //!
1822//! [`InvoicePayer`] is capable of retrying failed payments. It accomplishes this by implementing
1923//! [`EventHandler`] which decorates a user-provided handler. It will intercept any
2024//! [`Event::PaymentPathFailed`] events and retry the failed paths for a fixed number of total
8084//! # &self, _short_channel_id: u64, _send_amt: u64, _chan_amt: Option<u64>, _source: &NodeId, _target: &NodeId
8185//! # ) -> u64 { 0 }
8286//! # fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
87+ //! # fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
8388//! # }
8489//! #
8590//! # struct FakeLogger {}
@@ -140,6 +145,10 @@ use std::sync::Mutex;
140145use std:: time:: { Duration , SystemTime } ;
141146
142147/// 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
143152pub struct InvoicePayer < P : Deref , R , S : Deref , L : Deref , E >
144153where
145154 P :: Target : Payer ,
@@ -474,6 +483,10 @@ where
474483
475484 if * all_paths_failed { self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ; }
476485 } ,
486+ Event :: PaymentPathSuccessful { path, .. } => {
487+ let path = path. iter ( ) . collect :: < Vec < _ > > ( ) ;
488+ self . scorer . lock ( ) . payment_path_successful ( & path) ;
489+ } ,
477490 Event :: PaymentSent { payment_hash, .. } => {
478491 let mut payment_cache = self . payment_cache . lock ( ) . unwrap ( ) ;
479492 let attempts = payment_cache
@@ -1128,7 +1141,9 @@ mod tests {
11281141 . expect_send ( Amount :: ForInvoice ( final_value_msat) )
11291142 . expect_send ( Amount :: OnRetry ( final_value_msat / 2 ) ) ;
11301143 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+ } ) ) ;
11321147 let logger = TestLogger :: new ( ) ;
11331148 let invoice_payer =
11341149 InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
@@ -1147,6 +1162,39 @@ mod tests {
11471162 invoice_payer. handle_event ( & event) ;
11481163 }
11491164
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+
11501198 struct TestRouter ;
11511199
11521200 impl TestRouter {
@@ -1213,18 +1261,24 @@ mod tests {
12131261 }
12141262
12151263 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 > } ,
12171271 }
12181272
12191273 impl TestScorer {
12201274 fn new ( ) -> Self {
12211275 Self {
1222- expectations : VecDeque :: new ( ) ,
1276+ expectations : None ,
12231277 }
12241278 }
12251279
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 ) ;
12281282 self
12291283 }
12301284 }
@@ -1233,14 +1287,38 @@ mod tests {
12331287 impl lightning:: util:: ser:: Writeable for TestScorer {
12341288 fn write < W : lightning:: util:: ser:: Writer > ( & self , _: & mut W ) -> Result < ( ) , std:: io:: Error > { unreachable ! ( ) ; }
12351289 }
1290+
12361291 impl Score for TestScorer {
12371292 fn channel_penalty_msat (
12381293 & self , _short_channel_id : u64 , _send_amt : u64 , _chan_amt : Option < u64 > , _source : & NodeId , _target : & NodeId
12391294 ) -> u64 { 0 }
12401295
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+ }
12441322 }
12451323 }
12461324 }
@@ -1251,8 +1329,10 @@ mod tests {
12511329 return ;
12521330 }
12531331
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+ }
12561336 }
12571337 }
12581338 }
0 commit comments