@@ -37,12 +37,13 @@ use amaru_stores::rocksdb::consensus::InMemConsensusStore;
3737use anyhow:: Error ;
3838use bytes:: Bytes ;
3939use clap:: Parser ;
40- use generate:: { generate_inputs_strategy , parse_json, read_chain_json} ;
40+ use generate:: { generate_entries , parse_json, read_chain_json} ;
4141use ledger:: { populate_chain_store, FakeStakeDistribution } ;
42- use proptest:: test_runner:: Config ;
4342use pure_stage:: { simulation:: SimulationBuilder , trace_buffer:: TraceBuffer , StageRef } ;
44- use pure_stage:: { Receiver , StageGraph , Void } ;
45- use simulate:: { pure_stage_node_handle, simulate, Trace } ;
43+ use pure_stage:: { Instant , Receiver , StageGraph , Void } ;
44+ use rand:: Rng ;
45+ use simulate:: { pure_stage_node_handle, simulate, History , SimulateConfig } ;
46+ use std:: time:: Duration ;
4647use std:: { path:: PathBuf , sync:: Arc } ;
4748use tokio:: sync:: Mutex ;
4849use tracing:: { info, Span } ;
@@ -81,6 +82,18 @@ pub struct Args {
8182 #[ arg( long, default_value_t = Hash :: from( [ 0 ; 32 ] ) ) ]
8283 pub start_header : Hash < 32 > ,
8384
85+ /// Number of tests to run in simulation
86+ #[ arg( long, default_value = "50" ) ]
87+ pub number_of_tests : Option < u32 > ,
88+
89+ /// Number of nodes in simulation.
90+ #[ arg( long, default_value = "1" ) ]
91+ pub number_of_nodes : Option < u8 > ,
92+
93+ /// Number of upstream peers to simulate
94+ #[ arg( long, default_value = "2" ) ]
95+ pub number_of_upstream_peers : Option < u8 > ,
96+
8497 /// Seed for simulation testing.
8598 #[ arg( long) ]
8699 pub seed : Option < u64 > ,
@@ -108,8 +121,9 @@ fn init_node(args: &Args) -> (GlobalParameters, SelectChain, ValidateHeader) {
108121 let select_chain = SelectChain :: new ( make_chain_selector (
109122 Origin ,
110123 & chain_store,
111- // FIXME: Shouldn't be hardcoded!
112- & vec ! [ Peer :: new( "c1" ) ] ,
124+ & ( 1 ..=args. number_of_upstream_peers . unwrap_or ( 2 ) )
125+ . map ( |i| Peer :: new ( & format ! ( "c{}" , i) ) )
126+ . collect :: < Vec < _ > > ( ) ,
113127 ) ) ;
114128 let chain_ref = Arc :: new ( Mutex :: new ( chain_store) ) ;
115129 let validate_header = ValidateHeader :: new ( Arc :: new ( stake_distribution) , chain_ref. clone ( ) ) ;
@@ -334,7 +348,9 @@ fn spawn_node(
334348}
335349
336350pub fn run ( rt : tokio:: runtime:: Runtime , args : Args ) {
337- let number_of_nodes = 1 ;
351+ let number_of_tests = args. number_of_tests . unwrap_or ( 50 ) ;
352+ let number_of_nodes = args. number_of_nodes . unwrap_or ( 1 ) ;
353+ let number_of_upstream_peers = args. number_of_upstream_peers . unwrap_or ( 2 ) ;
338354 let trace_buffer = Arc :: new ( parking_lot:: Mutex :: new ( TraceBuffer :: new ( 42 , 1_000_000_000 ) ) ) ;
339355
340356 let spawn = || {
@@ -344,11 +360,24 @@ pub fn run(rt: tokio::runtime::Runtime, args: Args) {
344360 pure_stage_node_handle ( rx, receive, running) . unwrap ( )
345361 } ;
346362
363+ let seed = args. seed . unwrap_or ( {
364+ let mut rng = rand:: rng ( ) ;
365+ rng. random :: < u64 > ( )
366+ } ) ;
367+
347368 simulate (
348- Config :: default ( ) ,
349- number_of_nodes,
369+ SimulateConfig {
370+ number_of_tests,
371+ seed,
372+ number_of_nodes,
373+ } ,
350374 spawn,
351- generate_inputs_strategy ( & args. block_tree_file , args. seed ) ,
375+ generate_entries (
376+ & args. block_tree_file ,
377+ Instant :: at_offset ( Duration :: from_secs ( 0 ) ) ,
378+ 200.0 ,
379+ number_of_upstream_peers,
380+ ) ,
352381 chain_property ( & args. block_tree_file ) ,
353382 trace_buffer. clone ( ) ,
354383 args. persist_on_success ,
@@ -357,15 +386,13 @@ pub fn run(rt: tokio::runtime::Runtime, args: Args) {
357386
358387fn chain_property (
359388 chain_data_path : & PathBuf ,
360- ) -> impl Fn ( Trace < ChainSyncMessage > ) -> Result < ( ) , String > + use < ' _ > {
361- move |trace | {
362- match trace . 0 . last ( ) {
363- None => Err ( "impossible, no last entry in trace " . to_string ( ) ) ,
389+ ) -> impl Fn ( History < ChainSyncMessage > ) -> Result < ( ) , String > + use < ' _ > {
390+ move |history | {
391+ match history . 0 . last ( ) {
392+ None => Err ( "impossible, no last entry in history " . to_string ( ) ) ,
364393 Some ( entry) => {
365- assert_eq ! ( entry. src, "n1" , "entry: {:?}, trace: {:?}" , entry, trace) ;
366- assert_eq ! ( entry. dest, "c1" ) ;
367394 // FIXME: the property is wrong, we should check the property
368- // that the output message trace is a prefix of the read chain
395+ // that the output message history is a prefix of the read chain
369396 let data = read_chain_json ( chain_data_path) ;
370397 let blocks = parse_json ( data. as_bytes ( ) ) . map_err ( |err| err. to_string ( ) ) ?;
371398 match & entry. body {
@@ -376,20 +403,13 @@ fn chain_property(
376403 . map ( |block| ( block. hash . clone ( ) , Slot :: from ( block. slot ) ) )
377404 . expect ( "empty chain data" ) ;
378405 if actual != expected {
379- panic ! (
406+ return Err ( format ! (
380407 "tip of chains don't match, expected {:?}, got {:?}" ,
381408 expected, actual
382- ) ;
383- }
384- info ! ( "Success!" )
385- }
386- _ => {
387- info ! ( "TRACE:" ) ;
388- for entry in & trace. 0 {
389- info ! ( "{:?}" , entry) ;
409+ ) ) ;
390410 }
391- panic ! ( "Last entry in trace isn't a forward" )
392411 }
412+ _ => return Err ( "Last entry in history isn't a forward" . to_string ( ) ) ,
393413 }
394414 Ok ( ( ) )
395415 }
0 commit comments