Skip to content

Commit afe7ece

Browse files
committed
Introduce create_blinded_paths helpers in OffersMessageFlow
These functions will be used in the following commit to replace closure usage in Flow trait functions.
1 parent bf48767 commit afe7ece

File tree

2 files changed

+121
-5
lines changed

2 files changed

+121
-5
lines changed

lightning/src/ln/channelmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2842,7 +2842,7 @@ pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*7;
28422842
// scale them up to suit its security policy. At the network-level, we shouldn't constrain them too much,
28432843
// while avoiding to introduce a DoS vector. Further, a low CTLV_FAR_FAR_AWAY could be a source of
28442844
// routing failure for any HTLC sender picking up an LDK node among the first hops.
2845-
pub(super) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6;
2845+
pub(crate) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6;
28462846

28472847
/// Minimum CLTV difference between the current block height and received inbound payments.
28482848
/// Invoices generated for payment to us must set their `min_final_cltv_expiry_delta` field to at least

lightning/src/offers/flow.rs

+120-4
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,31 @@ use core::ops::Deref;
1414
use core::sync::atomic::{AtomicUsize, Ordering};
1515
use core::time::Duration;
1616

17-
use bitcoin::block::Header;
18-
use bitcoin::constants::ChainHash;
19-
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
20-
17+
use crate::blinded_path::message::{
18+
BlindedMessagePath, MessageContext, MessageForwardNode, OffersContext,
19+
};
20+
use crate::blinded_path::payment::{
21+
BlindedPaymentPath, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs,
22+
};
23+
use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
2124
use crate::chain::transaction::TransactionData;
2225
use crate::chain::{self, BestBlock};
26+
use crate::ln::channel_state::ChannelDetails;
27+
use crate::ln::channelmanager::{
28+
ChainParameters, CLTV_FAR_FAR_AWAY, MAX_SHORT_LIVED_RELATIVE_EXPIRY,
29+
};
2330
use crate::ln::inbound_payment;
31+
use crate::offers::nonce::Nonce;
2432
use crate::onion_message::async_payments::AsyncPaymentsMessage;
2533
use crate::onion_message::messenger::{MessageRouter, MessageSendInstructions};
2634
use crate::onion_message::offers::OffersMessage;
2735
use crate::routing::router::Router;
2836
use crate::sign::EntropySource;
2937
use crate::sync::{Mutex, RwLock};
38+
use bitcoin::block::Header;
39+
use bitcoin::constants::ChainHash;
40+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
41+
use lightning_invoice::PaymentSecret;
3042

3143
#[cfg(feature = "dnssec")]
3244
use crate::onion_message::dns_resolution::DNSResolverMessage;
@@ -144,6 +156,110 @@ where
144156
}
145157
}
146158

159+
impl<ES: Deref, MR: Deref, R: Deref> OffersMessageFlow<ES, MR, R>
160+
where
161+
ES::Target: EntropySource,
162+
MR::Target: MessageRouter,
163+
R::Target: Router,
164+
{
165+
/// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
166+
/// the path's intended lifetime.
167+
///
168+
/// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
169+
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
170+
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
171+
fn create_blinded_paths_using_absolute_expiry(
172+
&self, context: OffersContext, absolute_expiry: Option<Duration>,
173+
peers: Vec<MessageForwardNode>,
174+
) -> Result<Vec<BlindedMessagePath>, ()> {
175+
let now = self.duration_since_epoch();
176+
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
177+
178+
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
179+
self.create_compact_blinded_paths(peers, context)
180+
} else {
181+
self.create_blinded_paths(peers, MessageContext::Offers(context))
182+
}
183+
}
184+
185+
/// Creates a collection of blinded paths by delegating to
186+
/// [`MessageRouter::create_blinded_paths`].
187+
///
188+
/// Errors if the `MessageRouter` errors.
189+
fn create_blinded_paths(
190+
&self, peers: Vec<MessageForwardNode>, context: MessageContext,
191+
) -> Result<Vec<BlindedMessagePath>, ()> {
192+
let recipient = self.get_our_node_id();
193+
let secp_ctx = &self.secp_ctx;
194+
195+
let peers = peers.into_iter().map(|node| node.node_id).collect();
196+
197+
self.message_router
198+
.create_blinded_paths(recipient, context, peers, secp_ctx)
199+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
200+
}
201+
202+
/// Creates a collection of blinded paths by delegating to
203+
/// [`MessageRouter::create_compact_blinded_paths`].
204+
///
205+
/// Errors if the `MessageRouter` errors.
206+
fn create_compact_blinded_paths(
207+
&self, peers: Vec<MessageForwardNode>, context: OffersContext,
208+
) -> Result<Vec<BlindedMessagePath>, ()> {
209+
let recipient = self.get_our_node_id();
210+
let secp_ctx = &self.secp_ctx;
211+
212+
let peers = peers;
213+
214+
self.message_router
215+
.create_compact_blinded_paths(
216+
recipient,
217+
MessageContext::Offers(context),
218+
peers,
219+
secp_ctx,
220+
)
221+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
222+
}
223+
224+
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
225+
/// [`Router::create_blinded_payment_paths`].
226+
fn create_blinded_payment_paths(
227+
&self, usable_channels: Vec<ChannelDetails>, amount_msats: Option<u64>,
228+
payment_secret: PaymentSecret, payment_context: PaymentContext,
229+
relative_expiry_seconds: u32,
230+
) -> Result<Vec<BlindedPaymentPath>, ()> {
231+
let expanded_key = &self.inbound_payment_key;
232+
let entropy = &*self.entropy_source;
233+
let secp_ctx = &self.secp_ctx;
234+
235+
let first_hops = usable_channels;
236+
let payee_node_id = self.get_our_node_id();
237+
238+
// Assume shorter than usual block times to avoid spuriously failing payments too early.
239+
const SECONDS_PER_BLOCK: u32 = 9 * 60;
240+
let relative_expiry_blocks = relative_expiry_seconds / SECONDS_PER_BLOCK;
241+
let max_cltv_expiry = core::cmp::max(relative_expiry_blocks, CLTV_FAR_FAR_AWAY)
242+
.saturating_add(LATENCY_GRACE_PERIOD_BLOCKS)
243+
.saturating_add(self.best_block.read().unwrap().height);
244+
245+
let payee_tlvs = UnauthenticatedReceiveTlvs {
246+
payment_secret,
247+
payment_constraints: PaymentConstraints { max_cltv_expiry, htlc_minimum_msat: 1 },
248+
payment_context,
249+
};
250+
let nonce = Nonce::from_entropy_source(entropy);
251+
let payee_tlvs = payee_tlvs.authenticate(nonce, expanded_key);
252+
253+
self.router.create_blinded_payment_paths(
254+
payee_node_id,
255+
first_hops,
256+
payee_tlvs,
257+
amount_msats,
258+
secp_ctx,
259+
)
260+
}
261+
}
262+
147263
impl<ES: Deref, MR: Deref, R: Deref> chain::Listen for OffersMessageFlow<ES, MR, R>
148264
where
149265
ES::Target: EntropySource,

0 commit comments

Comments
 (0)