Skip to content

Commit 6ee1be2

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 91181d8 commit 6ee1be2

File tree

5 files changed

+122
-16
lines changed

5 files changed

+122
-16
lines changed

lightning-background-processor/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1584,8 +1584,10 @@ mod tests {
15841584
network_graph.clone(),
15851585
Arc::clone(&keys_manager),
15861586
));
1587+
let best_block = BestBlock::from_network(network);
1588+
let params = ChainParameters { network, best_block };
15871589
let flow = Arc::new(OffersMessageFlow::new(
1588-
network,
1590+
params,
15891591
keys_manager.get_node_id(Recipient::Node).unwrap(),
15901592
genesis_block.header.time,
15911593
keys_manager.get_inbound_payment_key(),
@@ -1605,8 +1607,6 @@ mod tests {
16051607
fee_estimator.clone(),
16061608
kv_store.clone(),
16071609
));
1608-
let best_block = BestBlock::from_network(network);
1609-
let params = ChainParameters { network, best_block };
16101610
let manager = Arc::new(ChannelManager::new(
16111611
fee_estimator.clone(),
16121612
chain_monitor.clone(),

lightning-liquidity/tests/common/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,12 @@ pub(crate) fn create_liquidity_node(
444444
));
445445
let msg_router =
446446
Arc::new(DefaultMessageRouter::new(Arc::clone(&network_graph), Arc::clone(&keys_manager)));
447+
448+
let best_block = BestBlock::from_network(network);
449+
let chain_params = ChainParameters { network, best_block };
450+
447451
let flow = Arc::new(OffersMessageFlow::new(
448-
network,
452+
chain_params,
449453
keys_manager.get_node_id(Recipient::Node).unwrap(),
450454
genesis_block.header.time,
451455
keys_manager.get_inbound_payment_key(),
@@ -463,8 +467,6 @@ pub(crate) fn create_liquidity_node(
463467
fee_estimator.clone(),
464468
kv_store.clone(),
465469
));
466-
let best_block = BestBlock::from_network(network);
467-
let chain_params = ChainParameters { network, best_block };
468470
let channel_manager = Arc::new(ChannelManager::new(
469471
fee_estimator.clone(),
470472
chain_monitor.clone(),

lightning/src/ln/channelmanager.rs

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

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

lightning/src/ln/functional_test_utils.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -3354,7 +3354,7 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
33543354
network,
33553355
best_block: BestBlock::from_network(network),
33563356
};
3357-
let flow = Arc::new(TestOffersMessageFlow::new(network, cfgs[i].keys_manager.get_node_id(Recipient::Node).unwrap(), genesis_block.header.time, cfgs[i].keys_manager.get_inbound_payment_key(), cfgs[i].keys_manager, &cfgs[i].message_router, &cfgs[i].router));
3357+
let flow = Arc::new(TestOffersMessageFlow::new(params, cfgs[i].keys_manager.get_node_id(Recipient::Node).unwrap(), genesis_block.header.time, cfgs[i].keys_manager.get_inbound_payment_key(), cfgs[i].keys_manager, &cfgs[i].message_router, &cfgs[i].router));
33583358
let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, &cfgs[i].router, &cfgs[i].message_router, flow, cfgs[i].logger, cfgs[i].keys_manager,
33593359
cfgs[i].keys_manager, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { test_default_channel_config() }, params, genesis_block.header.time);
33603360
chanmgrs.push(node);
@@ -3387,7 +3387,12 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
33873387
IgnoringMessageHandler {},
33883388
);
33893389

3390-
let flow = Arc::new(TestOffersMessageFlow::new(network, cfgs[i].keys_manager.get_node_id(Recipient::Node).unwrap(), genesis_block.header.time, cfgs[i].keys_manager.get_inbound_payment_key(), &cfgs[i].keys_manager, &cfgs[i].message_router, &cfgs[i].router));
3390+
let params = ChainParameters {
3391+
network,
3392+
best_block: BestBlock::from_network(network),
3393+
};
3394+
3395+
let flow = Arc::new(TestOffersMessageFlow::new(params, cfgs[i].keys_manager.get_node_id(Recipient::Node).unwrap(), genesis_block.header.time, cfgs[i].keys_manager.get_inbound_payment_key(), &cfgs[i].keys_manager, &cfgs[i].message_router, &cfgs[i].router));
33913396

33923397
let gossip_sync = P2PGossipSync::new(cfgs[i].network_graph.as_ref(), None, cfgs[i].logger);
33933398
let wallet_source = Arc::new(test_utils::TestWalletSource::new(SecretKey::from_slice(&[i as u8 + 1; 32]).unwrap()));

lightning/src/offers/flow.rs

+106-7
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@
1414
use core::ops::Deref;
1515
use core::time::Duration;
1616
use core::sync::atomic::{AtomicUsize, Ordering};
17+
use crate::sync::RwLock;
1718

1819
use bitcoin::block::Header;
1920
use bitcoin::constants::ChainHash;
2021
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
21-
use bitcoin::network::Network;
2222

23-
use crate::blinded_path::message::{AsyncPaymentsContext, BlindedMessagePath, MessageContext, OffersContext};
24-
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
25-
use crate::chain;
23+
use crate::blinded_path::message::{AsyncPaymentsContext, BlindedMessagePath, MessageContext, MessageForwardNode, OffersContext};
24+
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs};
25+
use crate::chain::{self, BestBlock};
26+
use crate::chain::channelmonitor::LATENCY_GRACE_PERIOD_BLOCKS;
2627
use crate::chain::transaction::TransactionData;
27-
use crate::ln::channelmanager::{PaymentId, Verification, OFFERS_MESSAGE_REQUEST_LIMIT};
28+
use crate::ln::channel_state::ChannelDetails;
29+
use crate::ln::channelmanager::{ChainParameters, PaymentId, Verification, CLTV_FAR_FAR_AWAY, MAX_SHORT_LIVED_RELATIVE_EXPIRY, OFFERS_MESSAGE_REQUEST_LIMIT};
2830
use crate::offers::invoice::{Bolt12Invoice, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
2931
use crate::offers::invoice_error::InvoiceError;
3032
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder, VerifiedInvoiceRequest};
@@ -153,6 +155,7 @@ where
153155
R::Target: Router,
154156
{
155157
chain_hash: ChainHash,
158+
best_block: RwLock<BestBlock>,
156159

157160
our_network_pubkey: PublicKey,
158161
highest_seen_timestamp: AtomicUsize,
@@ -183,15 +186,16 @@ where
183186
{
184187
/// Creates a new [`OffersMessageFlow`]
185188
pub fn new(
186-
network: Network, our_network_pubkey: PublicKey,
189+
params: ChainParameters, our_network_pubkey: PublicKey,
187190
current_timestamp: u32, inbound_payment_key: inbound_payment::ExpandedKey,
188191
entropy_source: ES, message_router: MR, router: R,
189192
) -> Self {
190193
let mut secp_ctx = Secp256k1::new();
191194
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
192195

193196
Self {
194-
chain_hash: ChainHash::using_genesis_block(network),
197+
chain_hash: ChainHash::using_genesis_block(params.network),
198+
best_block: RwLock::new(params.best_block),
195199

196200
our_network_pubkey,
197201
highest_seen_timestamp: AtomicUsize::new(current_timestamp as usize),
@@ -248,6 +252,101 @@ where
248252
}
249253
}
250254

255+
impl<ES: Deref, MR: Deref, R: Deref> OffersMessageFlow<ES, MR, R>
256+
where
257+
ES::Target: EntropySource,
258+
MR::Target: MessageRouter,
259+
R::Target: Router,
260+
{
261+
/// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
262+
/// the path's intended lifetime.
263+
///
264+
/// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
265+
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
266+
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
267+
fn create_blinded_paths_using_absolute_expiry(
268+
&self, context: OffersContext, absolute_expiry: Option<Duration>, peers: Vec<MessageForwardNode>
269+
) -> Result<Vec<BlindedMessagePath>, ()> {
270+
let now = self.duration_since_epoch();
271+
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
272+
273+
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
274+
self.create_compact_blinded_paths(peers, context)
275+
} else {
276+
self.create_blinded_paths(peers, MessageContext::Offers(context))
277+
}
278+
}
279+
280+
/// Creates a collection of blinded paths by delegating to
281+
/// [`MessageRouter::create_blinded_paths`].
282+
///
283+
/// Errors if the `MessageRouter` errors.
284+
fn create_blinded_paths(&self, peers: Vec<MessageForwardNode>, context: MessageContext) -> Result<Vec<BlindedMessagePath>, ()> {
285+
let recipient = self.get_our_node_id();
286+
let secp_ctx = &self.secp_ctx;
287+
288+
let peers = peers
289+
.into_iter()
290+
.map(|node| node.node_id)
291+
.collect();
292+
293+
self.message_router
294+
.create_blinded_paths(recipient, context, peers, secp_ctx)
295+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
296+
}
297+
298+
/// Creates a collection of blinded paths by delegating to
299+
/// [`MessageRouter::create_compact_blinded_paths`].
300+
///
301+
/// Errors if the `MessageRouter` errors.
302+
fn create_compact_blinded_paths(&self, peers: Vec<MessageForwardNode>, context: OffersContext) -> Result<Vec<BlindedMessagePath>, ()> {
303+
let recipient = self.get_our_node_id();
304+
let secp_ctx = &self.secp_ctx;
305+
306+
let peers = peers;
307+
308+
self.message_router
309+
.create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
310+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
311+
}
312+
313+
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
314+
/// [`Router::create_blinded_payment_paths`].
315+
fn create_blinded_payment_paths(
316+
&self, usable_channels: Vec<ChannelDetails>, amount_msats: Option<u64>, payment_secret: PaymentSecret,
317+
payment_context: PaymentContext, relative_expiry_seconds: u32
318+
) -> Result<Vec<BlindedPaymentPath>, ()> {
319+
let expanded_key = &self.inbound_payment_key;
320+
let entropy = &*self.entropy_source;
321+
let secp_ctx = &self.secp_ctx;
322+
323+
let first_hops = usable_channels;
324+
let payee_node_id = self.get_our_node_id();
325+
326+
// Assume shorter than usual block times to avoid spuriously failing payments too early.
327+
const SECONDS_PER_BLOCK: u32 = 9 * 60;
328+
let relative_expiry_blocks = relative_expiry_seconds / SECONDS_PER_BLOCK;
329+
let max_cltv_expiry = core::cmp::max(relative_expiry_blocks, CLTV_FAR_FAR_AWAY)
330+
.saturating_add(LATENCY_GRACE_PERIOD_BLOCKS)
331+
.saturating_add(self.best_block.read().unwrap().height);
332+
333+
let payee_tlvs = UnauthenticatedReceiveTlvs {
334+
payment_secret,
335+
payment_constraints: PaymentConstraints {
336+
max_cltv_expiry,
337+
htlc_minimum_msat: 1,
338+
},
339+
payment_context,
340+
};
341+
let nonce = Nonce::from_entropy_source(entropy);
342+
let payee_tlvs = payee_tlvs.authenticate(nonce, expanded_key);
343+
344+
self.router.create_blinded_payment_paths(
345+
payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx
346+
)
347+
}
348+
}
349+
251350
impl<ES: Deref, MR: Deref, R: Deref> chain::Listen for OffersMessageFlow<ES, MR, R>
252351
where
253352
ES::Target: EntropySource,

0 commit comments

Comments
 (0)