Skip to content

Commit 6132b1b

Browse files
committed
f: combine unblinded Trampoline payment test into other two
1 parent ae53326 commit 6132b1b

File tree

1 file changed

+62
-200
lines changed

1 file changed

+62
-200
lines changed

lightning/src/ln/blinded_payment_tests.rs

+62-200
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,14 @@ fn test_trampoline_inbound_payment_decoding() {
19631963
}
19641964

19651965
#[cfg(trampoline)]
1966-
fn do_test_trampoline_single_hop_receive(success: bool) {
1966+
enum TrampolineSingleHopReceiveCheck {
1967+
SuccessfulBlindedReceive,
1968+
SuccessfulUnblindedReceive,
1969+
InvalidOnionFailure,
1970+
}
1971+
1972+
#[cfg(trampoline)]
1973+
fn do_test_trampoline_single_hop_receive(scenario: TrampolineSingleHopReceiveCheck) {
19671974
const TOTAL_NODE_COUNT: usize = 3;
19681975
let secp_ctx = Secp256k1::new();
19691976

@@ -1991,7 +1998,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
19911998

19921999
let carol_alice_trampoline_session_priv = secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03");
19932000
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv);
1994-
let carol_blinded_hops = if success {
2001+
let carol_blinded_hops = if matches!(scenario, TrampolineSingleHopReceiveCheck::SuccessfulBlindedReceive | TrampolineSingleHopReceiveCheck::SuccessfulUnblindedReceive) {
19952002
let payee_tlvs = UnauthenticatedReceiveTlvs {
19962003
payment_secret,
19972004
payment_constraints: PaymentConstraints {
@@ -2081,29 +2088,44 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
20812088

20822089
check_added_monitors!(&nodes[0], 1);
20832090

2084-
if success {
2091+
if matches!(scenario, TrampolineSingleHopReceiveCheck::SuccessfulBlindedReceive) {
20852092
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
20862093
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
20872094
} else {
20882095
let replacement_onion = {
2089-
// create a substitute onion where the last Trampoline hop is a forward
2096+
// Create a substitute onion:
2097+
// In the invalid onion failure scenario, it's to make the last payload a forward.
2098+
// In the unblinded receive scenario, which we (deliberately) do not support out of the
2099+
// box, it's to make the receive payload unblinded.
20902100
let trampoline_secret_key = secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799");
20912101
let prng_seed = secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9");
20922102
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
20932103

20942104
let mut blinded_tail = route.paths[0].blinded_tail.clone().unwrap();
20952105

2096-
// append some dummy blinded hop so the intro hop looks like a forward
2097-
blinded_tail.hops.push(BlindedHop {
2098-
blinded_node_id: alice_node_id,
2099-
encrypted_payload: vec![],
2100-
});
2106+
if matches!(scenario, TrampolineSingleHopReceiveCheck::InvalidOnionFailure) {
2107+
// append some dummy blinded hop so the intro hop looks like a forward
2108+
blinded_tail.hops.push(BlindedHop {
2109+
blinded_node_id: alice_node_id,
2110+
encrypted_payload: vec![],
2111+
});
2112+
}
21012113

21022114
let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&blinded_tail, amt_msat, &recipient_onion_fields, 32, &None).unwrap();
21032115

2104-
// pop the last dummy hop
21052116
trampoline_payloads.pop();
21062117

2118+
if matches!(scenario, TrampolineSingleHopReceiveCheck::SuccessfulUnblindedReceive) {
2119+
trampoline_payloads.push(msgs::OutboundTrampolinePayload::Receive {
2120+
payment_data: Some(msgs::FinalOnionHopData {
2121+
payment_secret,
2122+
total_msat: amt_msat,
2123+
}),
2124+
sender_intended_htlc_amt_msat: amt_msat,
2125+
cltv_expiry_height: 104,
2126+
});
2127+
}
2128+
21072129
let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys(&secp_ctx, &route.paths[0].blinded_tail.as_ref().unwrap(), &trampoline_secret_key).unwrap();
21082130
let trampoline_packet = onion_utils::construct_trampoline_onion_packet(
21092131
trampoline_payloads,
@@ -2142,30 +2164,36 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
21422164
});
21432165

21442166
let route: &[&Node] = &[&nodes[1], &nodes[2]];
2145-
let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event)
2146-
.with_payment_preimage(payment_preimage)
2147-
.without_claimable_event()
2148-
.expect_failure(HTLCDestination::InvalidOnion);
2149-
do_pass_along_path(args);
2167+
let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event);
2168+
2169+
if matches!(scenario, TrampolineSingleHopReceiveCheck::InvalidOnionFailure) {
2170+
let args = args.expect_failure(HTLCDestination::InvalidOnion)
2171+
.with_payment_preimage(payment_preimage)
2172+
.without_claimable_event();
2173+
do_pass_along_path(args);
2174+
2175+
{
2176+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
2177+
nodes[1].node.handle_update_fail_htlc(
2178+
nodes[2].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0],
2179+
);
2180+
do_commitment_signed_dance(&nodes[1], &nodes[2], &unblinded_node_updates.commitment_signed, true, false);
2181+
}
2182+
{
2183+
let unblinded_node_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
2184+
nodes[0].node.handle_update_fail_htlc(
2185+
nodes[1].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0],
2186+
);
2187+
do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false);
2188+
}
21502189

2151-
{
2152-
let unblinded_node_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
2153-
nodes[1].node.handle_update_fail_htlc(
2154-
nodes[2].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2155-
);
2156-
do_commitment_signed_dance(&nodes[1], &nodes[2], &unblinded_node_updates.commitment_signed, true, false);
2157-
}
2158-
{
2159-
let unblinded_node_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
2160-
nodes[0].node.handle_update_fail_htlc(
2161-
nodes[1].node.get_our_node_id(), &unblinded_node_updates.update_fail_htlcs[0]
2162-
);
2163-
do_commitment_signed_dance(&nodes[0], &nodes[1], &unblinded_node_updates.commitment_signed, false, false);
2164-
}
2165-
{
21662190
let payment_failed_conditions = PaymentFailedConditions::new()
21672191
.expected_htlc_error_data(0x4000 | 22, &[0; 0]);
21682192
expect_payment_failed_conditions(&nodes[0], payment_hash, true, payment_failed_conditions);
2193+
} else {
2194+
let args = args.with_payment_secret(payment_secret);
2195+
do_pass_along_path(args);
2196+
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
21692197
}
21702198
}
21712199
}
@@ -2174,177 +2202,11 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
21742202
#[cfg(trampoline)]
21752203
fn test_trampoline_single_hop_receive() {
21762204
// Simulate a payment of A (0) -> B (1) -> C(Trampoline (blinded intro)) (2)
2177-
do_test_trampoline_single_hop_receive(true);
2178-
2179-
// Simulate a payment failure of A (0) -> B (1) -> C(Trampoline (blinded forward)) (2)
2180-
do_test_trampoline_single_hop_receive(false);
2181-
}
2205+
do_test_trampoline_single_hop_receive(TrampolineSingleHopReceiveCheck::SuccessfulBlindedReceive);
21822206

2183-
#[test]
2184-
#[cfg(trampoline)]
2185-
fn test_trampoline_unblinded_receive() {
21862207
// Simulate a payment of A (0) -> B (1) -> C(Trampoline) (2)
2208+
do_test_trampoline_single_hop_receive(TrampolineSingleHopReceiveCheck::SuccessfulUnblindedReceive);
21872209

2188-
const TOTAL_NODE_COUNT: usize = 3;
2189-
let secp_ctx = Secp256k1::new();
2190-
2191-
let chanmon_cfgs = create_chanmon_cfgs(TOTAL_NODE_COUNT);
2192-
let node_cfgs = create_node_cfgs(TOTAL_NODE_COUNT, &chanmon_cfgs);
2193-
let node_chanmgrs = create_node_chanmgrs(TOTAL_NODE_COUNT, &node_cfgs, &vec![None; TOTAL_NODE_COUNT]);
2194-
let mut nodes = create_network(TOTAL_NODE_COUNT, &node_cfgs, &node_chanmgrs);
2195-
2196-
let (_, _, chan_id_alice_bob, _) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
2197-
let (_, _, chan_id_bob_carol, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
2198-
2199-
for i in 0..TOTAL_NODE_COUNT { // connect all nodes' blocks
2200-
connect_blocks(&nodes[i], (TOTAL_NODE_COUNT as u32) * CHAN_CONFIRM_DEPTH + 1 - nodes[i].best_block_info().1);
2201-
}
2202-
2203-
let alice_node_id = nodes[0].node().get_our_node_id();
2204-
let bob_node_id = nodes[1].node().get_our_node_id();
2205-
let carol_node_id = nodes[2].node().get_our_node_id();
2206-
2207-
let alice_bob_scid = nodes[0].node().list_channels().iter().find(|c| c.channel_id == chan_id_alice_bob).unwrap().short_channel_id.unwrap();
2208-
let bob_carol_scid = nodes[1].node().list_channels().iter().find(|c| c.channel_id == chan_id_bob_carol).unwrap().short_channel_id.unwrap();
2209-
2210-
let amt_msat = 1000;
2211-
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None);
2212-
let payee_tlvs = blinded_path::payment::TrampolineForwardTlvs {
2213-
next_trampoline: alice_node_id,
2214-
payment_constraints: PaymentConstraints {
2215-
max_cltv_expiry: u32::max_value(),
2216-
htlc_minimum_msat: amt_msat,
2217-
},
2218-
features: BlindedHopFeatures::empty(),
2219-
payment_relay: PaymentRelay {
2220-
cltv_expiry_delta: 0,
2221-
fee_proportional_millionths: 0,
2222-
fee_base_msat: 0,
2223-
},
2224-
next_blinding_override: None,
2225-
};
2226-
2227-
let carol_unblinded_tlvs = payee_tlvs.encode();
2228-
let path = [(carol_node_id, WithoutLength(&carol_unblinded_tlvs))];
2229-
let carol_alice_trampoline_session_priv = secret_from_hex("a0f4b8d7b6c2d0ffdfaf718f76e9decaef4d9fb38a8c4addb95c4007cc3eee03");
2230-
let carol_blinding_point = PublicKey::from_secret_key(&secp_ctx, &carol_alice_trampoline_session_priv);
2231-
let carol_blinded_hops = blinded_path::utils::construct_blinded_hops(
2232-
&secp_ctx, path.into_iter(), &carol_alice_trampoline_session_priv
2233-
).unwrap();
2234-
2235-
let route = Route {
2236-
paths: vec![Path {
2237-
hops: vec![
2238-
// Bob
2239-
RouteHop {
2240-
pubkey: bob_node_id,
2241-
node_features: NodeFeatures::empty(),
2242-
short_channel_id: alice_bob_scid,
2243-
channel_features: ChannelFeatures::empty(),
2244-
fee_msat: 1000,
2245-
cltv_expiry_delta: 48,
2246-
maybe_announced_channel: false,
2247-
},
2248-
2249-
// Carol
2250-
RouteHop {
2251-
pubkey: carol_node_id,
2252-
node_features: NodeFeatures::empty(),
2253-
short_channel_id: bob_carol_scid,
2254-
channel_features: ChannelFeatures::empty(),
2255-
fee_msat: 0,
2256-
cltv_expiry_delta: 48,
2257-
maybe_announced_channel: false,
2258-
}
2259-
],
2260-
blinded_tail: Some(BlindedTail {
2261-
trampoline_hops: vec![
2262-
// Carol
2263-
TrampolineHop {
2264-
pubkey: carol_node_id,
2265-
node_features: Features::empty(),
2266-
fee_msat: amt_msat,
2267-
cltv_expiry_delta: 24,
2268-
},
2269-
],
2270-
hops: carol_blinded_hops,
2271-
blinding_point: carol_blinding_point,
2272-
excess_final_cltv_expiry_delta: 39,
2273-
final_value_msat: amt_msat,
2274-
})
2275-
}],
2276-
route_params: None,
2277-
};
2278-
2279-
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
2280-
2281-
let replacement_onion = {
2282-
// create a substitute onion where the last Trampoline hop is an unblinded receive, which we
2283-
// (deliberately) do not support out of the box, therefore necessitating this workaround
2284-
let trampoline_secret_key = secret_from_hex("0134928f7b7ca6769080d70f16be84c812c741f545b49a34db47ce338a205799");
2285-
let prng_seed = secret_from_hex("fe02b4b9054302a3ddf4e1e9f7c411d644aebbd295218ab009dca94435f775a9");
2286-
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
2287-
2288-
let blinded_tail = route.paths[0].blinded_tail.clone().unwrap();
2289-
let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&blinded_tail, amt_msat, &recipient_onion_fields, 32, &None).unwrap();
2290-
2291-
// pop the last dummy hop
2292-
trampoline_payloads.pop();
2293-
2294-
trampoline_payloads.push(msgs::OutboundTrampolinePayload::Receive {
2295-
payment_data: Some(msgs::FinalOnionHopData {
2296-
payment_secret,
2297-
total_msat: amt_msat,
2298-
}),
2299-
sender_intended_htlc_amt_msat: amt_msat,
2300-
cltv_expiry_height: 104,
2301-
});
2302-
2303-
let trampoline_onion_keys = onion_utils::construct_trampoline_onion_keys(&secp_ctx, &route.paths[0].blinded_tail.as_ref().unwrap(), &trampoline_secret_key).unwrap();
2304-
let trampoline_packet = onion_utils::construct_trampoline_onion_packet(
2305-
trampoline_payloads,
2306-
trampoline_onion_keys,
2307-
prng_seed.secret_bytes(),
2308-
&payment_hash,
2309-
None,
2310-
).unwrap();
2311-
2312-
let outer_session_priv = secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677");
2313-
2314-
let (outer_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], outer_total_msat, &recipient_onion_fields, outer_starting_htlc_offset, &None, None, Some(trampoline_packet)).unwrap();
2315-
let outer_onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.clone().paths[0], &outer_session_priv).unwrap();
2316-
let outer_packet = onion_utils::construct_onion_packet(
2317-
outer_payloads,
2318-
outer_onion_keys,
2319-
prng_seed.secret_bytes(),
2320-
&payment_hash,
2321-
).unwrap();
2322-
2323-
outer_packet
2324-
};
2325-
2326-
check_added_monitors!(&nodes[0], 1);
2327-
2328-
// Check that we've queued the HTLCs of the async keysend payment.
2329-
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
2330-
assert_eq!(events.len(), 1);
2331-
let mut first_message_event = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
2332-
let mut update_message = match first_message_event {
2333-
MessageSendEvent::UpdateHTLCs { ref mut updates, .. } => {
2334-
assert_eq!(updates.update_add_htlcs.len(), 1);
2335-
updates.update_add_htlcs.get_mut(0)
2336-
},
2337-
_ => panic!()
2338-
};
2339-
update_message.map(|msg| {
2340-
msg.onion_routing_packet = replacement_onion.clone();
2341-
});
2342-
2343-
let route: &[&Node] = &[&nodes[1], &nodes[2]];
2344-
let args = PassAlongPathArgs::new(&nodes[0], route, amt_msat, payment_hash, first_message_event)
2345-
.with_payment_secret(payment_secret);
2346-
do_pass_along_path(args);
2347-
2348-
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
2210+
// Simulate a payment failure of A (0) -> B (1) -> C(Trampoline (blinded forward)) (2)
2211+
do_test_trampoline_single_hop_receive(TrampolineSingleHopReceiveCheck::InvalidOnionFailure);
23492212
}
2350-

0 commit comments

Comments
 (0)