@@ -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
324328impl 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) ]
15891597mod 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