Skip to content

Commit 2b6a6d7

Browse files
committed
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 2b2dc99 commit 2b6a6d7

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
@@ -2341,3 +2341,122 @@ fn test_trampoline_unblinded_receive() {
23412341
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
23422342
}
23432343

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

0 commit comments

Comments
 (0)