1
- use bitcoin:: secp256k1:: PublicKey ;
2
- use std:: collections:: HashMap ;
3
- use std:: path:: PathBuf ;
4
- use std:: sync:: Arc ;
5
- use tokio:: sync:: Mutex ;
6
-
7
1
use anyhow:: anyhow;
2
+ use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
8
3
use clap:: builder:: TypedValueParser ;
9
4
use clap:: Parser ;
10
5
use log:: LevelFilter ;
6
+ use rand:: distributions:: Uniform ;
7
+ use rand:: Rng ;
11
8
use sim_lib:: {
12
- cln:: ClnNode , lnd:: LndNode , ActivityDefinition , LightningError , LightningNode , NodeConnection ,
13
- NodeId , SimParams , Simulation , WriteResults ,
9
+ cln:: ClnNode ,
10
+ lnd:: LndNode ,
11
+ sim_node:: {
12
+ ln_node_from_graph, populate_network_graph, ChannelPolicy , SimGraph , SimulatedChannel ,
13
+ } ,
14
+ ActivityDefinition , LightningError , LightningNode , NodeConnection , NodeId , SimParams ,
15
+ Simulation , WriteResults ,
14
16
} ;
15
17
use simple_logger:: SimpleLogger ;
18
+ use std:: collections:: HashMap ;
19
+ use std:: path:: PathBuf ;
20
+ use std:: sync:: Arc ;
21
+ use tokio:: sync:: Mutex ;
16
22
17
23
/// The default directory where the simulation files are stored and where the results will be written to.
18
24
pub const DEFAULT_DATA_DIR : & str = "." ;
@@ -189,7 +195,6 @@ async fn main() -> anyhow::Result<()> {
189
195
amount_msat : act. amount_msat ,
190
196
} ) ;
191
197
}
192
-
193
198
let write_results = if !cli. no_results {
194
199
Some ( WriteResults {
195
200
results_dir : mkdir ( cli. data_dir . join ( "results" ) ) . await ?,
@@ -200,8 +205,20 @@ async fn main() -> anyhow::Result<()> {
200
205
} ;
201
206
202
207
let ( shutdown_trigger, shutdown_listener) = triggered:: trigger ( ) ;
208
+
209
+ let channels = generate_sim_nodes ( ) ;
210
+ let graph = match SimGraph :: new ( channels. clone ( ) , shutdown_trigger. clone ( ) ) {
211
+ Ok ( graph) => Arc :: new ( Mutex :: new ( graph) ) ,
212
+ Err ( e) => anyhow:: bail!( "failed: {:?}" , e) ,
213
+ } ;
214
+
215
+ let routing_graph = match populate_network_graph ( channels) {
216
+ Ok ( r) => r,
217
+ Err ( e) => anyhow:: bail!( "failed: {:?}" , e) ,
218
+ } ;
219
+
203
220
let sim = Simulation :: new (
204
- clients ,
221
+ ln_node_from_graph ( graph . clone ( ) , Arc :: new ( routing_graph ) ) . await ,
205
222
validated_activities,
206
223
cli. total_time ,
207
224
cli. expected_pmt_amt ,
@@ -216,11 +233,93 @@ async fn main() -> anyhow::Result<()> {
216
233
sim2. shutdown ( ) ;
217
234
} ) ?;
218
235
236
+ // Run the simulation (blocking) until it exits. Once this happens, we can also wait for the simulated graph to
237
+ // shut down. Errors in either of these will universally trigger shutdown because we share a trigger, so it doesn't
238
+ // matter what order we wait for these.
219
239
sim. run ( ) . await ?;
240
+ graph. lock ( ) . await . wait_for_shutdown ( ) . await ;
220
241
221
242
Ok ( ( ) )
222
243
}
223
244
245
+ fn generate_sim_nodes ( ) -> Vec < SimulatedChannel > {
246
+ let capacity = 300000000 ;
247
+ let mut channels: Vec < SimulatedChannel > = vec ! [ ] ;
248
+ let ( _, first_node) = get_random_keypair ( ) ;
249
+
250
+ // Create channels in a ring so that we'll get long payment paths.
251
+ let mut node_1 = first_node;
252
+ for i in 0 ..10 {
253
+ // Create a new node that we'll create a channel with. If we're on the last node in the circle, we'll loop
254
+ // back around to the first node to close it.
255
+ let node_2 = if i == 10 {
256
+ first_node
257
+ } else {
258
+ let ( _, pk) = get_random_keypair ( ) ;
259
+ pk
260
+ } ;
261
+
262
+ let node_1_to_2 = ChannelPolicy {
263
+ pubkey : node_1,
264
+ max_htlc_count : 483 ,
265
+ max_in_flight_msat : capacity / 2 ,
266
+ min_htlc_size_msat : 1 ,
267
+ max_htlc_size_msat : capacity / 2 ,
268
+ cltv_expiry_delta : 40 ,
269
+ // Alter fee rate a little for different values.
270
+ base_fee : 1000 * i,
271
+ fee_rate_prop : 1500 * i,
272
+ } ;
273
+
274
+ let node_2_to_1 = ChannelPolicy {
275
+ pubkey : node_2,
276
+ max_htlc_count : 483 ,
277
+ max_in_flight_msat : capacity / 2 ,
278
+ min_htlc_size_msat : 1 ,
279
+ max_htlc_size_msat : capacity / 2 ,
280
+ cltv_expiry_delta : 40 + 10 * i as u32 ,
281
+ // Alter fee rate a little for different values.
282
+ base_fee : 2000 * i,
283
+ fee_rate_prop : i,
284
+ } ;
285
+
286
+ channels. push ( SimulatedChannel :: new (
287
+ capacity,
288
+ // Unique channel ID per link.
289
+ 100 + i,
290
+ node_1_to_2,
291
+ node_2_to_1,
292
+ ) ) ;
293
+
294
+ // Once we've created this link in the circle, progress our current node to be node_1 so that we can generate
295
+ // a new edge.
296
+ node_1 = node_2;
297
+ }
298
+
299
+ channels
300
+ }
301
+
302
+ /// COPIED from test utils!
303
+ pub fn get_random_bytes ( size : usize ) -> Vec < u8 > {
304
+ rand:: thread_rng ( )
305
+ . sample_iter ( Uniform :: new ( u8:: MIN , u8:: MAX ) )
306
+ . take ( size)
307
+ . collect ( )
308
+ }
309
+
310
+ pub fn get_random_int ( s : u64 , e : u64 ) -> u64 {
311
+ rand:: thread_rng ( ) . gen_range ( s..e)
312
+ }
313
+
314
+ pub fn get_random_keypair ( ) -> ( SecretKey , PublicKey ) {
315
+ loop {
316
+ if let Ok ( sk) = SecretKey :: from_slice ( & get_random_bytes ( 32 ) ) {
317
+ return ( sk, PublicKey :: from_secret_key ( & Secp256k1 :: new ( ) , & sk) ) ;
318
+ }
319
+ }
320
+ }
321
+ /// COPIED from test utils!
322
+
224
323
async fn read_sim_path ( data_dir : PathBuf , sim_file : PathBuf ) -> anyhow:: Result < PathBuf > {
225
324
let sim_path = if sim_file. is_relative ( ) {
226
325
data_dir. join ( sim_file)
0 commit comments