Skip to content

Commit 9184ce7

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 9bafa56 commit 9184ce7

File tree

2 files changed

+119
-4
lines changed

2 files changed

+119
-4
lines changed

lightning/src/ln/channelmanager.rs

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

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

lightning/src/offers/flow.rs

+118-3
Original file line numberDiff line numberDiff line change
@@ -14,21 +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;
2936
use crate::routing::router::Router;
3037
use crate::sign::EntropySource;
3138
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;
3243

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

0 commit comments

Comments
 (0)