7
7
// You may not use this file except in accordance with one or both of these
8
8
// licenses.
9
9
10
- //! A module for paying Lightning invoices.
10
+ //! A module for paying Lightning invoices and sending spontaneous payments .
11
11
//!
12
- //! Defines an [`InvoicePayer`] utility for paying invoices , parameterized by [`Payer`] and
12
+ //! Defines an [`InvoicePayer`] utility for sending payments , parameterized by [`Payer`] and
13
13
//! [`Router`] traits. Implementations of [`Payer`] provide the payer's node id, channels, and means
14
14
//! to send a payment over a [`Route`]. Implementations of [`Router`] find a [`Route`] between payer
15
- //! and payee using information provided by the payer and from the payee's [`Invoice`].
15
+ //! and payee using information provided by the payer and from the payee's [`Invoice`], when
16
+ //! applicable.
16
17
//!
17
18
//! [`InvoicePayer`] is capable of retrying failed payments. It accomplishes this by implementing
18
19
//! [`EventHandler`] which decorates a user-provided handler. It will intercept any
27
28
//! # extern crate lightning_invoice;
28
29
//! # extern crate secp256k1;
29
30
//! #
30
- //! # use lightning::ln::{PaymentHash, PaymentSecret};
31
+ //! # use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
31
32
//! # use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
32
33
//! # use lightning::ln::msgs::LightningError;
33
34
//! # use lightning::routing;
53
54
//! # fn send_payment(
54
55
//! # &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>
55
56
//! # ) -> Result<PaymentId, PaymentSendFailure> { unimplemented!() }
57
+ //! # fn send_spontaneous_payment(
58
+ //! # &self, route: &Route, payment_preimage: PaymentPreimage
59
+ //! # ) -> Result<PaymentId, PaymentSendFailure> { unimplemented!() }
56
60
//! # fn retry_payment(
57
61
//! # &self, route: &Route, payment_id: PaymentId
58
62
//! # ) -> Result<(), PaymentSendFailure> { unimplemented!() }
113
117
use crate :: Invoice ;
114
118
115
119
use bitcoin_hashes:: Hash ;
120
+ use bitcoin_hashes:: sha256:: Hash as Sha256 ;
116
121
117
- use lightning:: ln:: { PaymentHash , PaymentSecret } ;
122
+ use lightning:: ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
118
123
use lightning:: ln:: channelmanager:: { ChannelDetails , PaymentId , PaymentSendFailure } ;
119
124
use lightning:: ln:: msgs:: LightningError ;
120
125
use lightning:: routing;
@@ -130,7 +135,7 @@ use std::ops::Deref;
130
135
use std:: sync:: Mutex ;
131
136
use std:: time:: { Duration , SystemTime } ;
132
137
133
- /// A utility for paying [`Invoice]`s .
138
+ /// A utility for paying [`Invoice`]s and sending spontaneous payments .
134
139
pub struct InvoicePayer < P : Deref , R , S : Deref , L : Deref , E >
135
140
where
136
141
P :: Target : Payer ,
@@ -162,6 +167,11 @@ pub trait Payer {
162
167
& self , route : & Route , payment_hash : PaymentHash , payment_secret : & Option < PaymentSecret >
163
168
) -> Result < PaymentId , PaymentSendFailure > ;
164
169
170
+ /// Sends a spontaneous payment over the Lightning Network using the given [`Route`].
171
+ fn send_spontaneous_payment (
172
+ & self , route : & Route , payment_preimage : PaymentPreimage
173
+ ) -> Result < PaymentId , PaymentSendFailure > ;
174
+
165
175
/// Retries a failed payment path for the [`PaymentId`] using the given [`Route`].
166
176
fn retry_payment ( & self , route : & Route , payment_id : PaymentId ) -> Result < ( ) , PaymentSendFailure > ;
167
177
}
@@ -273,13 +283,43 @@ where
273
283
final_cltv_expiry_delta : invoice. min_final_cltv_expiry ( ) as u32 ,
274
284
} ;
275
285
276
- self . pay_internal ( & params, payment_hash, & payment_secret)
286
+ let send_payment = |route : & Route | {
287
+ self . payer . send_payment ( route, payment_hash, & payment_secret)
288
+ } ;
289
+ self . pay_internal ( & params, payment_hash, send_payment)
290
+ . map_err ( |e| { self . payment_cache . lock ( ) . unwrap ( ) . remove ( & payment_hash) ; e } )
291
+ }
292
+
293
+ /// Pays `pubkey` an amount using the hash of the given preimage, caching it for later use in
294
+ /// case a retry is needed.
295
+ ///
296
+ /// You should ensure that `payment_preimage` is unique and that its `payment_hash` has never
297
+ /// been paid before. Because [`InvoicePayer`] is stateless no effort is made to do so for you.
298
+ pub fn pay_pubkey (
299
+ & self , pubkey : PublicKey , payment_preimage : PaymentPreimage , amount_msats : u64 ,
300
+ final_cltv_expiry_delta : u32
301
+ ) -> Result < PaymentId , PaymentError > {
302
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
303
+ match self . payment_cache . lock ( ) . unwrap ( ) . entry ( payment_hash) {
304
+ hash_map:: Entry :: Occupied ( _) => return Err ( PaymentError :: Invoice ( "payment pending" ) ) ,
305
+ hash_map:: Entry :: Vacant ( entry) => entry. insert ( 0 ) ,
306
+ } ;
307
+
308
+ let params = RouteParameters {
309
+ payee : Payee :: for_keysend ( pubkey) ,
310
+ final_value_msat : amount_msats,
311
+ final_cltv_expiry_delta,
312
+ } ;
313
+
314
+ let send_payment = |route : & Route | {
315
+ self . payer . send_spontaneous_payment ( route, payment_preimage)
316
+ } ;
317
+ self . pay_internal ( & params, payment_hash, send_payment)
277
318
. map_err ( |e| { self . payment_cache . lock ( ) . unwrap ( ) . remove ( & payment_hash) ; e } )
278
319
}
279
320
280
- fn pay_internal (
281
- & self , params : & RouteParameters , payment_hash : PaymentHash ,
282
- payment_secret : & Option < PaymentSecret > ,
321
+ fn pay_internal < F : FnOnce ( & Route ) -> Result < PaymentId , PaymentSendFailure > + Copy > (
322
+ & self , params : & RouteParameters , payment_hash : PaymentHash , send_payment : F ,
283
323
) -> Result < PaymentId , PaymentError > {
284
324
if has_expired ( params) {
285
325
log_trace ! ( self . logger, "Invoice expired prior to send for payment {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -295,7 +335,7 @@ where
295
335
& self . scorer . lock ( ) ,
296
336
) . map_err ( |e| PaymentError :: Routing ( e) ) ?;
297
337
298
- match self . payer . send_payment ( & route, payment_hash , payment_secret ) {
338
+ match send_payment ( & route) {
299
339
Ok ( payment_id) => Ok ( payment_id) ,
300
340
Err ( e) => match e {
301
341
PaymentSendFailure :: ParameterError ( _) => Err ( e) ,
@@ -308,7 +348,7 @@ where
308
348
} else {
309
349
* retry_count += 1 ;
310
350
std:: mem:: drop ( payment_cache) ;
311
- Ok ( self . pay_internal ( params, payment_hash, payment_secret ) ?)
351
+ Ok ( self . pay_internal ( params, payment_hash, send_payment ) ?)
312
352
}
313
353
} ,
314
354
PaymentSendFailure :: PartialFailure { failed_paths_retry, payment_id, .. } => {
@@ -514,6 +554,10 @@ mod tests {
514
554
. unwrap ( )
515
555
}
516
556
557
+ fn pubkey ( ) -> PublicKey {
558
+ PublicKey :: from_slice ( & hex:: decode ( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap ( ) [ ..] ) . unwrap ( )
559
+ }
560
+
517
561
#[ test]
518
562
fn pays_invoice_on_first_attempt ( ) {
519
563
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -969,6 +1013,57 @@ mod tests {
969
1013
}
970
1014
}
971
1015
1016
+ #[ test]
1017
+ fn pays_pubkey_with_amount ( ) {
1018
+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
1019
+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1020
+
1021
+ let pubkey = pubkey ( ) ;
1022
+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1023
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
1024
+ let final_value_msat = 100 ;
1025
+ let final_cltv_expiry_delta = 42 ;
1026
+
1027
+ let payer = TestPayer :: new ( )
1028
+ . expect_send ( Amount :: Spontaneous ( final_value_msat) )
1029
+ . expect_send ( Amount :: ForInvoiceOrRetry ( final_value_msat) ) ;
1030
+ let router = TestRouter { } ;
1031
+ let scorer = RefCell :: new ( TestScorer :: new ( ) ) ;
1032
+ let logger = TestLogger :: new ( ) ;
1033
+ let invoice_payer =
1034
+ InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
1035
+
1036
+ let payment_id = Some ( invoice_payer. pay_pubkey (
1037
+ pubkey, payment_preimage, final_value_msat, final_cltv_expiry_delta
1038
+ ) . unwrap ( ) ) ;
1039
+ assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
1040
+
1041
+ let retry = RouteParameters {
1042
+ payee : Payee :: for_keysend ( pubkey) ,
1043
+ final_value_msat,
1044
+ final_cltv_expiry_delta,
1045
+ } ;
1046
+ let event = Event :: PaymentPathFailed {
1047
+ payment_id,
1048
+ payment_hash,
1049
+ network_update : None ,
1050
+ rejected_by_dest : false ,
1051
+ all_paths_failed : false ,
1052
+ path : vec ! [ ] ,
1053
+ short_channel_id : None ,
1054
+ retry : Some ( retry) ,
1055
+ } ;
1056
+ invoice_payer. handle_event ( & event) ;
1057
+ assert_eq ! ( * event_handled. borrow( ) , false ) ;
1058
+ assert_eq ! ( * payer. attempts. borrow( ) , 2 ) ;
1059
+
1060
+ invoice_payer. handle_event ( & Event :: PaymentSent {
1061
+ payment_id, payment_preimage, payment_hash, fee_paid_msat : None
1062
+ } ) ;
1063
+ assert_eq ! ( * event_handled. borrow( ) , true ) ;
1064
+ assert_eq ! ( * payer. attempts. borrow( ) , 2 ) ;
1065
+ }
1066
+
972
1067
#[ test]
973
1068
fn scores_failed_channel ( ) {
974
1069
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -1116,11 +1211,17 @@ mod tests {
1116
1211
}
1117
1212
1118
1213
struct TestPayer {
1119
- expectations : core:: cell:: RefCell < VecDeque < u64 > > ,
1214
+ expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
1120
1215
attempts : core:: cell:: RefCell < usize > ,
1121
1216
failing_on_attempt : Option < usize > ,
1122
1217
}
1123
1218
1219
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
1220
+ enum Amount {
1221
+ ForInvoiceOrRetry ( u64 ) ,
1222
+ Spontaneous ( u64 ) ,
1223
+ }
1224
+
1124
1225
impl TestPayer {
1125
1226
fn new ( ) -> Self {
1126
1227
Self {
@@ -1131,6 +1232,11 @@ mod tests {
1131
1232
}
1132
1233
1133
1234
fn expect_value_msat ( self , value_msat : u64 ) -> Self {
1235
+ self . expectations . borrow_mut ( ) . push_back ( Amount :: ForInvoiceOrRetry ( value_msat) ) ;
1236
+ self
1237
+ }
1238
+
1239
+ fn expect_send ( self , value_msat : Amount ) -> Self {
1134
1240
self . expectations . borrow_mut ( ) . push_back ( value_msat) ;
1135
1241
self
1136
1242
}
@@ -1153,10 +1259,9 @@ mod tests {
1153
1259
}
1154
1260
}
1155
1261
1156
- fn check_value_msats ( & self , route : & Route ) {
1262
+ fn check_value_msats ( & self , actual_value_msats : Amount ) {
1157
1263
let expected_value_msats = self . expectations . borrow_mut ( ) . pop_front ( ) ;
1158
1264
if let Some ( expected_value_msats) = expected_value_msats {
1159
- let actual_value_msats = route. get_total_amount ( ) ;
1160
1265
assert_eq ! ( actual_value_msats, expected_value_msats) ;
1161
1266
}
1162
1267
}
@@ -1191,7 +1296,20 @@ mod tests {
1191
1296
_payment_secret : & Option < PaymentSecret >
1192
1297
) -> Result < PaymentId , PaymentSendFailure > {
1193
1298
if self . check_attempts ( ) {
1194
- self . check_value_msats ( route) ;
1299
+ self . check_value_msats ( Amount :: ForInvoiceOrRetry ( route. get_total_amount ( ) ) ) ;
1300
+ Ok ( PaymentId ( [ 1 ; 32 ] ) )
1301
+ } else {
1302
+ Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
1303
+ }
1304
+ }
1305
+
1306
+ fn send_spontaneous_payment (
1307
+ & self ,
1308
+ route : & Route ,
1309
+ _payment_preimage : PaymentPreimage ,
1310
+ ) -> Result < PaymentId , PaymentSendFailure > {
1311
+ if self . check_attempts ( ) {
1312
+ self . check_value_msats ( Amount :: Spontaneous ( route. get_total_amount ( ) ) ) ;
1195
1313
Ok ( PaymentId ( [ 1 ; 32 ] ) )
1196
1314
} else {
1197
1315
Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
@@ -1202,7 +1320,7 @@ mod tests {
1202
1320
& self , route : & Route , _payment_id : PaymentId
1203
1321
) -> Result < ( ) , PaymentSendFailure > {
1204
1322
if self . check_attempts ( ) {
1205
- self . check_value_msats ( route) ;
1323
+ self . check_value_msats ( Amount :: ForInvoiceOrRetry ( route. get_total_amount ( ) ) ) ;
1206
1324
Ok ( ( ) )
1207
1325
} else {
1208
1326
Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
0 commit comments