Skip to content

Commit 63c5624

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 e761270 commit 63c5624

File tree

2 files changed

+119
-5
lines changed

2 files changed

+119
-5
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-4
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,28 @@ 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::BestBlock;
25+
use crate::ln::channel_state::ChannelDetails;
26+
use crate::ln::channelmanager::{CLTV_FAR_FAR_AWAY, MAX_SHORT_LIVED_RELATIVE_EXPIRY};
2227
use crate::ln::inbound_payment;
28+
use crate::offers::nonce::Nonce;
2329
use crate::onion_message::async_payments::AsyncPaymentsMessage;
2430
use crate::onion_message::messenger::{MessageRouter, MessageSendInstructions};
2531
use crate::onion_message::offers::OffersMessage;
2632
use crate::routing::router::Router;
2733
use crate::sign::EntropySource;
2834
use crate::sync::{Mutex, RwLock};
35+
use bitcoin::block::Header;
36+
use bitcoin::constants::ChainHash;
37+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
38+
use lightning_invoice::PaymentSecret;
2939

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

0 commit comments

Comments
 (0)