Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 40c7e03

Browse files
committedMar 26, 2025··
Test rejection of Trampoline forwards
In the next PR, we will be adding support for forwarding payments between Trampoline hops. Until we do that, forwarding payments need to be rejected, which we test in this commit.
1 parent 9fe6a91 commit 40c7e03

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
 

‎lightning/src/ln/blinded_payment_tests.rs

+119
Original file line numberDiff line numberDiff line change
@@ -2342,3 +2342,122 @@ fn test_trampoline_unblinded_receive() {
23422342
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
23432343
}
23442344

2345+
#[test]
2346+
fn test_trampoline_forward_rejection() {
2347+
const TOTAL_NODE_COUNT: usize = 3;
2348+
2349+
let chanmon_cfgs = create_chanmon_cfgs(TOTAL_NODE_COUNT);
2350+
let node_cfgs = create_node_cfgs(TOTAL_NODE_COUNT, &chanmon_cfgs);
2351+
let node_chanmgrs = create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]);
2352+
let mut nodes = create_network(TOTAL_NODE_COUNT, &node_cfgs, &node_chanmgrs);
2353+
2354+
let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
2355+
let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
2356+
2357+
for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks
2358+
connect_blocks(&nodes[i], (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1);
2359+
}
2360+
2361+
let alice_node_id = nodes[0].node().get_our_node_id();
2362+
let bob_node_id = nodes[1].node().get_our_node_id();
2363+
let carol_node_id = nodes[2].node().get_our_node_id();
2364+
2365+
let alice_bob_scid = nodes[0].node().list_channels().iter().find(|c| c.channel_id == chan_id_alice_bob).unwrap().short_channel_id.unwrap();
2366+
let bob_carol_scid = nodes[1].node().list_channels().iter().find(|c| c.channel_id == chan_id_bob_carol).unwrap().short_channel_id.unwrap();
2367+
2368+
let amt_msat = 1000;
2369+
let (payment_preimage, payment_hash, _) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None);
2370+
2371+
let route = Route {
2372+
paths: vec![Path {
2373+
hops: vec![
2374+
// Bob
2375+
RouteHop {
2376+
pubkey: bob_node_id,
2377+
node_features: NodeFeatures::empty(),
2378+
short_channel_id: alice_bob_scid,
2379+
channel_features: ChannelFeatures::empty(),
2380+
fee_msat: 1000,
2381+
cltv_expiry_delta: 48,
2382+
maybe_announced_channel: false,
2383+
},
2384+
2385+
// Carol
2386+
RouteHop {
2387+
pubkey: carol_node_id,
2388+
node_features: NodeFeatures::empty(),
2389+
short_channel_id: bob_carol_scid,
2390+
channel_features: ChannelFeatures::empty(),
2391+
fee_msat: 0,
2392+
cltv_expiry_delta: 48,
2393+
maybe_announced_channel: false,
2394+
}
2395+
],
2396+
blinded_tail: Some(BlindedTail {
2397+
trampoline_hops: vec![
2398+
// Carol
2399+
TrampolineHop {
2400+
pubkey: carol_node_id,
2401+
node_features: Features::empty(),
2402+
fee_msat: amt_msat,
2403+
cltv_expiry_delta: 24,
2404+
},
2405+
2406+
// Alice (unreachable)
2407+
TrampolineHop {
2408+
pubkey: alice_node_id,
2409+
node_features: Features::empty(),
2410+
fee_msat: amt_msat,
2411+
cltv_expiry_delta: 24,
2412+
},
2413+
],
2414+
hops: vec![BlindedHop{
2415+
// Fake public key
2416+
blinded_node_id: alice_node_id,
2417+
encrypted_payload: vec![],
2418+
}],
2419+
blinding_point: alice_node_id,
2420+
excess_final_cltv_expiry_delta: 39,
2421+
final_value_msat: amt_msat,
2422+
})
2423+
}],
2424+
route_params: None,
2425+
};
2426+
2427+
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
2428+
2429+
check_added_monitors!(&nodes[0], 1);
2430+
2431+
// pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
2432+
2433+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2434+
assert_eq!(events.len(), 1);
2435+
let first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
2436+
2437+
let route: &[&Node] = &[&nodes[1], &nodes[2]];
2438+
let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event)
2439+
.with_payment_preimage(payment_preimage)
2440+
.without_claimable_event()
2441+
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
2442+
do_pass_along_path(args);
2443+
2444+
{
2445+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
2446+
nodes[1].node.handle_update_fail_htlc(
2447+
nodes[2].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2448+
);
2449+
do_commitment_signed_dance(&nodes[1], &nodes[2], &unblinded_node_updates.commitment_signed, true, false);
2450+
}
2451+
{
2452+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
2453+
nodes[0].node.handle_update_fail_htlc(
2454+
nodes[1].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2455+
);
2456+
do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false);
2457+
}
2458+
{
2459+
let payment_failed_conditions = PaymentFailedConditions::new()
2460+
.expected_htlc_error_data(0x4000 | 10, &[0; 0]);
2461+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, payment_failed_conditions);
2462+
}
2463+
}

0 commit comments

Comments
 (0)
Please sign in to comment.