27
27
//! # extern crate lightning_invoice;
28
28
//! # extern crate secp256k1;
29
29
//! #
30
- //! # use lightning::ln::{PaymentHash, PaymentSecret};
30
+ //! # use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
31
31
//! # use lightning::ln::channelmanager::{ChannelDetails, PaymentId, PaymentSendFailure};
32
32
//! # use lightning::ln::msgs::LightningError;
33
33
//! # use lightning::routing;
53
53
//! # fn send_payment(
54
54
//! # &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>
55
55
//! # ) -> Result<PaymentId, PaymentSendFailure> { unimplemented!() }
56
+ //! # fn send_spontaneous_payment(
57
+ //! # &self, route: &Route, payment_preimage: PaymentPreimage
58
+ //! # ) -> Result<PaymentId, PaymentSendFailure> { unimplemented!() }
56
59
//! # fn retry_payment(
57
60
//! # &self, route: &Route, payment_id: PaymentId
58
61
//! # ) -> Result<(), PaymentSendFailure> { unimplemented!() }
110
113
//! as updates to the network graph or changes to channel scores should be applied prior to
111
114
//! retries, typically by way of composing [`EventHandler`]s accordingly.
112
115
113
- use crate :: Invoice ;
116
+ use crate :: { DEFAULT_MIN_FINAL_CLTV_EXPIRY , Invoice } ;
114
117
115
118
use bitcoin_hashes:: Hash ;
119
+ use bitcoin_hashes:: sha256:: Hash as Sha256 ;
116
120
117
- use lightning:: ln:: { PaymentHash , PaymentSecret } ;
121
+ use lightning:: ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
118
122
use lightning:: ln:: channelmanager:: { ChannelDetails , PaymentId , PaymentSendFailure } ;
119
123
use lightning:: ln:: msgs:: LightningError ;
120
124
use lightning:: routing;
@@ -161,6 +165,11 @@ pub trait Payer {
161
165
& self , route : & Route , payment_hash : PaymentHash , payment_secret : & Option < PaymentSecret >
162
166
) -> Result < PaymentId , PaymentSendFailure > ;
163
167
168
+ /// Sends a spontaneous payment over the Lightning Network using the given [`Route`].
169
+ fn send_spontaneous_payment (
170
+ & self , route : & Route , payment_preimage : PaymentPreimage
171
+ ) -> Result < PaymentId , PaymentSendFailure > ;
172
+
164
173
/// Retries a failed payment path for the [`PaymentId`] using the given [`Route`].
165
174
fn retry_payment ( & self , route : & Route , payment_id : PaymentId ) -> Result < ( ) , PaymentSendFailure > ;
166
175
}
@@ -287,15 +296,47 @@ where
287
296
final_cltv_expiry_delta : invoice. min_final_cltv_expiry ( ) as u32 ,
288
297
} ;
289
298
290
- self . pay_internal ( & mut entry, & params, payment_hash, & payment_secret)
299
+ let send_payment = |route : & Route | {
300
+ self . payer . send_payment ( route, payment_hash, & payment_secret)
301
+ } ;
302
+ self . pay_internal ( & mut entry, & params, send_payment)
303
+ . map_err ( |e| { entry. remove ( ) ; e } )
304
+ }
305
+
306
+ /// Pays `pubkey` an amount using the hash of the given preimage, caching it for later use in
307
+ /// case a retry is needed.
308
+ ///
309
+ /// You should ensure that `payment_preimage` is unique and that its `payment_hash` has never
310
+ /// been paid before. Because [`InvoicePayer`] is stateless no effort is made to do so for you.
311
+ pub fn pay_pubkey (
312
+ & self , pubkey : PublicKey , payment_preimage : PaymentPreimage , amount_msats : u64
313
+ ) -> Result < PaymentId , PaymentError > {
314
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
315
+ let mut payment_cache = self . payment_cache . lock ( ) . unwrap ( ) ;
316
+ let mut entry = match payment_cache. entry ( payment_hash) {
317
+ hash_map:: Entry :: Occupied ( _) => return Err ( PaymentError :: Invoice ( "payment pending" ) ) ,
318
+ hash_map:: Entry :: Vacant ( _) => look_up_or_insert ! ( payment_cache, payment_hash) ,
319
+ } ;
320
+
321
+ let payee = Payee :: for_keysend ( pubkey) ;
322
+ let params = RouteParameters {
323
+ payee,
324
+ final_value_msat : amount_msats,
325
+ final_cltv_expiry_delta : DEFAULT_MIN_FINAL_CLTV_EXPIRY as u32 ,
326
+ } ;
327
+
328
+ let send_payment = |route : & Route | {
329
+ self . payer . send_spontaneous_payment ( route, payment_preimage)
330
+ } ;
331
+ self . pay_internal ( & mut entry, & params, send_payment)
291
332
. map_err ( |e| { entry. remove ( ) ; e } )
292
333
}
293
334
294
- fn pay_internal (
295
- & self , entry : & mut PaymentEntry , params : & RouteParameters , payment_hash : PaymentHash ,
296
- payment_secret : & Option < PaymentSecret > ,
335
+ fn pay_internal < F : FnOnce ( & Route ) -> Result < PaymentId , PaymentSendFailure > + Copy > (
336
+ & self , entry : & mut PaymentEntry , params : & RouteParameters , send_payment : F ,
297
337
) -> Result < PaymentId , PaymentError > {
298
338
if has_expired ( params) {
339
+ let payment_hash = entry. key ( ) ;
299
340
log_trace ! ( self . logger, "Invoice expired prior to send for payment {}" , log_bytes!( payment_hash. 0 ) ) ;
300
341
return Err ( PaymentError :: Invoice ( "Invoice expired prior to send" ) ) ;
301
342
}
@@ -309,7 +350,7 @@ where
309
350
& self . scorer . lock ( ) ,
310
351
) . map_err ( |e| PaymentError :: Routing ( e) ) ?;
311
352
312
- match self . payer . send_payment ( & route, payment_hash , payment_secret ) {
353
+ match send_payment ( & route) {
313
354
Ok ( payment_id) => Ok ( payment_id) ,
314
355
Err ( e) => match e {
315
356
PaymentSendFailure :: ParameterError ( _) => Err ( e) ,
@@ -320,7 +361,7 @@ where
320
361
Err ( e)
321
362
} else {
322
363
* retry_count += 1 ;
323
- Ok ( self . pay_internal ( entry, params, payment_hash , payment_secret ) ?)
364
+ Ok ( self . pay_internal ( entry, params, send_payment ) ?)
324
365
}
325
366
} ,
326
367
PaymentSendFailure :: PartialFailure { failed_paths_retry, payment_id, .. } => {
@@ -526,6 +567,10 @@ mod tests {
526
567
. unwrap ( )
527
568
}
528
569
570
+ fn pubkey ( ) -> PublicKey {
571
+ PublicKey :: from_slice ( & hex:: decode ( "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619" ) . unwrap ( ) [ ..] ) . unwrap ( )
572
+ }
573
+
529
574
#[ test]
530
575
fn pays_invoice_on_first_attempt ( ) {
531
576
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -981,6 +1026,55 @@ mod tests {
981
1026
}
982
1027
}
983
1028
1029
+ #[ test]
1030
+ fn pays_pubkey_with_amount ( ) {
1031
+ let event_handled = core:: cell:: RefCell :: new ( false ) ;
1032
+ let event_handler = |_: & _ | { * event_handled. borrow_mut ( ) = true ; } ;
1033
+
1034
+ let pubkey = pubkey ( ) ;
1035
+ let payment_preimage = PaymentPreimage ( [ 1 ; 32 ] ) ;
1036
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
1037
+ let final_value_msat = 100 ;
1038
+
1039
+ let payer = TestPayer :: new ( )
1040
+ . expect_send ( Amount :: Spontaneous ( final_value_msat) )
1041
+ . expect_send ( Amount :: ForInvoiceOrRetry ( final_value_msat) ) ;
1042
+ let router = TestRouter { } ;
1043
+ let scorer = RefCell :: new ( TestScorer :: new ( ) ) ;
1044
+ let logger = TestLogger :: new ( ) ;
1045
+ let invoice_payer =
1046
+ InvoicePayer :: new ( & payer, router, & scorer, & logger, event_handler, RetryAttempts ( 2 ) ) ;
1047
+
1048
+ let payment_id =
1049
+ Some ( invoice_payer. pay_pubkey ( pubkey, payment_preimage, final_value_msat) . unwrap ( ) ) ;
1050
+ assert_eq ! ( * payer. attempts. borrow( ) , 1 ) ;
1051
+
1052
+ let retry = RouteParameters {
1053
+ payee : Payee :: for_keysend ( pubkey) ,
1054
+ final_value_msat,
1055
+ final_cltv_expiry_delta : DEFAULT_MIN_FINAL_CLTV_EXPIRY as u32 ,
1056
+ } ;
1057
+ let event = Event :: PaymentPathFailed {
1058
+ payment_id,
1059
+ payment_hash,
1060
+ network_update : None ,
1061
+ rejected_by_dest : false ,
1062
+ all_paths_failed : false ,
1063
+ path : vec ! [ ] ,
1064
+ short_channel_id : None ,
1065
+ retry : Some ( retry) ,
1066
+ } ;
1067
+ invoice_payer. handle_event ( & event) ;
1068
+ assert_eq ! ( * event_handled. borrow( ) , false ) ;
1069
+ assert_eq ! ( * payer. attempts. borrow( ) , 2 ) ;
1070
+
1071
+ invoice_payer. handle_event ( & Event :: PaymentSent {
1072
+ payment_id, payment_preimage, payment_hash, fee_paid_msat : None
1073
+ } ) ;
1074
+ assert_eq ! ( * event_handled. borrow( ) , true ) ;
1075
+ assert_eq ! ( * payer. attempts. borrow( ) , 2 ) ;
1076
+ }
1077
+
984
1078
#[ test]
985
1079
fn scores_failed_channel ( ) {
986
1080
let event_handled = core:: cell:: RefCell :: new ( false ) ;
@@ -1128,11 +1222,17 @@ mod tests {
1128
1222
}
1129
1223
1130
1224
struct TestPayer {
1131
- expectations : core:: cell:: RefCell < VecDeque < u64 > > ,
1225
+ expectations : core:: cell:: RefCell < VecDeque < Amount > > ,
1132
1226
attempts : core:: cell:: RefCell < usize > ,
1133
1227
failing_on_attempt : Option < usize > ,
1134
1228
}
1135
1229
1230
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
1231
+ enum Amount {
1232
+ ForInvoiceOrRetry ( u64 ) ,
1233
+ Spontaneous ( u64 ) ,
1234
+ }
1235
+
1136
1236
impl TestPayer {
1137
1237
fn new ( ) -> Self {
1138
1238
Self {
@@ -1143,6 +1243,11 @@ mod tests {
1143
1243
}
1144
1244
1145
1245
fn expect_value_msat ( self , value_msat : u64 ) -> Self {
1246
+ self . expectations . borrow_mut ( ) . push_back ( Amount :: ForInvoiceOrRetry ( value_msat) ) ;
1247
+ self
1248
+ }
1249
+
1250
+ fn expect_send ( self , value_msat : Amount ) -> Self {
1146
1251
self . expectations . borrow_mut ( ) . push_back ( value_msat) ;
1147
1252
self
1148
1253
}
@@ -1165,10 +1270,9 @@ mod tests {
1165
1270
}
1166
1271
}
1167
1272
1168
- fn check_value_msats ( & self , route : & Route ) {
1273
+ fn check_value_msats ( & self , actual_value_msats : Amount ) {
1169
1274
let expected_value_msats = self . expectations . borrow_mut ( ) . pop_front ( ) ;
1170
1275
if let Some ( expected_value_msats) = expected_value_msats {
1171
- let actual_value_msats = route. get_total_amount ( ) ;
1172
1276
assert_eq ! ( actual_value_msats, expected_value_msats) ;
1173
1277
}
1174
1278
}
@@ -1203,7 +1307,20 @@ mod tests {
1203
1307
_payment_secret : & Option < PaymentSecret >
1204
1308
) -> Result < PaymentId , PaymentSendFailure > {
1205
1309
if self . check_attempts ( ) {
1206
- self . check_value_msats ( route) ;
1310
+ self . check_value_msats ( Amount :: ForInvoiceOrRetry ( route. get_total_amount ( ) ) ) ;
1311
+ Ok ( PaymentId ( [ 1 ; 32 ] ) )
1312
+ } else {
1313
+ Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
1314
+ }
1315
+ }
1316
+
1317
+ fn send_spontaneous_payment (
1318
+ & self ,
1319
+ route : & Route ,
1320
+ _payment_preimage : PaymentPreimage ,
1321
+ ) -> Result < PaymentId , PaymentSendFailure > {
1322
+ if self . check_attempts ( ) {
1323
+ self . check_value_msats ( Amount :: Spontaneous ( route. get_total_amount ( ) ) ) ;
1207
1324
Ok ( PaymentId ( [ 1 ; 32 ] ) )
1208
1325
} else {
1209
1326
Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
@@ -1214,7 +1331,7 @@ mod tests {
1214
1331
& self , route : & Route , _payment_id : PaymentId
1215
1332
) -> Result < ( ) , PaymentSendFailure > {
1216
1333
if self . check_attempts ( ) {
1217
- self . check_value_msats ( route) ;
1334
+ self . check_value_msats ( Amount :: ForInvoiceOrRetry ( route. get_total_amount ( ) ) ) ;
1218
1335
Ok ( ( ) )
1219
1336
} else {
1220
1337
Err ( PaymentSendFailure :: ParameterError ( APIError :: MonitorUpdateFailed ) )
0 commit comments