Skip to content

Commit 1d3248f

Browse files
Support creating reply_path for HeldHtlcAvailable
As part of supporting sending payments as an often-offline sender, the sender needs to send held_htlc_available onion messages such that the reply path to the message terminates at their always-online channel counterparty that is holding the HTLC. That way when the recipient responds with release_held_htlc, the sender's counterparty will receive that message. Here we add a method for creating said reply path, which will be used in the next commit.
1 parent 6264eec commit 1d3248f

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode,
1919
use crate::crypto::streams::ChaChaPolyReadAdapter;
2020
use crate::io;
2121
use crate::io::Cursor;
22-
use crate::ln::channelmanager::PaymentId;
22+
use crate::ln::channelmanager::{InterceptId, PaymentId};
2323
use crate::ln::msgs::DecodeError;
2424
use crate::ln::onion_utils;
2525
use crate::offers::nonce::Nonce;
@@ -556,7 +556,7 @@ pub enum AsyncPaymentsContext {
556556
},
557557
/// Context contained within the reply [`BlindedMessagePath`] we put in outbound
558558
/// [`HeldHtlcAvailable`] messages, provided back to us in corresponding [`ReleaseHeldHtlc`]
559-
/// messages.
559+
/// messages if we are an always-online sender paying an async recipient.
560560
///
561561
/// [`HeldHtlcAvailable`]: crate::onion_message::async_payments::HeldHtlcAvailable
562562
/// [`ReleaseHeldHtlc`]: crate::onion_message::async_payments::ReleaseHeldHtlc
@@ -577,6 +577,17 @@ pub enum AsyncPaymentsContext {
577577
/// able to trivially ask if we're online forever.
578578
path_absolute_expiry: core::time::Duration,
579579
},
580+
/// Context contained within the reply [`BlindedMessagePath`] put in outbound
581+
/// [`HeldHtlcAvailable`] messages, provided back to the async sender's always-online counterparty
582+
/// in corresponding [`ReleaseHeldHtlc`] messages.
583+
///
584+
/// [`HeldHtlcAvailable`]: crate::onion_message::async_payments::HeldHtlcAvailable
585+
/// [`ReleaseHeldHtlc`]: crate::onion_message::async_payments::ReleaseHeldHtlc
586+
ReleaseHeldHtlc {
587+
/// An identifier for the HTLC that should be released by us as the sender's always-online
588+
/// channel counterparty to the often-offline recipient.
589+
intercept_id: InterceptId,
590+
},
580591
}
581592

582593
impl_writeable_tlv_based_enum!(MessageContext,
@@ -632,6 +643,9 @@ impl_writeable_tlv_based_enum!(AsyncPaymentsContext,
632643
(2, invoice_slot, required),
633644
(4, path_absolute_expiry, required),
634645
},
646+
(6, ReleaseHeldHtlc) => {
647+
(0, intercept_id, required),
648+
},
635649
);
636650

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

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5450,6 +5450,18 @@ where
54505450
res
54515451
}
54525452

5453+
/// If we are holding an HTLC on behalf of an often-offline sender, this method allows us to
5454+
/// create a path for the sender to use as the reply path when they send the recipient a
5455+
/// [`HeldHtlcAvailable`] onion message, so the recipient's [`ReleaseHeldHtlc`] response will be
5456+
/// received to our node.
5457+
fn path_for_release_held_htlc(
5458+
&self, htlc_id: u64, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
5459+
) -> BlindedMessagePath {
5460+
let intercept_id =
5461+
InterceptId::from_htlc_id_and_chan_id(htlc_id, channel_id, counterparty_node_id);
5462+
self.flow.path_for_release_held_htlc(intercept_id, &*self.entropy_source)
5463+
}
5464+
54535465
/// Signals that no further attempts for the given payment should occur. Useful if you have a
54545466
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
54555467
/// retries are exhausted.

lightning/src/offers/flow.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::prelude::*;
3232

3333
use crate::chain::BestBlock;
3434
use crate::ln::channel_state::ChannelDetails;
35-
use crate::ln::channelmanager::{PaymentId, CLTV_FAR_FAR_AWAY};
35+
use crate::ln::channelmanager::{InterceptId, PaymentId, CLTV_FAR_FAR_AWAY};
3636
use crate::ln::inbound_payment;
3737
use crate::offers::async_receive_offer_cache::AsyncReceiveOfferCache;
3838
use crate::offers::invoice::{
@@ -52,7 +52,7 @@ use crate::onion_message::async_payments::{
5252
StaticInvoicePersisted,
5353
};
5454
use crate::onion_message::messenger::{
55-
Destination, MessageRouter, MessageSendInstructions, Responder,
55+
Destination, MessageRouter, MessageSendInstructions, Responder, PADDED_PATH_LENGTH,
5656
};
5757
use crate::onion_message::offers::OffersMessage;
5858
use crate::onion_message::packet::OnionMessageContents;
@@ -1154,6 +1154,41 @@ where
11541154
Ok(())
11551155
}
11561156

1157+
/// If we are holding an HTLC on behalf of an often-offline sender, this method allows us to
1158+
/// create a path for the sender to use as the reply path when they send the recipient a
1159+
/// [`HeldHtlcAvailable`] onion message, so the recipient's [`ReleaseHeldHtlc`] response will be
1160+
/// received to our node.
1161+
///
1162+
/// [`ReleaseHeldHtlc`]: crate::onion_message::async_payments::ReleaseHeldHtlc
1163+
pub fn path_for_release_held_htlc<ES: Deref>(
1164+
&self, intercept_id: InterceptId, entropy: ES,
1165+
) -> BlindedMessagePath
1166+
where
1167+
ES::Target: EntropySource,
1168+
{
1169+
let peers = self.peers_cache.lock().unwrap().clone();
1170+
let context =
1171+
MessageContext::AsyncPayments(AsyncPaymentsContext::ReleaseHeldHtlc { intercept_id });
1172+
if let Ok(mut paths) = self.create_blinded_paths(peers, context.clone()) {
1173+
if let Some(path) = paths.pop() {
1174+
return path;
1175+
}
1176+
}
1177+
1178+
// If the `MessageRouter` fails on blinded path creation, fall back to creating a 1-hop blinded
1179+
// path.
1180+
let num_dummy_hops = PADDED_PATH_LENGTH.saturating_sub(1);
1181+
BlindedMessagePath::new_with_dummy_hops(
1182+
&[],
1183+
self.get_our_node_id(),
1184+
num_dummy_hops,
1185+
self.receive_auth_key,
1186+
context,
1187+
&*entropy,
1188+
&self.secp_ctx,
1189+
)
1190+
}
1191+
11571192
/// Enqueues the created [`DNSSECQuery`] to be sent to the counterparty.
11581193
///
11591194
/// # Peers

0 commit comments

Comments
 (0)