Skip to content

Commit 0e82461

Browse files
committed
ln/test: add multi-purpose trampoline test helper
To create trampoline forwarding and single hop receiving tails.
1 parent 983a343 commit 0e82461

File tree

3 files changed

+61
-50
lines changed

3 files changed

+61
-50
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,50 +2420,6 @@ fn test_trampoline_blinded_receive() {
24202420
do_test_trampoline_relay(true, TrampolineTestCase::OuterCLTVLessThanTrampoline);
24212421
}
24222422

2423-
/// Creates a blinded tail where Carol receives via a blinded path.
2424-
fn create_blinded_tail(
2425-
secp_ctx: &Secp256k1<All>, override_random_bytes: [u8; 32], carol_node_id: PublicKey,
2426-
carol_auth_key: ReceiveAuthKey, trampoline_cltv_expiry_delta: u32,
2427-
excess_final_cltv_delta: u32, final_value_msat: u64, payment_secret: PaymentSecret,
2428-
) -> BlindedTail {
2429-
let outer_session_priv = SecretKey::from_slice(&override_random_bytes).unwrap();
2430-
let trampoline_session_priv = onion_utils::compute_trampoline_session_priv(&outer_session_priv);
2431-
2432-
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &trampoline_session_priv);
2433-
let carol_blinded_hops = {
2434-
let payee_tlvs = ReceiveTlvs {
2435-
payment_secret,
2436-
payment_constraints: PaymentConstraints {
2437-
max_cltv_expiry: u32::max_value(),
2438-
htlc_minimum_msat: final_value_msat,
2439-
},
2440-
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
2441-
}
2442-
.encode();
2443-
2444-
let path = [((carol_node_id, Some(carol_auth_key)), WithoutLength(&payee_tlvs))];
2445-
2446-
blinded_path::utils::construct_blinded_hops(
2447-
&secp_ctx,
2448-
path.into_iter(),
2449-
&trampoline_session_priv,
2450-
)
2451-
};
2452-
2453-
BlindedTail {
2454-
trampoline_hops: vec![TrampolineHop {
2455-
pubkey: carol_node_id,
2456-
node_features: Features::empty(),
2457-
fee_msat: final_value_msat,
2458-
cltv_expiry_delta: trampoline_cltv_expiry_delta + excess_final_cltv_delta,
2459-
}],
2460-
hops: carol_blinded_hops,
2461-
blinding_point: carol_blinding_point,
2462-
excess_final_cltv_expiry_delta: excess_final_cltv_delta,
2463-
final_value_msat,
2464-
}
2465-
}
2466-
24672423
// Creates a replacement onion that is used to produce scenarios that we don't support, specifically
24682424
// payloads that send to unblinded receives and invalid payloads.
24692425
fn replacement_onion(
@@ -2631,15 +2587,23 @@ fn do_test_trampoline_relay(blinded: bool, test_case: TrampolineTestCase) {
26312587
// Create a blinded tail where Carol is receiving. In our unblinded test cases, we'll
26322588
// override this anyway (with a tail sending to an unblinded receive, which LDK doesn't
26332589
// allow).
2634-
blinded_tail: Some(create_blinded_tail(
2590+
blinded_tail: Some(create_trampoline_forward_blinded_tail(
26352591
&secp_ctx,
2636-
override_random_bytes,
2592+
&nodes[2].keys_manager,
2593+
&[],
26372594
carol_node_id,
26382595
nodes[2].keys_manager.get_receive_auth_key(),
2596+
ReceiveTlvs {
2597+
payment_secret,
2598+
payment_constraints: PaymentConstraints {
2599+
max_cltv_expiry: u32::max_value(),
2600+
htlc_minimum_msat: original_amt_msat,
2601+
},
2602+
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
2603+
},
26392604
original_trampoline_cltv,
26402605
excess_final_cltv,
26412606
original_amt_msat,
2642-
payment_secret,
26432607
)),
26442608
}],
26452609
route_params: None,

lightning/src/ln/functional_test_utils.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
//! A bunch of useful utilities for building networks of nodes and exchanging messages between
1111
//! nodes for functional tests.
1212
13-
use crate::blinded_path::payment::DummyTlvs;
13+
use crate::blinded_path::payment::{
14+
BlindedPaymentPath, DummyTlvs, ForwardNode, ReceiveTlvs, TrampolineForwardTlvs,
15+
};
1416
use crate::chain::channelmonitor::{ChannelMonitor, HTLC_FAIL_BACK_BUFFER};
1517
use crate::chain::transaction::OutPoint;
1618
use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
@@ -40,7 +42,8 @@ use crate::ln::types::ChannelId;
4042
use crate::onion_message::messenger::OnionMessenger;
4143
use crate::routing::gossip::{NetworkGraph, NetworkUpdate, P2PGossipSync};
4244
use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
43-
use crate::sign::{EntropySource, RandomBytes};
45+
use crate::routing::router::{compute_fees, BlindedTail, TrampolineHop};
46+
use crate::sign::{EntropySource, RandomBytes, ReceiveAuthKey};
4447
use crate::types::features::ChannelTypeFeatures;
4548
use crate::types::features::InitFeatures;
4649
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
@@ -5798,3 +5801,47 @@ pub fn get_scid_from_channel_id<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, channel_id:
57985801
.short_channel_id
57995802
.unwrap()
58005803
}
5804+
5805+
/// Creates a [`BlindedTail`] for a trampoline forward through a single intermediate node.
5806+
///
5807+
/// The resulting tail contains blinded hops built from `intermediate_nodes` plus a dummy receive
5808+
/// TLV, with the `TrampolineHop` fee and CLTV derived from the blinded path's aggregated payinfo.
5809+
pub fn create_trampoline_forward_blinded_tail<ES: EntropySource>(
5810+
secp_ctx: &bitcoin::secp256k1::Secp256k1<bitcoin::secp256k1::All>, entropy_source: ES,
5811+
intermediate_nodes: &[ForwardNode<TrampolineForwardTlvs>], payee_node_id: PublicKey,
5812+
payee_receive_key: ReceiveAuthKey, payee_tlvs: ReceiveTlvs, min_final_cltv_expiry_delta: u32,
5813+
excess_final_cltv_delta: u32, final_value_msat: u64,
5814+
) -> BlindedTail {
5815+
let blinded_path = BlindedPaymentPath::new_for_trampoline(
5816+
intermediate_nodes,
5817+
payee_node_id,
5818+
payee_receive_key,
5819+
payee_tlvs,
5820+
u64::max_value(),
5821+
min_final_cltv_expiry_delta as u16,
5822+
entropy_source,
5823+
secp_ctx,
5824+
)
5825+
.unwrap();
5826+
5827+
BlindedTail {
5828+
trampoline_hops: vec![TrampolineHop {
5829+
pubkey: intermediate_nodes.first().map(|n| n.node_id).unwrap_or(payee_node_id),
5830+
node_features: types::features::Features::empty(),
5831+
fee_msat: compute_fees(
5832+
final_value_msat,
5833+
lightning_types::routing::RoutingFees {
5834+
base_msat: blinded_path.payinfo.fee_base_msat,
5835+
proportional_millionths: blinded_path.payinfo.fee_proportional_millionths,
5836+
},
5837+
)
5838+
.unwrap(),
5839+
cltv_expiry_delta: blinded_path.payinfo.cltv_expiry_delta as u32
5840+
+ excess_final_cltv_delta,
5841+
}],
5842+
hops: blinded_path.blinded_hops().to_vec(),
5843+
blinding_point: blinded_path.blinding_point(),
5844+
excess_final_cltv_expiry_delta: excess_final_cltv_delta,
5845+
final_value_msat,
5846+
}
5847+
}

lightning/src/routing/router.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2464,7 +2464,7 @@ impl<'a> PaymentPath<'a> {
24642464
#[inline(always)]
24652465
/// Calculate the fees required to route the given amount over a channel with the given fees.
24662466
#[rustfmt::skip]
2467-
fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
2467+
pub(crate) fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
24682468
amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
24692469
.and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000))
24702470
}

0 commit comments

Comments
 (0)