Skip to content

Commit 373ab06

Browse files
Support sending async payments as an always-online sender.
Async receive is not yet supported.
1 parent 2ed6219 commit 373ab06

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4075,6 +4075,21 @@ where
40754075
Ok(())
40764076
}
40774077

4078+
#[cfg(async_payments)]
4079+
fn send_payment_for_static_invoice(
4080+
&self, payment_id: PaymentId, payment_release_secret: [u8; 32]
4081+
) -> Result<(), Bolt12PaymentError> {
4082+
let best_block_height = self.best_block.read().unwrap().height;
4083+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4084+
self.pending_outbound_payments
4085+
.send_payment_for_static_invoice(
4086+
payment_id, payment_release_secret, &self.router, self.list_usable_channels(),
4087+
|| self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer,
4088+
best_block_height, &self.logger, &self.pending_events,
4089+
|args| self.send_payment_along_path(args)
4090+
)
4091+
}
4092+
40784093
/// Signals that no further attempts for the given payment should occur. Useful if you have a
40794094
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
40804095
/// retries are exhausted.
@@ -10466,7 +10481,17 @@ where
1046610481
ResponseInstruction::NoResponse
1046710482
}
1046810483

10469-
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _payment_id: Option<PaymentId>) {}
10484+
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _payment_id: Option<PaymentId>) {
10485+
#[cfg(async_payments)] {
10486+
let payment_id = if let Some(id) = _payment_id { id } else { return };
10487+
if let Err(e) = self.send_payment_for_static_invoice(payment_id, _message.payment_release_secret) {
10488+
log_trace!(
10489+
self.logger, "Failed to release held HTLC with payment id {} and release secret {:02x?}: {:?}",
10490+
payment_id, _message.payment_release_secret, e
10491+
);
10492+
}
10493+
}
10494+
}
1047010495

1047110496
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
1047210497
core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap())

lightning/src/ln/outbound_payment.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,47 @@ impl OutboundPayments {
898898
};
899899
}
900900

901+
#[cfg(async_payments)]
902+
pub(super) fn send_payment_for_static_invoice<R: Deref, ES: Deref, NS: Deref, IH, SP, L: Deref>(
903+
&self, payment_id: PaymentId, payment_release_secret: [u8; 32], router: &R,
904+
first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
905+
best_block_height: u32, logger: &L,
906+
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>,
907+
send_payment_along_path: SP,
908+
) -> Result<(), Bolt12PaymentError>
909+
where
910+
R::Target: Router,
911+
ES::Target: EntropySource,
912+
NS::Target: NodeSigner,
913+
L::Target: Logger,
914+
IH: Fn() -> InFlightHtlcs,
915+
SP: Fn(SendAlongPathArgs) -> Result<(), APIError>,
916+
{
917+
let (payment_hash, route_params) =
918+
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
919+
hash_map::Entry::Occupied(entry) => match entry.get() {
920+
PendingOutboundPayment::StaticInvoiceReceived {
921+
payment_hash, payment_release_secret: release_secret, route_params, ..
922+
} => {
923+
if payment_release_secret != *release_secret {
924+
return Err(Bolt12PaymentError::UnexpectedInvoice)
925+
}
926+
(*payment_hash, route_params.clone())
927+
},
928+
_ => return Err(Bolt12PaymentError::DuplicateInvoice),
929+
},
930+
hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice),
931+
};
932+
933+
self.find_route_and_send_payment(
934+
payment_hash, payment_id, route_params, router, first_hops, &inflight_htlcs,
935+
entropy_source, node_signer, best_block_height, logger, pending_events,
936+
&send_payment_along_path
937+
);
938+
939+
Ok(())
940+
}
941+
901942
pub(super) fn check_retry_payments<R: Deref, ES: Deref, NS: Deref, SP, IH, FH, L: Deref>(
902943
&self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
903944
best_block_height: u32,
@@ -1163,7 +1204,20 @@ impl OutboundPayments {
11631204
*payment.into_mut() = retryable_payment;
11641205
(recipient_onion, None, onion_session_privs)
11651206
},
1166-
PendingOutboundPayment::StaticInvoiceReceived { .. } => todo!(),
1207+
PendingOutboundPayment::StaticInvoiceReceived {
1208+
payment_hash, keysend_preimage, retry_strategy, ..
1209+
} => {
1210+
let keysend_preimage = Some(*keysend_preimage);
1211+
let recipient_onion = RecipientOnionFields::spontaneous_empty();
1212+
let retry_strategy = Some(*retry_strategy);
1213+
let payment_params = Some(route_params.payment_params.clone());
1214+
let (retryable_payment, onion_session_privs) = self.create_pending_payment(
1215+
*payment_hash, recipient_onion.clone(), keysend_preimage, &route,
1216+
retry_strategy, payment_params, entropy_source, best_block_height
1217+
);
1218+
*payment.into_mut() = retryable_payment;
1219+
(recipient_onion, keysend_preimage, onion_session_privs)
1220+
},
11671221
PendingOutboundPayment::Fulfilled { .. } => {
11681222
log_error!(logger, "Payment already completed");
11691223
return

0 commit comments

Comments
 (0)