Skip to content

Commit 3eed178

Browse files
committed
end2end?
1 parent f317e66 commit 3eed178

File tree

3 files changed

+103
-12
lines changed

3 files changed

+103
-12
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,15 @@ pub enum AsyncPaymentsContext {
524524
/// [`Offer`]: crate::offers::offer::Offer
525525
payment_id: PaymentId,
526526
},
527+
/// Context contained within the reply [`BlindedMessagePath`] we put in outbound
528+
/// [`HeldHtlcAvailable`] messages, provided back to us in corresponding [`ReleaseHeldHtlc`]
529+
/// messages.
530+
OutboundHTLC {
531+
/// Incoming channel id of the HTLC that is being held.
532+
chan_id: u64,
533+
/// The HTLC id of the held HTLC on the incoming channel.
534+
htlc_id: u64,
535+
},
527536
/// Context contained within the [`BlindedMessagePath`]s we put in static invoices, provided back
528537
/// to us in corresponding [`HeldHtlcAvailable`] messages.
529538
///
@@ -599,6 +608,10 @@ impl_writeable_tlv_based_enum!(AsyncPaymentsContext,
599608
(2, invoice_id, required),
600609
(4, path_absolute_expiry, required),
601610
},
611+
(6, OutboundHTLC) => {
612+
(0, chan_id, required),
613+
(2, htlc_id, required),
614+
},
602615
);
603616

604617
/// Contains a simple nonce for use in a blinded path's context.

lightning/src/ln/channelmanager.rs

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ pub enum PendingHTLCRouting {
235235
blinded: Option<BlindedForward>,
236236
/// The absolute CLTV of the inbound HTLC
237237
incoming_cltv_expiry: Option<u32>,
238+
/// Signals that the HTLC should be held for release by an offline recipient.
238239
hold_htlc: bool,
239240
},
240241
/// An HTLC which should be forwarded on to another Trampoline node.
@@ -2558,6 +2559,7 @@ pub struct ChannelManager<
25582559
/// See `ChannelManager` struct-level documentation for lock order requirements.
25592560
pending_intercepted_htlcs: Mutex<HashMap<InterceptId, PendingAddHTLCInfo>>,
25602561

2562+
#[cfg(async_payments)]
25612563
pending_held_htlcs: Mutex<HashMap<(u64, u64), PendingAddHTLCInfo>>,
25622564

25632565
/// SCID/SCID Alias -> pending `update_add_htlc`s to decode.
@@ -3757,6 +3759,8 @@ where
37573759
decode_update_add_htlcs: Mutex::new(new_hash_map()),
37583760
claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }),
37593761
pending_intercepted_htlcs: Mutex::new(new_hash_map()),
3762+
#[cfg(async_payments)]
3763+
pending_held_htlcs: Mutex::new(new_hash_map()),
37603764
short_to_chan_info: FairRwLock::new(new_hash_map()),
37613765

37623766
our_network_pubkey,
@@ -6052,6 +6056,7 @@ where
60526056
Ok(())
60536057
}
60546058

6059+
#[cfg(async_payments)]
60556060
fn forward_held_htlc(&self, short_channel_id: u64, htlc_id: u64) -> Result<(), APIError> {
60566061
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
60576062

@@ -10314,11 +10319,44 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1031410319
let mut failed_intercept_forwards = Vec::new();
1031510320
if !pending_forwards.is_empty() {
1031610321
for (forward_info, prev_htlc_id) in pending_forwards.drain(..) {
10322+
// If this HTLC needs to be held for release by an offline recipient, we'll move it to a dedicated
10323+
// hash map for held HTLCs.
10324+
#[cfg(async_payments)]
1031710325
if let PendingHTLCRouting::Forward { hold_htlc: true, .. } =
1031810326
forward_info.routing
1031910327
{
1032010328
let mut held_htlcs = self.pending_held_htlcs.lock().unwrap();
10321-
held_htlcs.entry((prev_short_channel_id, prev_htlc_id));
10329+
held_htlcs.insert(
10330+
(prev_short_channel_id, prev_htlc_id),
10331+
PendingAddHTLCInfo {
10332+
prev_short_channel_id,
10333+
prev_counterparty_node_id,
10334+
prev_funding_outpoint,
10335+
prev_channel_id,
10336+
prev_htlc_id,
10337+
prev_user_channel_id,
10338+
forward_info,
10339+
},
10340+
);
10341+
10342+
// TODO: Where to get message paths from?!?
10343+
let message_paths = [];
10344+
10345+
self.flow.enqueue_held_forward_htlc_available(
10346+
prev_short_channel_id,
10347+
prev_htlc_id,
10348+
self.get_peers_for_blinded_path(),
10349+
&message_paths,
10350+
);
10351+
10352+
log_debug!(
10353+
self.logger,
10354+
"Holding HTLC {}:{} for release by an offline recipient",
10355+
prev_short_channel_id,
10356+
prev_htlc_id
10357+
);
10358+
10359+
continue;
1032210360
}
1032310361

1032410362
let scid = match forward_info.routing {
@@ -14387,19 +14425,30 @@ where
1438714425
fn handle_release_held_htlc(&self, _message: ReleaseHeldHtlc, _context: AsyncPaymentsContext) {
1438814426
#[cfg(async_payments)]
1438914427
{
14390-
let payment_id = match _context {
14391-
AsyncPaymentsContext::OutboundPayment { payment_id } => payment_id,
14428+
match _context {
14429+
AsyncPaymentsContext::OutboundPayment { payment_id } => {
14430+
if let Err(e) = self.send_payment_for_static_invoice(payment_id) {
14431+
log_trace!(
14432+
self.logger,
14433+
"Failed to release held HTLC with payment id {}: {:?}",
14434+
payment_id,
14435+
e
14436+
);
14437+
}
14438+
},
14439+
AsyncPaymentsContext::OutboundHTLC { chan_id, htlc_id } => {
14440+
if let Err(e) = self.forward_held_htlc(chan_id, htlc_id) {
14441+
log_trace!(
14442+
self.logger,
14443+
"Failed to release held forward HTLC {}:{} {:?}",
14444+
chan_id,
14445+
htlc_id,
14446+
e
14447+
);
14448+
}
14449+
},
1439214450
_ => return,
1439314451
};
14394-
14395-
if let Err(e) = self.send_payment_for_static_invoice(payment_id) {
14396-
log_trace!(
14397-
self.logger,
14398-
"Failed to release held HTLC with payment id {}: {:?}",
14399-
payment_id,
14400-
e
14401-
);
14402-
}
1440314452
}
1440414453
}
1440514454

@@ -16772,6 +16821,8 @@ where
1677216821
inbound_payment_key: expanded_inbound_key,
1677316822
pending_outbound_payments: pending_outbounds,
1677416823
pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()),
16824+
#[cfg(async_payments)]
16825+
pending_held_htlcs: Mutex::new(new_hash_map()), // TODO: Persistence.
1677516826

1677616827
forward_htlcs: Mutex::new(forward_htlcs),
1677716828
decode_update_add_htlcs: Mutex::new(decode_update_add_htlcs),

lightning/src/offers/flow.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,33 @@ where
11711171
Ok(())
11721172
}
11731173

1174+
/// Enqueues `held_htlc_available` onion messages to be sent to the payee for a held forward HTLC.
1175+
#[cfg(async_payments)]
1176+
pub fn enqueue_held_forward_htlc_available(
1177+
&self, chan_id: u64, htlc_id: u64, peers: Vec<MessageForwardNode>,
1178+
message_paths: &[BlindedMessagePath],
1179+
) -> Result<(), Bolt12SemanticError> {
1180+
let context =
1181+
MessageContext::AsyncPayments(AsyncPaymentsContext::OutboundHTLC { chan_id, htlc_id });
1182+
1183+
let reply_paths = self
1184+
.create_blinded_paths(peers, context)
1185+
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
1186+
1187+
let mut pending_async_payments_messages =
1188+
self.pending_async_payments_messages.lock().unwrap();
1189+
1190+
let message = AsyncPaymentsMessage::HeldHtlcAvailable(HeldHtlcAvailable {});
1191+
enqueue_onion_message_with_reply_paths(
1192+
message,
1193+
message_paths,
1194+
reply_paths,
1195+
&mut pending_async_payments_messages,
1196+
);
1197+
1198+
Ok(())
1199+
}
1200+
11741201
/// Enqueues the created [`DNSSECQuery`] to be sent to the counterparty.
11751202
///
11761203
/// # Peers

0 commit comments

Comments
 (0)