Skip to content

Commit 8e9de64

Browse files
Harden test to include mpp
1 parent f7ea5de commit 8e9de64

File tree

2 files changed

+230
-50
lines changed

2 files changed

+230
-50
lines changed

lightning/src/routing/network_graph.rs

Lines changed: 225 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,11 @@ pub struct ChannelInfo {
281281
/// Protocol features of a channel communicated during its announcement
282282
pub features: ChannelFeatures,
283283
/// Source node of the first direction of a channel
284-
pub node_one: PublicKey,
284+
pub node_alice: PublicKey,
285285
/// Details about the first direction of a channel
286286
pub alice_to_bob: Option<DirectionalChannelInfo>,
287287
/// Source node of the second direction of a channel
288-
pub node_two: PublicKey,
288+
pub node_bob: PublicKey,
289289
/// Details about the second direction of a channel
290290
pub bob_to_alice: Option<DirectionalChannelInfo>,
291291
/// An initial announcement of the channel
@@ -297,17 +297,17 @@ pub struct ChannelInfo {
297297

298298
impl std::fmt::Display for ChannelInfo {
299299
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
300-
write!(f, "features: {}, node_one: {}, alice_to_bob: {:?}, node_two: {}, bob_to_alice: {:?}",
301-
log_bytes!(self.features.encode()), log_pubkey!(self.node_one), self.alice_to_bob, log_pubkey!(self.node_two), self.bob_to_alice)?;
300+
write!(f, "features: {}, node_alice: {}, alice_to_bob: {:?}, node_bob: {}, bob_to_alice: {:?}",
301+
log_bytes!(self.features.encode()), log_pubkey!(self.node_alice), self.alice_to_bob, log_pubkey!(self.node_bob), self.bob_to_alice)?;
302302
Ok(())
303303
}
304304
}
305305

306306
impl_writeable!(ChannelInfo, 0, {
307307
features,
308-
node_one,
308+
node_alice,
309309
alice_to_bob,
310-
node_two,
310+
node_bob,
311311
bob_to_alice,
312312
announcement_message
313313
});
@@ -577,16 +577,18 @@ impl NetworkGraph {
577577
for route_hop in path {
578578
let short_channel_id = route_hop.short_channel_id;
579579
let channel = self.channels.get_mut(&short_channel_id).unwrap();
580-
let directional_channel_info = if route_hop.pubkey == channel.node_one {
581-
channel.alice_to_bob.as_mut().unwrap()
582-
} else {
583-
channel.bob_to_alice.as_mut().unwrap()
584-
};
585-
let channel_score = &mut directional_channel_info.channel_score;
586580
if faultive_nodes.contains(&(route_hop.pubkey)) {
581+
let directional_channel_info = if route_hop.pubkey == channel.node_alice {
582+
channel.bob_to_alice.as_mut().unwrap()
583+
} else {
584+
channel.alice_to_bob.as_mut().unwrap()
585+
};
586+
let channel_score = &mut directional_channel_info.channel_score;
587587
channel_score.payment_failed_score += 1;
588+
break; // You don't want to reward channels past this point in the path, but you don't want to penalize either. So here we just move onto the next path in the route.
588589
} else {
589-
channel_score.payment_sent_score += 1;
590+
channel.alice_to_bob.as_mut().unwrap().channel_score.payment_sent_score += 1;
591+
channel.bob_to_alice.as_mut().unwrap().channel_score.payment_sent_score += 1;
590592
}
591593
}
592594
}
@@ -644,9 +646,9 @@ impl NetworkGraph {
644646

645647
let chan_info = ChannelInfo {
646648
features: msg.contents.features.clone(),
647-
node_one: msg.contents.node_id_1.clone(),
649+
node_alice: msg.contents.node_id_1.clone(),
648650
alice_to_bob: None,
649-
node_two: msg.contents.node_id_2.clone(),
651+
node_bob: msg.contents.node_id_2.clone(),
650652
bob_to_alice: None,
651653
announcement_message: if should_relay { Some(msg.clone()) } else { None },
652654
};
@@ -776,17 +778,17 @@ impl NetworkGraph {
776778

777779
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
778780
if msg.contents.flags & 1 == 1 {
779-
dest_node_id = channel.node_one.clone();
781+
dest_node_id = channel.node_alice.clone();
780782
if let Some(sig_verifier) = secp_ctx {
781-
secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_two);
783+
secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_bob);
782784
}
783-
maybe_update_channel_info!(channel.bob_to_alice, channel.node_two);
785+
maybe_update_channel_info!(channel.bob_to_alice, channel.node_bob);
784786
} else {
785-
dest_node_id = channel.node_two.clone();
787+
dest_node_id = channel.node_bob.clone();
786788
if let Some(sig_verifier) = secp_ctx {
787-
secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_one);
789+
secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_alice);
788790
}
789-
maybe_update_channel_info!(channel.alice_to_bob, channel.node_one);
791+
maybe_update_channel_info!(channel.alice_to_bob, channel.node_alice);
790792
}
791793
}
792794
}
@@ -810,7 +812,7 @@ impl NetworkGraph {
810812
for chan_id in node.channels.iter() {
811813
let chan = self.channels.get(chan_id).unwrap();
812814
let chan_info_opt;
813-
if chan.node_one == dest_node_id {
815+
if chan.node_alice == dest_node_id {
814816
chan_info_opt = chan.bob_to_alice.as_ref();
815817
} else {
816818
chan_info_opt = chan.alice_to_bob.as_ref();
@@ -847,8 +849,8 @@ impl NetworkGraph {
847849
}
848850
}
849851

850-
remove_from_node!(chan.node_one);
851-
remove_from_node!(chan.node_two);
852+
remove_from_node!(chan.node_alice);
853+
remove_from_node!(chan.node_bob);
852854
}
853855
}
854856

@@ -1760,6 +1762,7 @@ mod tests {
17601762
// node_3 -> node_4
17611763
// We can use this to simulate a MPP from node_1 to node_4 via node_2 and node_3.
17621764
let (secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler();
1765+
let num_nodes = 4;
17631766
let node_0_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
17641767
let node_1_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
17651768
let node_2_privkey = &SecretKey::from_slice(&[40; 32]).unwrap();
@@ -1787,8 +1790,15 @@ mod tests {
17871790

17881791
{
17891792
// Create channels between each node
1790-
for i in 0..=3 {
1791-
for j in 0..=3 {
1793+
// The short channel IDs will be assigned as follows:
1794+
// 0 <-> 1 = 0
1795+
// 0 <-> 2 = 1
1796+
// 0 <-> 3 = 2
1797+
// 1 <-> 2 = 3
1798+
// 1 <-> 3 = 4
1799+
// 2 <-> 3 = 5
1800+
for i in 0..num_nodes {
1801+
for j in 0..num_nodes {
17921802
if i >= j {
17931803
continue;
17941804
} else {
@@ -1832,7 +1842,6 @@ mod tests {
18321842
// channel
18331843
let mut network = net_graph_msg_handler.network_graph.write().unwrap();
18341844
for channel_id in 0..short_channel_id {
1835-
//let chan_id = network.get_nodes().get(&node_ids[0]).unwrap().channels[0];
18361845
let channel_info = network.channels.get_mut(&channel_id).unwrap();
18371846
// Assign a DirectionalChannelInfo and ChannelScore object to alice_to_bob of
18381847
// channel_info
@@ -1877,12 +1886,12 @@ mod tests {
18771886
}
18781887
}
18791888

1880-
// From here on out we simulate the network learning of payments.
1889+
// Network is now setup so we can proceed with testing the scoring function
18811890
{
18821891
// Assume a PaymentSent event is picked up and it consists of a simple payment from
18831892
// node_0 to node_1
18841893
let route_hop = RouteHop {
1885-
pubkey: node_ids[0],
1894+
pubkey: node_ids[1],
18861895
node_features: NodeFeatures::empty(),
18871896
short_channel_id: 0,
18881897
channel_features: ChannelFeatures::empty(),
@@ -1895,37 +1904,208 @@ mod tests {
18951904
let sent_res = network.score_payment_sent_for_route(sent_route);
18961905
assert!(sent_res.unwrap() == true);
18971906
// Check that score_payment_sent_for_route incremented the appropriate ChannelScore
1898-
let chan_id = network.get_nodes().get(&node_ids[0]).unwrap().channels[0];
1907+
let chan_id = 0;
18991908
let channel_info = network.channels.get_mut(&chan_id).unwrap();
19001909
let dir_alice_to_bob = &channel_info.alice_to_bob.as_ref();
19011910
assert_eq!(dir_alice_to_bob.unwrap().channel_score.payment_sent_score, 1);
19021911
assert_eq!(dir_alice_to_bob.unwrap().channel_score.payment_failed_score, 0);
1912+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
1913+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
19031914
}
19041915

19051916
{
1906-
let route_hop = RouteHop {
1907-
pubkey: node_ids[0],
1908-
node_features: NodeFeatures::empty(),
1909-
short_channel_id: 0,
1910-
channel_features: ChannelFeatures::empty(),
1911-
fee_msat: 0,
1912-
cltv_expiry_delta: 0,
1913-
};
19141917
// Assume a payment fails due to node_1 (identified by its PublicKey), verify that its
1915-
// directional channel's score (node_1 -> node_2) has its PaymentFailed score
1918+
// directional channel's score (node_0 -> node_1) has its PaymentFailed score
19161919
// incremented.
1917-
let faultive_nodes: Vec<PublicKey> = vec![node_ids[0]];
1920+
let route_hop = RouteHop {
1921+
pubkey: node_ids[1],
1922+
node_features: NodeFeatures::empty(),
1923+
short_channel_id: 0,
1924+
channel_features: ChannelFeatures::empty(),
1925+
fee_msat: 0,
1926+
cltv_expiry_delta: 0,
1927+
};
1928+
let faultive_nodes: Vec<PublicKey> = vec![node_ids[1]];
19181929
let attempted_path: Vec<RouteHop> = vec![route_hop];
19191930
let failed_route: Vec<Vec<RouteHop>> = vec![attempted_path];
19201931
let mut network = net_graph_msg_handler.network_graph.write().unwrap();
19211932
let failed_res = network.score_payment_failed_for_route(failed_route, faultive_nodes);
19221933
assert!(failed_res.unwrap() == true);
1923-
let chan_id = network.get_nodes().get(&node_ids[0]).unwrap().channels[0];
1934+
let chan_id = 0;
19241935
let channel_info = network.channels.get_mut(&chan_id).unwrap();
1925-
assert!(channel_info.node_two == node_ids[1]);
1926-
let dir_alice_to_bob = &channel_info.alice_to_bob.as_ref();
1927-
assert_eq!(dir_alice_to_bob.unwrap().channel_score.payment_sent_score, 1);
1928-
assert_eq!(dir_alice_to_bob.unwrap().channel_score.payment_failed_score, 1);
1936+
assert!(channel_info.node_bob == node_ids[1]);
1937+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 1);
1938+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 1);
1939+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
1940+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
1941+
}
1942+
1943+
{
1944+
// In this case, the route through node_1 succeeded, but the route through node_2
1945+
// failed. We expect the node_0 <-> node_2 channel to be penalized.
1946+
let mut route_hops: Vec<RouteHop> = vec![];
1947+
for i in 0..num_nodes {
1948+
let route_hop = RouteHop {
1949+
pubkey: node_ids[i],
1950+
node_features: NodeFeatures::empty(),
1951+
short_channel_id: 0,
1952+
channel_features: ChannelFeatures::empty(),
1953+
fee_msat: 0,
1954+
cltv_expiry_delta: 0,
1955+
};
1956+
route_hops.push(route_hop);
1957+
}
1958+
let faultive_nodes: Vec<PublicKey> = vec![node_ids[2]];
1959+
let mut success_path: Vec<RouteHop> = vec![route_hops[1].clone(), route_hops[3].clone()];
1960+
let mut failed_path: Vec<RouteHop> = vec![route_hops[2].clone(), route_hops[3].clone()];
1961+
1962+
let mut network = net_graph_msg_handler.network_graph.write().unwrap();
1963+
success_path[0].short_channel_id = 0;
1964+
success_path[1].short_channel_id = 4;
1965+
failed_path[0].short_channel_id = 1;
1966+
failed_path[1].short_channel_id = 5;
1967+
1968+
let mpp_route: Vec<Vec<RouteHop>> = vec![success_path, failed_path];
1969+
let failed_res = network.score_payment_failed_for_route(mpp_route, faultive_nodes);
1970+
assert!(failed_res.unwrap() == true);
1971+
}
1972+
1973+
{
1974+
let network = net_graph_msg_handler.network_graph.read().unwrap();
1975+
let mut chan_id = 0; // Check on 0 <-> 1
1976+
let mut channel_info = network.channels.get(&chan_id).unwrap();
1977+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 2);
1978+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 1);
1979+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 2);
1980+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
1981+
1982+
chan_id = 1; // Check on 0 <-> 2
1983+
channel_info = network.channels.get(&chan_id).unwrap();
1984+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 0);
1985+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 1);
1986+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 0);
1987+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
1988+
}
1989+
1990+
{
1991+
// In this case, both routes succeed, so we will check that the payment_sent_score's
1992+
// for all channels are incremented.
1993+
let mut route_hops: Vec<RouteHop> = vec![];
1994+
for i in 0..num_nodes {
1995+
let route_hop = RouteHop {
1996+
pubkey: node_ids[i],
1997+
node_features: NodeFeatures::empty(),
1998+
short_channel_id: 0,
1999+
channel_features: ChannelFeatures::empty(),
2000+
fee_msat: 0,
2001+
cltv_expiry_delta: 0,
2002+
};
2003+
route_hops.push(route_hop);
2004+
}
2005+
let mut success_path_1: Vec<RouteHop> = vec![route_hops[1].clone(), route_hops[3].clone()];
2006+
let mut success_path_2: Vec<RouteHop> = vec![route_hops[2].clone(), route_hops[3].clone()];
2007+
2008+
let mut network = net_graph_msg_handler.network_graph.write().unwrap();
2009+
success_path_1[0].short_channel_id = 0;
2010+
success_path_1[1].short_channel_id = 4;
2011+
success_path_2[0].short_channel_id = 1;
2012+
success_path_2[1].short_channel_id = 5;
2013+
2014+
let mpp_route: Vec<Vec<RouteHop>> = vec![success_path_1, success_path_2];
2015+
let failed_res = network.score_payment_sent_for_route(mpp_route);
2016+
assert!(failed_res.unwrap() == true);
2017+
}
2018+
2019+
{
2020+
let network = net_graph_msg_handler.network_graph.read().unwrap();
2021+
let mut chan_id = 0; // Check on 0 <-> 1
2022+
let mut channel_info = network.channels.get(&chan_id).unwrap();
2023+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 3);
2024+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 1);
2025+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 3);
2026+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2027+
2028+
chan_id = 1; // Check on 0 <-> 2
2029+
channel_info = network.channels.get(&chan_id).unwrap();
2030+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 1);
2031+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 1);
2032+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
2033+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2034+
2035+
chan_id = 4; // Check on 1 <-> 3
2036+
channel_info = network.channels.get(&chan_id).unwrap();
2037+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 2);
2038+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 0);
2039+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 2);
2040+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2041+
2042+
chan_id = 5; // Check on 2 <-> 3
2043+
channel_info = network.channels.get(&chan_id).unwrap();
2044+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 1);
2045+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 0);
2046+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
2047+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2048+
}
2049+
2050+
{
2051+
// In this case, both routes fail, so we will check that the payment_fail_score's
2052+
// for all 0 <-> 1 and 0 <-> 2 are incremented while 1 <->3 and 2 <-> 3 remain the
2053+
// same.
2054+
let mut route_hops: Vec<RouteHop> = vec![];
2055+
for i in 0..num_nodes {
2056+
let route_hop = RouteHop {
2057+
pubkey: node_ids[i],
2058+
node_features: NodeFeatures::empty(),
2059+
short_channel_id: 0,
2060+
channel_features: ChannelFeatures::empty(),
2061+
fee_msat: 0,
2062+
cltv_expiry_delta: 0,
2063+
};
2064+
route_hops.push(route_hop);
2065+
}
2066+
let faultive_nodes = vec![node_ids[1], node_ids[2]];
2067+
let mut fail_path_1: Vec<RouteHop> = vec![route_hops[1].clone(), route_hops[3].clone()];
2068+
let mut fail_path_2: Vec<RouteHop> = vec![route_hops[2].clone(), route_hops[3].clone()];
2069+
2070+
let mut network = net_graph_msg_handler.network_graph.write().unwrap();
2071+
fail_path_1[0].short_channel_id = 0;
2072+
fail_path_1[1].short_channel_id = 4;
2073+
fail_path_2[0].short_channel_id = 1;
2074+
fail_path_2[1].short_channel_id = 5;
2075+
2076+
let mpp_route: Vec<Vec<RouteHop>> = vec![fail_path_1, fail_path_2];
2077+
let failed_res = network.score_payment_failed_for_route(mpp_route, faultive_nodes);
2078+
assert!(failed_res.unwrap() == true);
2079+
}
2080+
{
2081+
let network = net_graph_msg_handler.network_graph.read().unwrap();
2082+
let mut chan_id = 0; // Check on 0 <-> 1
2083+
let mut channel_info = network.channels.get(&chan_id).unwrap();
2084+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 3);
2085+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 2);
2086+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 3);
2087+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2088+
2089+
chan_id = 1; // Check on 0 <-> 2
2090+
channel_info = network.channels.get(&chan_id).unwrap();
2091+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 1);
2092+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 2);
2093+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
2094+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2095+
2096+
chan_id = 4; // Check on 1 <-> 3
2097+
channel_info = network.channels.get(&chan_id).unwrap();
2098+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 2);
2099+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 0);
2100+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 2);
2101+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
2102+
2103+
chan_id = 5; // Check on 2 <-> 3
2104+
channel_info = network.channels.get(&chan_id).unwrap();
2105+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_sent_score, 1);
2106+
assert_eq!(channel_info.alice_to_bob.as_ref().unwrap().channel_score.payment_failed_score, 0);
2107+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_sent_score, 1);
2108+
assert_eq!(channel_info.bob_to_alice.as_ref().unwrap().channel_score.payment_failed_score, 0);
19292109
}
19302110
}
19312111
}

0 commit comments

Comments
 (0)