Skip to content

Commit ceee321

Browse files
Support sending async payments as an always-online sender.
Async receive is not yet supported.
1 parent d3de51b commit ceee321

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4344,6 +4344,21 @@ where
43444344
res
43454345
}
43464346

4347+
#[cfg(async_payments)]
4348+
fn send_payment_for_static_invoice(
4349+
&self, payment_id: PaymentId, payment_release_secret: [u8; 32]
4350+
) -> Result<(), Bolt12PaymentError> {
4351+
let best_block_height = self.best_block.read().unwrap().height;
4352+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4353+
self.pending_outbound_payments
4354+
.send_payment_for_static_invoice(
4355+
payment_id, payment_release_secret, &self.router, self.list_usable_channels(),
4356+
|| self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer,
4357+
best_block_height, &self.logger, &self.pending_events,
4358+
|args| self.send_payment_along_path(args)
4359+
)
4360+
}
4361+
43474362
/// Signals that no further attempts for the given payment should occur. Useful if you have a
43484363
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
43494364
/// retries are exhausted.
@@ -11069,7 +11084,17 @@ where
1106911084
None
1107011085
}
1107111086

11072-
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {}
11087+
fn release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {
11088+
#[cfg(async_payments)] {
11089+
let AsyncPaymentsContext::OutboundPayment { payment_id } = _context;
11090+
if let Err(e) = self.send_payment_for_static_invoice(payment_id, _message.payment_release_secret) {
11091+
log_trace!(
11092+
self.logger, "Failed to release held HTLC with payment id {} and release secret {:02x?}: {:?}",
11093+
payment_id, _message.payment_release_secret, e
11094+
);
11095+
}
11096+
}
11097+
}
1107311098

1107411099
fn release_pending_messages(&self) -> Vec<(AsyncPaymentsMessage, MessageSendInstructions)> {
1107511100
core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap())

lightning/src/ln/outbound_payment.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,47 @@ impl OutboundPayments {
986986
};
987987
}
988988

989+
#[cfg(async_payments)]
990+
pub(super) fn send_payment_for_static_invoice<R: Deref, ES: Deref, NS: Deref, IH, SP, L: Deref>(
991+
&self, payment_id: PaymentId, payment_release_secret: [u8; 32], router: &R,
992+
first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
993+
best_block_height: u32, logger: &L,
994+
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>,
995+
send_payment_along_path: SP,
996+
) -> Result<(), Bolt12PaymentError>
997+
where
998+
R::Target: Router,
999+
ES::Target: EntropySource,
1000+
NS::Target: NodeSigner,
1001+
L::Target: Logger,
1002+
IH: Fn() -> InFlightHtlcs,
1003+
SP: Fn(SendAlongPathArgs) -> Result<(), APIError>,
1004+
{
1005+
let (payment_hash, route_params) =
1006+
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
1007+
hash_map::Entry::Occupied(entry) => match entry.get() {
1008+
PendingOutboundPayment::StaticInvoiceReceived {
1009+
payment_hash, payment_release_secret: release_secret, route_params, ..
1010+
} => {
1011+
if payment_release_secret != *release_secret {
1012+
return Err(Bolt12PaymentError::UnexpectedInvoice)
1013+
}
1014+
(*payment_hash, route_params.clone())
1015+
},
1016+
_ => return Err(Bolt12PaymentError::DuplicateInvoice),
1017+
},
1018+
hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice),
1019+
};
1020+
1021+
self.find_route_and_send_payment(
1022+
payment_hash, payment_id, route_params, router, first_hops, &inflight_htlcs,
1023+
entropy_source, node_signer, best_block_height, logger, pending_events,
1024+
&send_payment_along_path
1025+
);
1026+
1027+
Ok(())
1028+
}
1029+
9891030
pub(super) fn check_retry_payments<R: Deref, ES: Deref, NS: Deref, SP, IH, FH, L: Deref>(
9901031
&self, router: &R, first_hops: FH, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS,
9911032
best_block_height: u32,
@@ -1265,7 +1306,21 @@ impl OutboundPayments {
12651306
debug_assert!(false);
12661307
return
12671308
},
1268-
PendingOutboundPayment::StaticInvoiceReceived { .. } => todo!(),
1309+
PendingOutboundPayment::StaticInvoiceReceived {
1310+
payment_hash, keysend_preimage, retry_strategy, ..
1311+
} => {
1312+
let keysend_preimage = Some(*keysend_preimage);
1313+
let total_amount = route_params.final_value_msat;
1314+
let recipient_onion = RecipientOnionFields::spontaneous_empty();
1315+
let retry_strategy = Some(*retry_strategy);
1316+
let payment_params = Some(route_params.payment_params.clone());
1317+
let (retryable_payment, onion_session_privs) = self.create_pending_payment(
1318+
*payment_hash, recipient_onion.clone(), keysend_preimage, &route,
1319+
retry_strategy, payment_params, entropy_source, best_block_height
1320+
);
1321+
*payment.into_mut() = retryable_payment;
1322+
(total_amount, recipient_onion, keysend_preimage, onion_session_privs)
1323+
},
12691324
PendingOutboundPayment::Fulfilled { .. } => {
12701325
log_error!(logger, "Payment already completed");
12711326
return

0 commit comments

Comments
 (0)