Skip to content

Commit 9f87a27

Browse files
committed
Define blinded path constructors in OffersMessageFlow
These functions will be used in the following commit to replace closure usage in Flow trait functions.
1 parent e69aaaa commit 9f87a27

File tree

2 files changed

+123
-4
lines changed

2 files changed

+123
-4
lines changed

lightning/src/ln/channelmanager.rs

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

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

lightning/src/offers/flow.rs

+122-3
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,32 @@ 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};
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;
2024

2125
#[allow(unused_imports)]
2226
use crate::prelude::*;
2327

2428
use crate::chain::BestBlock;
29+
use crate::ln::channel_state::ChannelDetails;
30+
use crate::ln::channelmanager::{CLTV_FAR_FAR_AWAY, MAX_SHORT_LIVED_RELATIVE_EXPIRY};
2531
use crate::ln::inbound_payment;
32+
use crate::offers::nonce::Nonce;
2633
use crate::onion_message::async_payments::AsyncPaymentsMessage;
2734
use crate::onion_message::messenger::{MessageRouter, MessageSendInstructions};
2835
use crate::onion_message::offers::OffersMessage;
36+
use crate::routing::router::Router;
37+
use crate::sign::EntropySource;
2938
use crate::sync::{Mutex, RwLock};
39+
use bitcoin::block::Header;
40+
use bitcoin::constants::ChainHash;
41+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
42+
use lightning_invoice::PaymentSecret;
3043

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

0 commit comments

Comments
 (0)