123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- pub mod sim;
- mod stats;
- mod types;
- use std::{env, process};
- use crate::types::{Quorum, Region, NodeCount};
- use crate::stats::{CurrentStats, CumulativeStats};
- use crate::sim::Simulation;
- use rand_pcg::Pcg64;
- use rand::SeedableRng;
- // use log::{info, error, set_logger};
- // use simplelog::*;
- // use std::fs::File;
- fn usage(cmd: &String) {
- eprintln!("Usage: {} h m lg_r k g lg_c T S", cmd);
- eprintln!("h: number of honest nodes");
- eprintln!("m: number of malicious nodes");
- eprintln!("lg_r: log_2 of the number of regions");
- eprintln!("k: k - 1 no. of secondary joins in CCR before new primary joins are accepted, k*g/g' nodes cuckoo-ed out with each primary join");
- eprintln!("g: desired number of nodes in a *region*");
- eprintln!("lg_c: log_2 of the number of regions per quorum");
- eprintln!("T: number of iterations after initialization");
- eprintln!("S: number of seeds");
- }
- fn run_print_errors(sim: &mut Simulation, is_init: bool, h: usize, m: usize, ctr: usize, max: usize) -> bool
- {
- let (prefix, iter, iters, inserted, inserted_below_bmax, rejoined_below_bmax, number_rejoined) = if is_init
- {
- let (init_iter, a, b, c, d) = sim.init(h, m);
- ("FAILED INIT ".to_string(), init_iter, m, a, b, c, d)
- }
- else
- {
- let (a, b, c, d) = sim.move_malicious();
- ("FAILED MOVE MALICIOUS ".to_string(), ctr, max, a, b, c, d)
- };
- if !inserted {
- let reason = "due to failed malicious node cuckoo insert";
- println!("{} iteration {} / {} {}", prefix, iter, iters, reason);
- }
- if !inserted_below_bmax {
- let reason = "as b_max was broken by moving malicious node";
- println!("{} iteration {} / {} {}", prefix, iter, iters, reason);
- }
- if !rejoined_below_bmax {
- let reason = "as b_max was broken by re-joining node".to_string();
- println!("{} iteration {} / {} {} {}", prefix, iter, iters, reason, number_rejoined + 1);
- }
- inserted && inserted_below_bmax && rejoined_below_bmax
- }
- fn run_sim_for_seed(h: NodeCount, m: NodeCount, lg_r: NodeCount, lg_c: NodeCount,
- k: NodeCount, g: NodeCount, iters: usize, seed: usize) ->
- (f64, NodeCount, NodeCount)
- {
- let blankregion = Region {
- num_honest: 0,
- num_malicious: 0,
- last_join: 0,
- num_nodes_since_last_primary_join: 0,
- };
- let blankquorum = Quorum {
- tot_honest: 0,
- tot_malicious: 0,
- tot_last_join: 0,
- };
- let mut sim = Simulation {
- done_init: false,
- now: 0,
- rand: Pcg64::seed_from_u64(seed as u64),
- quorums: Vec::new(),
- regions: Vec::new(),
- lg_regions_per_quorum: lg_c,
- num_region_mask: (1<<lg_r)-1,
- cur_stats: CurrentStats::default(),
- cum_stats: CumulativeStats::default(),
- k,
- g,
- };
- sim.regions.resize(1<<lg_r, blankregion);
- sim.quorums.resize(1<<(lg_r-lg_c), blankquorum);
- eprintln!("Starting simulation n={}, h={}, m={}, 2^r={} regions, CCR: k={}, desired quorum size: g={}, regions/quorum: 2^c={}, T={}, seed={}",
- h+m, h, m, 1 << lg_r, k, g, 1 << lg_c, iters, seed);
- let successful_init = run_print_errors(&mut sim, true, h, m, 0, 0);
- let mut successful_move_malicious = false;
- if successful_init {
- for iter in 0..iters {
- successful_move_malicious = run_print_errors(&mut sim, false, 0, 0, iter, iters);
- if !successful_move_malicious
- {break;}
- }
- }
- println!("Results for seed={} h={} m={} 2^r={} k={} g={} 2^c={} T={}:",
- seed, h, m, 1 << lg_r, k, g, 1<< lg_c, iters);
- sim.cum_stats.print();
- if successful_init && successful_move_malicious
- {
- (sim.cum_stats.max_b_0, sim.cum_stats.min_tot_nodes, sim.cum_stats.max_tot_nodes)
- } else {
- (999.0, 1000000, 0)
- }
- }
- fn main() {
- let args: Vec<String> = env::args().collect();
- if args.len() != 9 {
- usage(&args[0]);
- process::exit(1);
- }
- let valid_args: Vec<usize> = args.iter().enumerate()
- .filter(|(i, _)| *i != 0)
- .map(|(_, v)| v.parse::<usize>())
- .filter(|x| x.is_ok())
- .map(|x| x.unwrap())
- .collect();
- if valid_args.len() != 8 {
- usage(&args[0]);
- process::exit(1);
- }
- let h = valid_args[0];
- let m = valid_args[1];
- let lg_r = valid_args[2];
- let k = valid_args[3];
- let g = valid_args[4];
- let lg_c = valid_args[5];
- let iters = valid_args[6];
- let no_of_seeds = valid_args[7];
- if (lg_c > lg_r) | (k > g) {
- usage(&args[0]);
- process::exit(1);
- }
- let mut b_0_array : Vec<f64> = vec![999.0; no_of_seeds];
- let mut mins_array : Vec<NodeCount> = vec![1000; no_of_seeds];
- let mut maxs_array : Vec<NodeCount> = vec![0; no_of_seeds];
- for seed_ctr in 1..no_of_seeds + 1 {
- let (b0, mins, maxs) = run_sim_for_seed(h, m, lg_r, lg_c, k, g, iters, seed_ctr);
- b_0_array[seed_ctr - 1] = b0;
- mins_array[seed_ctr - 1] = mins;
- maxs_array[seed_ctr - 1] = maxs;
- }
- let max_b_0 = b_0_array.iter().cloned().fold(-1./0. /* -inf */, f64::max);
- let min_mins = mins_array.iter().cloned().fold(1000, NodeCount::min);
- let max_maxs = maxs_array.iter().cloned().fold(0, NodeCount::max);
- println!("FINAL Max_b_0={} min_s={} max_s={}", max_b_0, min_mins, max_maxs);
- }
|