@@ -18,6 +18,7 @@ use crate::events::{self, PaymentFailureReason};
18
18
use crate :: ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
19
19
use crate :: ln:: channelmanager:: { ChannelDetails , EventCompletionAction , HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , INVOICE_REQUEST_TIMEOUT_TICKS , PaymentId } ;
20
20
use crate :: ln:: onion_utils:: { DecodedOnionFailure , HTLCFailReason } ;
21
+ use crate :: offers:: invoice:: Bolt12Invoice ;
21
22
use crate :: routing:: router:: { InFlightHtlcs , Path , PaymentParameters , Route , RouteParameters , Router } ;
22
23
use crate :: util:: errors:: APIError ;
23
24
use crate :: util:: logger:: Logger ;
@@ -356,6 +357,10 @@ pub enum RetryableSendFailure {
356
357
/// [`Event::PaymentSent`]: crate::events::Event::PaymentSent
357
358
/// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed
358
359
DuplicatePayment ,
360
+ /// Indicates that a payment for the provided [`PaymentId`] was unexpected, either because the
361
+ /// invoice was not explicitly requested (or for a known refund) or the invoice was not received
362
+ /// in time (or was already paid).
363
+ UnexpectedPayment ,
359
364
}
360
365
361
366
/// If a payment fails to send with [`ChannelManager::send_payment_with_route`], it can be in one
@@ -565,6 +570,8 @@ pub(super) struct SendAlongPathArgs<'a> {
565
570
pub session_priv_bytes : [ u8 ; 32 ] ,
566
571
}
567
572
573
+ const BOLT_12_INVOICE_RETRY_STRATEGY : Retry = Retry :: Attempts ( 3 ) ;
574
+
568
575
pub ( super ) struct OutboundPayments {
569
576
pub ( super ) pending_outbound_payments : Mutex < HashMap < PaymentId , PendingOutboundPayment > > ,
570
577
pub ( super ) retry_lock : Mutex < ( ) > ,
@@ -598,6 +605,84 @@ impl OutboundPayments {
598
605
best_block_height, logger, pending_events, & send_payment_along_path)
599
606
}
600
607
608
+ pub ( super ) fn send_payment_for_bolt12_invoice < R : Deref , ES : Deref , NS : Deref , IH , SP , L : Deref > (
609
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId , router : & R ,
610
+ first_hops : Vec < ChannelDetails > , inflight_htlcs : IH , entropy_source : & ES , node_signer : & NS ,
611
+ best_block_height : u32 , logger : & L ,
612
+ pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > ,
613
+ send_payment_along_path : SP ,
614
+ ) -> Result < ( ) , RetryableSendFailure >
615
+ where
616
+ R :: Target : Router ,
617
+ ES :: Target : EntropySource ,
618
+ NS :: Target : NodeSigner ,
619
+ L :: Target : Logger ,
620
+ IH : Fn ( ) -> InFlightHtlcs ,
621
+ SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
622
+ {
623
+ let payment_hash = invoice. payment_hash ( ) ;
624
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
625
+ hash_map:: Entry :: Occupied ( entry) if entry. get ( ) . is_awaiting_invoice ( ) => {
626
+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived { payment_hash } ;
627
+ } ,
628
+ hash_map:: Entry :: Occupied ( _) => return Err ( RetryableSendFailure :: DuplicatePayment ) ,
629
+ hash_map:: Entry :: Vacant ( _) => return Err ( RetryableSendFailure :: UnexpectedPayment ) ,
630
+ } ;
631
+
632
+ #[ cfg( feature = "std" ) ] {
633
+ if invoice. is_expired ( ) {
634
+ log_error ! ( logger, "Invoice expired, abandoning payment {}" , & payment_id) ;
635
+ self . abandon_payment ( payment_id, PaymentFailureReason :: PaymentExpired , pending_events) ;
636
+ return Err ( RetryableSendFailure :: PaymentExpired ) ;
637
+ }
638
+ }
639
+
640
+ let recipient_onion = RecipientOnionFields {
641
+ payment_secret : None ,
642
+ payment_metadata : None ,
643
+ custom_tlvs : vec ! [ ] ,
644
+ } ;
645
+ let route_params = RouteParameters {
646
+ payment_params : PaymentParameters :: from_bolt12_invoice ( & invoice) ,
647
+ final_value_msat : invoice. amount_msats ( ) ,
648
+ } ;
649
+
650
+ let route = match router. find_route_with_id (
651
+ & node_signer. get_node_id ( Recipient :: Node ) . unwrap ( ) , & route_params,
652
+ Some ( & first_hops. iter ( ) . collect :: < Vec < _ > > ( ) ) , inflight_htlcs ( ) , payment_hash, payment_id
653
+ ) {
654
+ Ok ( route) => route,
655
+ Err ( e) => {
656
+ log_error ! (
657
+ logger, "Failed to find a route when sending, abandoning payment {}: {:#?}" ,
658
+ & payment_id, e
659
+ ) ;
660
+ self . abandon_payment ( payment_id, PaymentFailureReason :: RouteNotFound , pending_events) ;
661
+ return Err ( RetryableSendFailure :: RouteNotFound ) ;
662
+ }
663
+ } ;
664
+
665
+ let onion_session_privs = self . add_new_pending_bolt12_payment (
666
+ recipient_onion. clone ( ) , payment_id, None , & route, Some ( BOLT_12_INVOICE_RETRY_STRATEGY ) ,
667
+ Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height
668
+ ) ?;
669
+ let pay_result = self . pay_route_internal (
670
+ & route, payment_hash, recipient_onion, None , payment_id, None , onion_session_privs,
671
+ node_signer, best_block_height, & send_payment_along_path
672
+ ) ;
673
+ log_info ! ( logger, "Result sending payment with id {}: {:?}" , & payment_id, pay_result) ;
674
+
675
+ if let Err ( e) = pay_result {
676
+ self . handle_pay_route_err (
677
+ e, payment_id, payment_hash, route, route_params, router, first_hops,
678
+ & inflight_htlcs, entropy_source, node_signer, best_block_height, logger,
679
+ pending_events, & send_payment_along_path
680
+ ) ;
681
+ }
682
+
683
+ Ok ( ( ) )
684
+ }
685
+
601
686
pub ( super ) fn send_payment_with_route < ES : Deref , NS : Deref , F > (
602
687
& self , route : & Route , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields ,
603
688
payment_id : PaymentId , entropy_source : & ES , node_signer : & NS , best_block_height : u32 ,
@@ -1051,40 +1136,78 @@ impl OutboundPayments {
1051
1136
keysend_preimage : Option < PaymentPreimage > , route : & Route , retry_strategy : Option < Retry > ,
1052
1137
payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1053
1138
) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
1054
- let mut onion_session_privs = Vec :: with_capacity ( route. paths . len ( ) ) ;
1055
- for _ in 0 ..route. paths . len ( ) {
1056
- onion_session_privs. push ( entropy_source. get_secure_random_bytes ( ) ) ;
1057
- }
1058
-
1059
1139
let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1060
1140
match pending_outbounds. entry ( payment_id) {
1061
1141
hash_map:: Entry :: Occupied ( _) => Err ( PaymentSendFailure :: DuplicatePayment ) ,
1062
1142
hash_map:: Entry :: Vacant ( entry) => {
1063
- let payment = entry. insert ( PendingOutboundPayment :: Retryable {
1064
- retry_strategy,
1065
- attempts : PaymentAttempts :: new ( ) ,
1066
- payment_params,
1067
- session_privs : HashSet :: new ( ) ,
1068
- pending_amt_msat : 0 ,
1069
- pending_fee_msat : Some ( 0 ) ,
1070
- payment_hash,
1071
- payment_secret : recipient_onion. payment_secret ,
1072
- payment_metadata : recipient_onion. payment_metadata ,
1073
- keysend_preimage,
1074
- custom_tlvs : recipient_onion. custom_tlvs ,
1075
- starting_block_height : best_block_height,
1076
- total_msat : route. get_total_amount ( ) ,
1077
- } ) ;
1078
-
1079
- for ( path, session_priv_bytes) in route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) {
1080
- assert ! ( payment. insert( * session_priv_bytes, path) ) ;
1081
- }
1082
-
1143
+ let ( payment, onion_session_privs) = self . create_pending_payment (
1144
+ payment_hash, recipient_onion, keysend_preimage, route, retry_strategy,
1145
+ payment_params, entropy_source, best_block_height
1146
+ ) ;
1147
+ entry. insert ( payment) ;
1083
1148
Ok ( onion_session_privs)
1084
1149
} ,
1085
1150
}
1086
1151
}
1087
1152
1153
+ pub ( super ) fn add_new_pending_bolt12_payment < ES : Deref > (
1154
+ & self , recipient_onion : RecipientOnionFields , payment_id : PaymentId ,
1155
+ keysend_preimage : Option < PaymentPreimage > , route : & Route , retry_strategy : Option < Retry > ,
1156
+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1157
+ ) -> Result < Vec < [ u8 ; 32 ] > , RetryableSendFailure > where ES :: Target : EntropySource {
1158
+ let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1159
+ match pending_outbounds. entry ( payment_id) {
1160
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1161
+ PendingOutboundPayment :: InvoiceReceived { payment_hash } => {
1162
+ let ( payment, onion_session_privs) = self . create_pending_payment (
1163
+ * payment_hash, recipient_onion, keysend_preimage, route, retry_strategy,
1164
+ payment_params, entropy_source, best_block_height
1165
+ ) ;
1166
+ * entry. into_mut ( ) = payment;
1167
+ Ok ( onion_session_privs)
1168
+ } ,
1169
+ _ => Err ( RetryableSendFailure :: DuplicatePayment ) ,
1170
+ } ,
1171
+ hash_map:: Entry :: Vacant ( _) => Err ( RetryableSendFailure :: UnexpectedPayment ) ,
1172
+ }
1173
+ }
1174
+
1175
+ fn create_pending_payment < ES : Deref > (
1176
+ & self , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields ,
1177
+ keysend_preimage : Option < PaymentPreimage > , route : & Route , retry_strategy : Option < Retry > ,
1178
+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1179
+ ) -> ( PendingOutboundPayment , Vec < [ u8 ; 32 ] > )
1180
+ where
1181
+ ES :: Target : EntropySource ,
1182
+ {
1183
+ let mut onion_session_privs = Vec :: with_capacity ( route. paths . len ( ) ) ;
1184
+ for _ in 0 ..route. paths . len ( ) {
1185
+ onion_session_privs. push ( entropy_source. get_secure_random_bytes ( ) ) ;
1186
+ }
1187
+
1188
+ let mut payment = PendingOutboundPayment :: Retryable {
1189
+ retry_strategy,
1190
+ attempts : PaymentAttempts :: new ( ) ,
1191
+ payment_params,
1192
+ session_privs : HashSet :: new ( ) ,
1193
+ pending_amt_msat : 0 ,
1194
+ pending_fee_msat : Some ( 0 ) ,
1195
+ payment_hash,
1196
+ payment_secret : recipient_onion. payment_secret ,
1197
+ payment_metadata : recipient_onion. payment_metadata ,
1198
+ keysend_preimage,
1199
+ custom_tlvs : recipient_onion. custom_tlvs ,
1200
+ starting_block_height : best_block_height,
1201
+ total_msat : route. get_total_amount ( ) ,
1202
+ } ;
1203
+
1204
+ for ( path, session_priv_bytes) in route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) {
1205
+ assert ! ( payment. insert( * session_priv_bytes, path) ) ;
1206
+ }
1207
+
1208
+ ( payment, onion_session_privs)
1209
+ }
1210
+
1088
1211
#[ allow( unused) ]
1089
1212
pub ( super ) fn add_new_awaiting_invoice ( & self , payment_id : PaymentId ) -> Result < ( ) , ( ) > {
1090
1213
let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
0 commit comments