Skip to content

Commit 4f2ea60

Browse files
committed
Clean up long_mpp_route_test and mpp_cheaper_route_test
These tests are a bit annoying to deal with and ultimately work on almost the same graph subset, so it makes sense to combine their graph layout logic and then call it twice. We do that here, combining them and also cleaning up the possible paths as there actually are paths that the router could select which don't meet the tests requirements.
1 parent d88198b commit 4f2ea60

File tree

1 file changed

+55
-232
lines changed

1 file changed

+55
-232
lines changed

lightning/src/routing/router.rs

Lines changed: 55 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,187 +5740,33 @@ mod tests {
57405740
}
57415741

57425742
#[test]
5743-
fn long_mpp_route_test() {
5744-
let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5745-
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5746-
let scorer = ln_test_utils::TestScorer::new();
5747-
let random_seed_bytes = [42; 32];
5748-
let config = UserConfig::default();
5749-
let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
5750-
.with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5751-
.unwrap();
5752-
5753-
// We need a route consisting of 3 paths:
5754-
// From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
5755-
// Note that these paths overlap (channels 5, 12, 13).
5756-
// We will route 300 sats.
5757-
// Each path will have 100 sats capacity, those channels which
5758-
// are used twice will have 200 sats capacity.
5759-
5760-
// Disable other potential paths.
5761-
update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5762-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5763-
short_channel_id: 2,
5764-
timestamp: 2,
5765-
message_flags: 1, // Only must_be_one
5766-
channel_flags: 2,
5767-
cltv_expiry_delta: 0,
5768-
htlc_minimum_msat: 0,
5769-
htlc_maximum_msat: 100_000,
5770-
fee_base_msat: 0,
5771-
fee_proportional_millionths: 0,
5772-
excess_data: Vec::new()
5773-
});
5774-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5775-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5776-
short_channel_id: 7,
5777-
timestamp: 2,
5778-
message_flags: 1, // Only must_be_one
5779-
channel_flags: 2,
5780-
cltv_expiry_delta: 0,
5781-
htlc_minimum_msat: 0,
5782-
htlc_maximum_msat: 100_000,
5783-
fee_base_msat: 0,
5784-
fee_proportional_millionths: 0,
5785-
excess_data: Vec::new()
5786-
});
5787-
5788-
// Path via {node0, node2} is channels {1, 3, 5}.
5789-
update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5790-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5791-
short_channel_id: 1,
5792-
timestamp: 2,
5793-
message_flags: 1, // Only must_be_one
5794-
channel_flags: 0,
5795-
cltv_expiry_delta: 0,
5796-
htlc_minimum_msat: 0,
5797-
htlc_maximum_msat: 100_000,
5798-
fee_base_msat: 0,
5799-
fee_proportional_millionths: 0,
5800-
excess_data: Vec::new()
5801-
});
5802-
update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5803-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5804-
short_channel_id: 3,
5805-
timestamp: 2,
5806-
message_flags: 1, // Only must_be_one
5807-
channel_flags: 0,
5808-
cltv_expiry_delta: 0,
5809-
htlc_minimum_msat: 0,
5810-
htlc_maximum_msat: 100_000,
5811-
fee_base_msat: 0,
5812-
fee_proportional_millionths: 0,
5813-
excess_data: Vec::new()
5814-
});
5815-
5816-
// Capacity of 200 sats because this channel will be used by 3rd path as well.
5817-
add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
5818-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5819-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5820-
short_channel_id: 5,
5821-
timestamp: 2,
5822-
message_flags: 1, // Only must_be_one
5823-
channel_flags: 0,
5824-
cltv_expiry_delta: 0,
5825-
htlc_minimum_msat: 0,
5826-
htlc_maximum_msat: 200_000,
5827-
fee_base_msat: 0,
5828-
fee_proportional_millionths: 0,
5829-
excess_data: Vec::new()
5830-
});
5831-
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
5832-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5833-
short_channel_id: 5,
5834-
timestamp: 2,
5835-
message_flags: 1, // Only must_be_one
5836-
channel_flags: 3, // disable direction 1
5837-
cltv_expiry_delta: 0,
5838-
htlc_minimum_msat: 0,
5839-
htlc_maximum_msat: 200_000,
5840-
fee_base_msat: 0,
5841-
fee_proportional_millionths: 0,
5842-
excess_data: Vec::new()
5843-
});
5844-
5845-
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
5846-
// Add 100 sats to the capacities of {12, 13}, because these channels
5847-
// are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats.
5848-
update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5849-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5850-
short_channel_id: 12,
5851-
timestamp: 2,
5852-
message_flags: 1, // Only must_be_one
5853-
channel_flags: 0,
5854-
cltv_expiry_delta: 0,
5855-
htlc_minimum_msat: 0,
5856-
htlc_maximum_msat: 200_000,
5857-
fee_base_msat: 0,
5858-
fee_proportional_millionths: 0,
5859-
excess_data: Vec::new()
5860-
});
5861-
update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
5862-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5863-
short_channel_id: 13,
5864-
timestamp: 2,
5865-
message_flags: 1, // Only must_be_one
5866-
channel_flags: 0,
5867-
cltv_expiry_delta: 0,
5868-
htlc_minimum_msat: 0,
5869-
htlc_maximum_msat: 200_000,
5870-
fee_base_msat: 0,
5871-
fee_proportional_millionths: 0,
5872-
excess_data: Vec::new()
5873-
});
5874-
5875-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5876-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5877-
short_channel_id: 6,
5878-
timestamp: 2,
5879-
message_flags: 1, // Only must_be_one
5880-
channel_flags: 0,
5881-
cltv_expiry_delta: 0,
5882-
htlc_minimum_msat: 0,
5883-
htlc_maximum_msat: 100_000,
5884-
fee_base_msat: 0,
5885-
fee_proportional_millionths: 0,
5886-
excess_data: Vec::new()
5887-
});
5888-
update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
5889-
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5890-
short_channel_id: 11,
5891-
timestamp: 2,
5892-
message_flags: 1, // Only must_be_one
5893-
channel_flags: 0,
5894-
cltv_expiry_delta: 0,
5895-
htlc_minimum_msat: 0,
5896-
htlc_maximum_msat: 100_000,
5897-
fee_base_msat: 0,
5898-
fee_proportional_millionths: 0,
5899-
excess_data: Vec::new()
5900-
});
5901-
5902-
// Path via {node7, node2} is channels {12, 13, 5}.
5903-
// We already limited them to 200 sats (they are used twice for 100 sats).
5904-
// Nothing to do here.
5905-
5743+
fn mpp_tests() {
5744+
let secp_ctx = Secp256k1::new();
5745+
let (_, _, _, nodes) = get_nodes(&secp_ctx);
59065746
{
5907-
// Attempt to route more than available results in a failure.
5908-
let route_params = RouteParameters::from_payment_params_and_value(
5909-
payment_params.clone(), 350_000);
5910-
if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
5911-
&our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5912-
&scorer, &Default::default(), &random_seed_bytes) {
5913-
assert_eq!(err, "Failed to find a sufficient route to the given destination");
5914-
} else { panic!(); }
5915-
}
5747+
// Check that if we have two cheaper paths and a more expensive (fewer hops) path, we
5748+
// choose the two cheaper paths:
5749+
let route = do_mpp_route_tests(180_000).unwrap();
5750+
assert_eq!(route.paths.len(), 2);
59165751

5752+
let mut total_value_transferred_msat = 0;
5753+
let mut total_paid_msat = 0;
5754+
for path in &route.paths {
5755+
assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
5756+
total_value_transferred_msat += path.final_value_msat();
5757+
for hop in &path.hops {
5758+
total_paid_msat += hop.fee_msat;
5759+
}
5760+
}
5761+
// If we paid fee, this would be higher.
5762+
assert_eq!(total_value_transferred_msat, 180_000);
5763+
let total_fees_paid = total_paid_msat - total_value_transferred_msat;
5764+
assert_eq!(total_fees_paid, 0);
5765+
}
59175766
{
5918-
// Now, attempt to route 300 sats (exact amount we can route).
5919-
// Our algorithm should provide us with these 3 paths, 100 sats each.
5920-
let route_params = RouteParameters::from_payment_params_and_value(
5921-
payment_params, 300_000);
5922-
let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5923-
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5767+
// Check that if we use the same channels but need to send more than we could fit in
5768+
// the cheaper paths we select all three paths:
5769+
let route = do_mpp_route_tests(300_000).unwrap();
59245770
assert_eq!(route.paths.len(), 3);
59255771

59265772
let mut total_amount_paid_msat = 0;
@@ -5930,11 +5776,11 @@ mod tests {
59305776
}
59315777
assert_eq!(total_amount_paid_msat, 300_000);
59325778
}
5933-
5779+
// Check that trying to pay more than our available liquidity fails.
5780+
assert!(do_mpp_route_tests(300_001).is_err());
59345781
}
59355782

5936-
#[test]
5937-
fn mpp_cheaper_route_test() {
5783+
fn do_mpp_route_tests(amt: u64) -> Result<Route, LightningError> {
59385784
let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
59395785
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
59405786
let scorer = ln_test_utils::TestScorer::new();
@@ -5944,21 +5790,17 @@ mod tests {
59445790
.with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
59455791
.unwrap();
59465792

5947-
// This test checks that if we have two cheaper paths and one more expensive path,
5948-
// so that liquidity-wise any 2 of 3 combination is sufficient,
5949-
// two cheaper paths will be taken.
5950-
// These paths have equal available liquidity.
5951-
5952-
// We need a combination of 3 paths:
5953-
// From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
5954-
// Note that these paths overlap (channels 5, 12, 13).
5955-
// Each path will have 100 sats capacity, those channels which
5956-
// are used twice will have 200 sats capacity.
5793+
// Build a setup where we have three potential paths from us to node3:
5794+
// {node0, node2, node4} (channels 1, 3, 6, 11), fee 0 msat,
5795+
// {node7, node2, node4} (channels 12, 13, 6, 11), fee 0 msat, and
5796+
// {node1} (channel 2, then a new channel 16), fee 1000 msat.
5797+
// Note that these paths overlap on channels 6 and 11.
5798+
// Each channel will have 100 sats capacity except for 6 and 11, which have 200.
59575799

59585800
// Disable other potential paths.
5959-
update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5801+
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
59605802
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5961-
short_channel_id: 2,
5803+
short_channel_id: 7,
59625804
timestamp: 2,
59635805
message_flags: 1, // Only must_be_one
59645806
channel_flags: 2,
@@ -5969,9 +5811,9 @@ mod tests {
59695811
fee_proportional_millionths: 0,
59705812
excess_data: Vec::new()
59715813
});
5972-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5814+
update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
59735815
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5974-
short_channel_id: 7,
5816+
short_channel_id: 4,
59755817
timestamp: 2,
59765818
message_flags: 1, // Only must_be_one
59775819
channel_flags: 2,
@@ -6011,31 +5853,30 @@ mod tests {
60115853
excess_data: Vec::new()
60125854
});
60135855

6014-
// Capacity of 200 sats because this channel will be used by 3rd path as well.
6015-
add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6016-
update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5856+
add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(16)), 16);
5857+
update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
60175858
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6018-
short_channel_id: 5,
5859+
short_channel_id: 16,
60195860
timestamp: 2,
60205861
message_flags: 1, // Only must_be_one
60215862
channel_flags: 0,
60225863
cltv_expiry_delta: 0,
60235864
htlc_minimum_msat: 0,
6024-
htlc_maximum_msat: 200_000,
6025-
fee_base_msat: 0,
5865+
htlc_maximum_msat: 100_000,
5866+
fee_base_msat: 1_000,
60265867
fee_proportional_millionths: 0,
60275868
excess_data: Vec::new()
60285869
});
60295870
update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
60305871
chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6031-
short_channel_id: 5,
5872+
short_channel_id: 16,
60325873
timestamp: 2,
60335874
message_flags: 1, // Only must_be_one
60345875
channel_flags: 3, // disable direction 1
60355876
cltv_expiry_delta: 0,
60365877
htlc_minimum_msat: 0,
6037-
htlc_maximum_msat: 200_000,
6038-
fee_base_msat: 0,
5878+
htlc_maximum_msat: 100_000,
5879+
fee_base_msat: 1_000,
60395880
fee_proportional_millionths: 0,
60405881
excess_data: Vec::new()
60415882
});
@@ -6051,7 +5892,7 @@ mod tests {
60515892
channel_flags: 0,
60525893
cltv_expiry_delta: 0,
60535894
htlc_minimum_msat: 0,
6054-
htlc_maximum_msat: 200_000,
5895+
htlc_maximum_msat: 100_000,
60555896
fee_base_msat: 0,
60565897
fee_proportional_millionths: 0,
60575898
excess_data: Vec::new()
@@ -6064,7 +5905,7 @@ mod tests {
60645905
channel_flags: 0,
60655906
cltv_expiry_delta: 0,
60665907
htlc_minimum_msat: 0,
6067-
htlc_maximum_msat: 200_000,
5908+
htlc_maximum_msat: 100_000,
60685909
fee_base_msat: 0,
60695910
fee_proportional_millionths: 0,
60705911
excess_data: Vec::new()
@@ -6078,8 +5919,8 @@ mod tests {
60785919
channel_flags: 0,
60795920
cltv_expiry_delta: 0,
60805921
htlc_minimum_msat: 0,
6081-
htlc_maximum_msat: 100_000,
6082-
fee_base_msat: 1_000,
5922+
htlc_maximum_msat: 200_000,
5923+
fee_base_msat: 0,
60835924
fee_proportional_millionths: 0,
60845925
excess_data: Vec::new()
60855926
});
@@ -6091,7 +5932,7 @@ mod tests {
60915932
channel_flags: 0,
60925933
cltv_expiry_delta: 0,
60935934
htlc_minimum_msat: 0,
6094-
htlc_maximum_msat: 100_000,
5935+
htlc_maximum_msat: 200_000,
60955936
fee_base_msat: 0,
60965937
fee_proportional_millionths: 0,
60975938
excess_data: Vec::new()
@@ -6101,29 +5942,11 @@ mod tests {
61015942
// We already limited them to 200 sats (they are used twice for 100 sats).
61025943
// Nothing to do here.
61035944

6104-
{
6105-
// Now, attempt to route 180 sats.
6106-
// Our algorithm should provide us with these 2 paths.
6107-
let route_params = RouteParameters::from_payment_params_and_value(
6108-
payment_params, 180_000);
6109-
let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6110-
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6111-
assert_eq!(route.paths.len(), 2);
6112-
6113-
let mut total_value_transferred_msat = 0;
6114-
let mut total_paid_msat = 0;
6115-
for path in &route.paths {
6116-
assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6117-
total_value_transferred_msat += path.final_value_msat();
6118-
for hop in &path.hops {
6119-
total_paid_msat += hop.fee_msat;
6120-
}
6121-
}
6122-
// If we paid fee, this would be higher.
6123-
assert_eq!(total_value_transferred_msat, 180_000);
6124-
let total_fees_paid = total_paid_msat - total_value_transferred_msat;
6125-
assert_eq!(total_fees_paid, 0);
6126-
}
5945+
let route_params = RouteParameters::from_payment_params_and_value(
5946+
payment_params, amt);
5947+
let res = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5948+
Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes);
5949+
res
61275950
}
61285951

61295952
#[test]

0 commit comments

Comments
 (0)