Skip to content

Commit 0792570

Browse files
committed
ln/test: add multi-purpose trampoline test helper
To create trampoline forwarding and single hop receiving tails.
1 parent 95ae963 commit 0792570

3 files changed

Lines changed: 61 additions & 50 deletions

File tree

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,50 +2428,6 @@ fn test_trampoline_blinded_receive() {
24282428
do_test_trampoline_relay(true, TrampolineTestCase::OuterCLTVLessThanTrampoline);
24292429
}
24302430

2431-
/// Creates a blinded tail where Carol receives via a blinded path.
2432-
fn create_blinded_tail(
2433-
secp_ctx: &Secp256k1<All>, override_random_bytes: [u8; 32], carol_node_id: PublicKey,
2434-
carol_auth_key: ReceiveAuthKey, trampoline_cltv_expiry_delta: u32,
2435-
excess_final_cltv_delta: u32, final_value_msat: u64, payment_secret: PaymentSecret,
2436-
) -> BlindedTail {
2437-
let outer_session_priv = SecretKey::from_slice(&override_random_bytes).unwrap();
2438-
let trampoline_session_priv = onion_utils::compute_trampoline_session_priv(&outer_session_priv);
2439-
2440-
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &trampoline_session_priv);
2441-
let carol_blinded_hops = {
2442-
let payee_tlvs = ReceiveTlvs {
2443-
payment_secret,
2444-
payment_constraints: PaymentConstraints {
2445-
max_cltv_expiry: u32::max_value(),
2446-
htlc_minimum_msat: final_value_msat,
2447-
},
2448-
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
2449-
}
2450-
.encode();
2451-
2452-
let path = [((carol_node_id, Some(carol_auth_key)), WithoutLength(&payee_tlvs))];
2453-
2454-
blinded_path::utils::construct_blinded_hops(
2455-
&secp_ctx,
2456-
path.into_iter(),
2457-
&trampoline_session_priv,
2458-
)
2459-
};
2460-
2461-
BlindedTail {
2462-
trampoline_hops: vec![TrampolineHop {
2463-
pubkey: carol_node_id,
2464-
node_features: Features::empty(),
2465-
fee_msat: final_value_msat,
2466-
cltv_expiry_delta: trampoline_cltv_expiry_delta + excess_final_cltv_delta,
2467-
}],
2468-
hops: carol_blinded_hops,
2469-
blinding_point: carol_blinding_point,
2470-
excess_final_cltv_expiry_delta: excess_final_cltv_delta,
2471-
final_value_msat,
2472-
}
2473-
}
2474-
24752431
// Creates a replacement onion that is used to produce scenarios that we don't support, specifically
24762432
// payloads that send to unblinded receives and invalid payloads.
24772433
fn replacement_onion(
@@ -2639,15 +2595,23 @@ fn do_test_trampoline_relay(blinded: bool, test_case: TrampolineTestCase) {
26392595
// Create a blinded tail where Carol is receiving. In our unblinded test cases, we'll
26402596
// override this anyway (with a tail sending to an unblinded receive, which LDK doesn't
26412597
// allow).
2642-
blinded_tail: Some(create_blinded_tail(
2598+
blinded_tail: Some(create_trampoline_forward_blinded_tail(
26432599
&secp_ctx,
2644-
override_random_bytes,
2600+
&nodes[2].keys_manager,
2601+
&[],
26452602
carol_node_id,
26462603
nodes[2].keys_manager.get_receive_auth_key(),
2604+
ReceiveTlvs {
2605+
payment_secret,
2606+
payment_constraints: PaymentConstraints {
2607+
max_cltv_expiry: u32::max_value(),
2608+
htlc_minimum_msat: original_amt_msat,
2609+
},
2610+
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
2611+
},
26472612
original_trampoline_cltv,
26482613
excess_final_cltv,
26492614
original_amt_msat,
2650-
payment_secret,
26512615
)),
26522616
}],
26532617
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};
@@ -5768,3 +5771,47 @@ pub fn get_scid_from_channel_id<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, channel_id:
57685771
.short_channel_id
57695772
.unwrap()
57705773
}
5774+
5775+
/// Creates a [`BlindedTail`] for a trampoline forward through a single intermediate node.
5776+
///
5777+
/// The resulting tail contains blinded hops built from `intermediate_nodes` plus a dummy receive
5778+
/// TLV, with the `TrampolineHop` fee and CLTV derived from the blinded path's aggregated payinfo.
5779+
pub fn create_trampoline_forward_blinded_tail<ES: EntropySource>(
5780+
secp_ctx: &bitcoin::secp256k1::Secp256k1<bitcoin::secp256k1::All>, entropy_source: ES,
5781+
intermediate_nodes: &[ForwardNode<TrampolineForwardTlvs>], payee_node_id: PublicKey,
5782+
payee_receive_key: ReceiveAuthKey, payee_tlvs: ReceiveTlvs, min_final_cltv_expiry_delta: u32,
5783+
excess_final_cltv_delta: u32, final_value_msat: u64,
5784+
) -> BlindedTail {
5785+
let blinded_path = BlindedPaymentPath::new_for_trampoline(
5786+
intermediate_nodes,
5787+
payee_node_id,
5788+
payee_receive_key,
5789+
payee_tlvs,
5790+
u64::max_value(),
5791+
min_final_cltv_expiry_delta as u16,
5792+
entropy_source,
5793+
secp_ctx,
5794+
)
5795+
.unwrap();
5796+
5797+
BlindedTail {
5798+
trampoline_hops: vec![TrampolineHop {
5799+
pubkey: intermediate_nodes.first().map(|n| n.node_id).unwrap_or(payee_node_id),
5800+
node_features: types::features::Features::empty(),
5801+
fee_msat: compute_fees(
5802+
final_value_msat,
5803+
lightning_types::routing::RoutingFees {
5804+
base_msat: blinded_path.payinfo.fee_base_msat,
5805+
proportional_millionths: blinded_path.payinfo.fee_proportional_millionths,
5806+
},
5807+
)
5808+
.unwrap(),
5809+
cltv_expiry_delta: blinded_path.payinfo.cltv_expiry_delta as u32
5810+
+ excess_final_cltv_delta,
5811+
}],
5812+
hops: blinded_path.blinded_hops().to_vec(),
5813+
blinding_point: blinded_path.blinding_point(),
5814+
excess_final_cltv_expiry_delta: excess_final_cltv_delta,
5815+
final_value_msat,
5816+
}
5817+
}

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)