Skip to content

Commit 39257da

Browse files
committed
simln-lib: exclude capacity from excluded nodes list
1 parent 2bdd675 commit 39257da

File tree

2 files changed

+121
-22
lines changed

2 files changed

+121
-22
lines changed

sim-cli/src/parsing.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,6 @@ pub struct NetworkParser {
172172
pub node_2: ChannelPolicy,
173173
}
174174

175-
impl From<NetworkParser> for SimulatedChannel {
176-
fn from(network_parser: NetworkParser) -> Self {
177-
SimulatedChannel::new(
178-
network_parser.capacity_msat,
179-
network_parser.scid,
180-
network_parser.node_1,
181-
network_parser.node_2,
182-
)
183-
}
184-
}
185-
186175
/// Data structure used to parse information from the simulation file. It allows source and destination to be
187176
/// [NodeId], which enables the use of public keys and aliases in the simulation description.
188177
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -277,7 +266,17 @@ pub async fn create_simulation_with_network(
277266
let channels = sim_network
278267
.clone()
279268
.into_iter()
280-
.map(SimulatedChannel::from)
269+
.map(|channel| {
270+
let exclude_capacity = exclude.contains(&channel.node_1.pubkey)
271+
|| exclude.contains(&channel.node_2.pubkey);
272+
SimulatedChannel::new(
273+
channel.capacity_msat,
274+
channel.scid,
275+
channel.node_1,
276+
channel.node_2,
277+
exclude_capacity,
278+
)
279+
})
281280
.collect::<Vec<SimulatedChannel>>();
282281

283282
let mut nodes_info = HashMap::new();

simln-lib/src/sim_node.rs

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ pub struct SimulatedChannel {
319319
short_channel_id: ShortChannelID,
320320
node_1: ChannelState,
321321
node_2: ChannelState,
322+
// When excluding nodes from sending and receiving payments in a simulation (only used for
323+
// routing) we use this field to also exclude the capacity of the channel so that it is not
324+
// counted towards the capacity of a node that we do want to send payments from.
325+
exclude_capacity: bool,
322326
}
323327

324328
impl SimulatedChannel {
@@ -329,12 +333,14 @@ impl SimulatedChannel {
329333
short_channel_id: ShortChannelID,
330334
node_1: ChannelPolicy,
331335
node_2: ChannelPolicy,
336+
exclude_capacity: bool,
332337
) -> Self {
333338
SimulatedChannel {
334339
capacity_msat,
335340
short_channel_id,
336341
node_1: ChannelState::new(node_1, capacity_msat / 2),
337342
node_2: ChannelState::new(node_2, capacity_msat / 2),
343+
exclude_capacity,
338344
}
339345
}
340346

@@ -1062,16 +1068,18 @@ impl SimGraph {
10621068
Entry::Vacant(v) => v.insert(channel.clone()),
10631069
};
10641070

1065-
// It's okay to have duplicate pubkeys because one node can have many channels.
1066-
for info in [&channel.node_1.policy, &channel.node_2.policy] {
1067-
match nodes.entry(info.pubkey) {
1068-
Entry::Occupied(o) => o.into_mut().1.push(channel.capacity_msat),
1069-
Entry::Vacant(v) => {
1070-
v.insert((
1071-
node_info(info.pubkey, info.alias.clone()),
1072-
vec![channel.capacity_msat],
1073-
));
1074-
},
1071+
if !channel.exclude_capacity {
1072+
// It's okay to have duplicate pubkeys because one node can have many channels.
1073+
for info in [&channel.node_1.policy, &channel.node_2.policy] {
1074+
match nodes.entry(info.pubkey) {
1075+
Entry::Occupied(o) => o.into_mut().1.push(channel.capacity_msat),
1076+
Entry::Vacant(v) => {
1077+
v.insert((
1078+
node_info(info.pubkey, info.alias.clone()),
1079+
vec![channel.capacity_msat],
1080+
));
1081+
},
1082+
}
10751083
}
10761084
}
10771085
}
@@ -1588,6 +1596,7 @@ impl UtxoLookup for UtxoValidator {
15881596
#[cfg(test)]
15891597
mod tests {
15901598
use super::*;
1599+
use crate::clock::SimulationClock;
15911600
use crate::clock::SystemClock;
15921601
use crate::test_utils::get_random_keypair;
15931602
use lightning::routing::router::build_route_from_hops;
@@ -1597,6 +1606,7 @@ mod tests {
15971606
use std::time::Duration;
15981607
use tokio::sync::oneshot;
15991608
use tokio::time::{self, timeout};
1609+
use triggered::trigger;
16001610

16011611
/// Creates a test channel policy with its maximum HTLC size set to half of the in flight limit of the channel.
16021612
/// The minimum HTLC size is hardcoded to 2 so that we can fall beneath this value with a 1 msat htlc.
@@ -1660,6 +1670,7 @@ mod tests {
16601670
short_channel_id: ShortChannelID::from(i),
16611671
node_1: ChannelState::new(node_1_to_2, capacity_msat),
16621672
node_2: ChannelState::new(node_2_to_1, 0),
1673+
exclude_capacity: false,
16631674
});
16641675

16651676
// Progress source ID to create a chain of nodes.
@@ -1896,6 +1907,94 @@ mod tests {
18961907
));
18971908
}
18981909

1910+
#[tokio::test]
1911+
async fn test_excluded_channel_balance() {
1912+
let capacity_1 = 200_000_000;
1913+
let capacity_2 = 300_000_000;
1914+
1915+
let pk1 = get_random_keypair().1;
1916+
let pk2 = get_random_keypair().1;
1917+
let pk3 = get_random_keypair().1;
1918+
1919+
let create_policy = |max_in_flight_msat: u64, pubkey: PublicKey| -> ChannelPolicy {
1920+
ChannelPolicy {
1921+
pubkey,
1922+
alias: String::default(),
1923+
max_htlc_count: 10,
1924+
max_in_flight_msat,
1925+
min_htlc_size_msat: 2,
1926+
max_htlc_size_msat: max_in_flight_msat / 2,
1927+
cltv_expiry_delta: 10,
1928+
base_fee: 1000,
1929+
fee_rate_prop: 5000,
1930+
}
1931+
};
1932+
1933+
let channels = vec![
1934+
SimulatedChannel::new(
1935+
capacity_1,
1936+
ShortChannelID::from(1),
1937+
create_policy(capacity_1 / 2, pk1),
1938+
create_policy(capacity_1 / 2, pk2),
1939+
false,
1940+
),
1941+
SimulatedChannel::new(
1942+
capacity_2,
1943+
ShortChannelID::from(2),
1944+
create_policy(capacity_2 / 2, pk1),
1945+
create_policy(capacity_2 / 2, pk3),
1946+
true,
1947+
),
1948+
];
1949+
1950+
let sim_graph = Arc::new(Mutex::new(
1951+
SimGraph::new(
1952+
channels.clone(),
1953+
TaskTracker::new(),
1954+
Vec::new(),
1955+
CustomRecords::default(),
1956+
trigger(),
1957+
)
1958+
.unwrap(),
1959+
));
1960+
1961+
let clock = Arc::new(SimulationClock::new(1).unwrap());
1962+
let routing_graph = Arc::new(populate_network_graph(channels, Arc::clone(&clock)).unwrap());
1963+
1964+
let nodes = ln_node_from_graph(sim_graph, routing_graph, clock)
1965+
.await
1966+
.unwrap();
1967+
1968+
let node_1_channels = nodes
1969+
.get(&pk1)
1970+
.unwrap()
1971+
.lock()
1972+
.await
1973+
.list_channels()
1974+
.await
1975+
.unwrap();
1976+
1977+
// Node 1 has 2 channels but one was excluded so here we should only have the one that was
1978+
// not excluded.
1979+
assert!(node_1_channels.len() == 1);
1980+
assert!(node_1_channels[0] == capacity_1);
1981+
1982+
let node_2_channels = nodes
1983+
.get(&pk2)
1984+
.unwrap()
1985+
.lock()
1986+
.await
1987+
.list_channels()
1988+
.await
1989+
.unwrap();
1990+
1991+
assert!(node_2_channels.len() == 1);
1992+
assert!(node_2_channels[0] == capacity_1);
1993+
1994+
// Node 3's only channel was excluded so it won't be present here.
1995+
assert!(!nodes.contains_key(&pk3));
1996+
}
1997+
18991998
/// Tests basic functionality of a `SimulatedChannel` but does no endeavor to test the underlying
19001999
/// `ChannelState`, as this is covered elsewhere in our tests.
19012000
#[test]
@@ -1911,6 +2010,7 @@ mod tests {
19112010
short_channel_id: ShortChannelID::from(123),
19122011
node_1: node_1.clone(),
19132012
node_2: node_2.clone(),
2013+
exclude_capacity: false,
19142014
};
19152015

19162016
// Assert that we're not able to send a htlc over node_2 -> node_1 (no liquidity).

0 commit comments

Comments
 (0)