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 {};
@@ -139,6 +144,10 @@ use std::sync::Mutex;
139144use std:: time:: { Duration , SystemTime } ;
140145
141146/// A utility for paying [`Invoice`]s and sending spontaneous payments.
147+ ///
148+ /// See [module-level documentation] for details.
149+ ///
150+ /// [module-level documentation]: crate::payment
142151pub struct InvoicePayer < P : Deref , R , S : Deref , L : Deref , E >
143152where
144153 P :: Target : Payer ,
@@ -473,6 +482,10 @@ where
473482
474483 if * all_paths_failed { self . payment_cache . lock ( ) . unwrap ( ) . remove ( payment_hash) ; }
475484 } ,
485+ Event :: PaymentPathSuccessful { path, .. } => {
486+ let path = path. iter ( ) . collect :: < Vec < _ > > ( ) ;
487+ self . scorer . lock ( ) . payment_path_successful ( & path) ;
488+ } ,
476489 Event :: PaymentSent { payment_hash, .. } => {
477490 let mut payment_cache = self . payment_cache . lock ( ) . unwrap ( ) ;
478491 let attempts = payment_cache
@@ -1127,7 +1140,9 @@ mod tests {
11271140 . expect_send ( Amount :: ForInvoice ( final_value_msat) )
11281141 . expect_send ( Amount :: OnRetry ( final_value_msat / 2 ) ) ;
11291142 let router = TestRouter { } ;
1130- let scorer = RefCell :: new ( TestScorer :: new ( ) . expect_channel_failure ( short_channel_id. unwrap ( ) ) ) ;
1143+ let scorer = RefCell :: new ( TestScorer :: new ( ) . expect ( PaymentPath :: Failure {
1144+ path : path. clone ( ) , short_channel_id : path[ 0 ] . short_channel_id ,
1145+ } ) ) ;
11311146 let logger = TestLogger :: new ( ) ;
11321147 let invoice_payer =
11331148 InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
@@ -1146,6 +1161,39 @@ mod tests {
11461161 invoice_payer. handle_event ( & event) ;
11471162 }
11481163
1164+ #[ test]
1165+ fn scores_successful_channels ( ) {
1166+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
1167+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1168+
1169+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1170+ let invoice = invoice ( payment_preimage) ;
1171+ let payment_hash = Some ( PaymentHash ( invoice. payment_hash ( ) . clone ( ) . into_inner ( ) ) ) ;
1172+ let final_value_msat = invoice. amount_milli_satoshis ( ) . unwrap ( ) ;
1173+ let route = TestRouter :: route_for_value ( final_value_msat) ;
1174+
1175+ // Expect that scorer is given short_channel_id upon handling the event.
1176+ let payer = TestPayer :: new ( ) . expect_send ( Amount :: ForInvoice ( final_value_msat) ) ;
1177+ let router = TestRouter { } ;
1178+ let scorer = RefCell :: new ( TestScorer :: new ( )
1179+ . expect ( PaymentPath :: Success { path : route. paths [ 0 ] . clone ( ) } )
1180+ . expect ( PaymentPath :: Success { path : route. paths [ 1 ] . clone ( ) } )
1181+ ) ;
1182+ let logger = TestLogger :: new ( ) ;
1183+ let invoice_payer =
1184+ InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
1185+
1186+ let payment_id = invoice_payer. pay_invoice ( & invoice) . unwrap ( ) ;
1187+ let event = Event :: PaymentPathSuccessful {
1188+ payment_id, payment_hash, path : route. paths [ 0 ] . clone ( )
1189+ } ;
1190+ invoice_payer. handle_event ( & event) ;
1191+ let event = Event :: PaymentPathSuccessful {
1192+ payment_id, payment_hash, path : route. paths [ 1 ] . clone ( )
1193+ } ;
1194+ invoice_payer. handle_event ( & event) ;
1195+ }
1196+
11491197 struct TestRouter ;
11501198
11511199 impl TestRouter {
@@ -1212,18 +1260,24 @@ mod tests {
12121260 }
12131261
12141262 struct TestScorer {
1215- expectations : VecDeque < u64 > ,
1263+ expectations : Option < VecDeque < PaymentPath > > ,
1264+ }
1265+
1266+ #[ derive( Debug ) ]
1267+ enum PaymentPath {
1268+ Failure { path : Vec < RouteHop > , short_channel_id : u64 } ,
1269+ Success { path : Vec < RouteHop > } ,
12161270 }
12171271
12181272 impl TestScorer {
12191273 fn new ( ) -> Self {
12201274 Self {
1221- expectations : VecDeque :: new ( ) ,
1275+ expectations : None ,
12221276 }
12231277 }
12241278
1225- fn expect_channel_failure ( mut self , short_channel_id : u64 ) -> Self {
1226- self . expectations . push_back ( short_channel_id ) ;
1279+ fn expect ( mut self , expectation : PaymentPath ) -> Self {
1280+ self . expectations . get_or_insert_with ( || VecDeque :: new ( ) ) . push_back ( expectation ) ;
12271281 self
12281282 }
12291283 }
@@ -1232,14 +1286,38 @@ mod tests {
12321286 impl lightning:: util:: ser:: Writeable for TestScorer {
12331287 fn write < W : lightning:: util:: ser:: Writer > ( & self , _: & mut W ) -> Result < ( ) , std:: io:: Error > { unreachable ! ( ) ; }
12341288 }
1289+
12351290 impl Score for TestScorer {
12361291 fn channel_penalty_msat (
12371292 & self , _short_channel_id : u64 , _send_amt : u64 , _chan_amt : Option < u64 > , _source : & NodeId , _target : & NodeId
12381293 ) -> u64 { 0 }
12391294
1240- fn payment_path_failed ( & mut self , _path : & [ & RouteHop ] , short_channel_id : u64 ) {
1241- if let Some ( expected_short_channel_id) = self . expectations . pop_front ( ) {
1242- assert_eq ! ( short_channel_id, expected_short_channel_id) ;
1295+ fn payment_path_failed ( & mut self , actual_path : & [ & RouteHop ] , actual_short_channel_id : u64 ) {
1296+ if let Some ( expectations) = & mut self . expectations {
1297+ match expectations. pop_front ( ) {
1298+ Some ( PaymentPath :: Failure { path, short_channel_id } ) => {
1299+ assert_eq ! ( actual_path, & path. iter( ) . collect:: <Vec <_>>( ) [ ..] ) ;
1300+ assert_eq ! ( actual_short_channel_id, short_channel_id) ;
1301+ } ,
1302+ Some ( PaymentPath :: Success { path } ) => {
1303+ panic ! ( "Unexpected successful payment path: {:?}" , path)
1304+ } ,
1305+ None => panic ! ( "Unexpected payment_path_failed call: {:?}" , actual_path) ,
1306+ }
1307+ }
1308+ }
1309+
1310+ fn payment_path_successful ( & mut self , actual_path : & [ & RouteHop ] ) {
1311+ if let Some ( expectations) = & mut self . expectations {
1312+ match expectations. pop_front ( ) {
1313+ Some ( PaymentPath :: Failure { path, .. } ) => {
1314+ panic ! ( "Unexpected payment path failure: {:?}" , path)
1315+ } ,
1316+ Some ( PaymentPath :: Success { path } ) => {
1317+ assert_eq ! ( actual_path, & path. iter( ) . collect:: <Vec <_>>( ) [ ..] ) ;
1318+ } ,
1319+ None => panic ! ( "Unexpected payment_path_successful call: {:?}" , actual_path) ,
1320+ }
12431321 }
12441322 }
12451323 }
@@ -1250,8 +1328,10 @@ mod tests {
12501328 return ;
12511329 }
12521330
1253- if !self . expectations . is_empty ( ) {
1254- panic ! ( "Unsatisfied channel failure expectations: {:?}" , self . expectations) ;
1331+ if let Some ( expectations) = & self . expectations {
1332+ if !expectations. is_empty ( ) {
1333+ panic ! ( "Unsatisfied scorer expectations: {:?}" , expectations) ;
1334+ }
12551335 }
12561336 }
12571337 }
0 commit comments