simulation.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Before running this, run:
  2. // 1. rdsys
  3. // 2. lox-distributor
  4. // 3. troll-patrol with the feature "simulation"
  5. use troll_patrol::{
  6. extra_info::ExtraInfo,
  7. get_date, increment_simulated_date, set_simulated_date,
  8. simulation::{
  9. bridge::Bridge,
  10. censor::{self, Censor},
  11. config::Config as SConfig,
  12. extra_infos_server,
  13. user::User,
  14. },
  15. };
  16. use clap::Parser;
  17. use lox_cli::{networking::*, *};
  18. use lox_library::proto::{level_up::LEVEL_INTERVAL, trust_promotion::UNTRUSTED_INTERVAL};
  19. use rand::Rng;
  20. use serde::Deserialize;
  21. use std::{
  22. collections::{HashMap, HashSet},
  23. fs::File,
  24. io::BufReader,
  25. path::PathBuf,
  26. time::Duration,
  27. };
  28. use tokio::{spawn, time::sleep};
  29. #[derive(Parser, Debug)]
  30. #[command(author, version, about, long_about = None)]
  31. struct Args {
  32. /// Name/path of the configuration file
  33. #[arg(short, long, default_value = "simulation_config.json")]
  34. config: PathBuf,
  35. }
  36. #[derive(Debug, Deserialize)]
  37. pub struct Config {
  38. pub la_port: u16,
  39. pub la_test_port: u16,
  40. pub tp_port: u16,
  41. pub tp_test_port: u16,
  42. pub censor_hides: censor::Hides,
  43. pub censor_speed: censor::Speed,
  44. pub censor_event_duration: u32,
  45. pub censor_totality: censor::Totality,
  46. pub censor_partial_blocking_percent: f64,
  47. pub country: String,
  48. pub min_new_users_per_day: u32,
  49. pub max_new_users_per_day: u32,
  50. // How many days to simulate
  51. pub num_days: u32,
  52. // We start with this many level 4 users
  53. pub num_initial_trusted_users: u32,
  54. pub one_positive_report_per_cred: bool,
  55. pub prob_connection_fails: f64,
  56. pub prob_user_invites_friend: f64,
  57. pub prob_user_is_censor: f64,
  58. pub prob_user_submits_reports: f64,
  59. }
  60. #[tokio::main]
  61. pub async fn main() {
  62. let args: Args = Args::parse();
  63. let config: Config = serde_json::from_reader(BufReader::new(
  64. File::open(&args.config).expect("Could not read config file"),
  65. ))
  66. .expect("Reading config file from JSON failed");
  67. let la_net = HyperNet {
  68. hostname: format!("http://localhost:{}", config.la_port),
  69. };
  70. let la_net_test = HyperNet {
  71. hostname: format!("http://localhost:{}", config.la_test_port),
  72. };
  73. let tp_net = HyperNet {
  74. hostname: format!("http://localhost:{}", config.tp_port),
  75. };
  76. let tp_net_test = HyperNet {
  77. hostname: format!("http://localhost:{}", config.tp_test_port),
  78. };
  79. let extra_infos_net = HyperNet {
  80. hostname: "http://localhost:8004".to_string(),
  81. };
  82. let la_pubkeys = get_lox_auth_keys(&la_net).await;
  83. let sconfig = SConfig {
  84. la_pubkeys,
  85. la_net,
  86. tp_net,
  87. censor_hides: config.censor_hides,
  88. censor_speed: config.censor_speed,
  89. censor_event_duration: config.censor_event_duration,
  90. censor_totality: config.censor_totality,
  91. censor_partial_blocking_percent: config.censor_partial_blocking_percent,
  92. country: config.country,
  93. one_positive_report_per_cred: config.one_positive_report_per_cred,
  94. prob_connection_fails: config.prob_connection_fails,
  95. prob_user_invites_friend: config.prob_user_invites_friend,
  96. prob_user_is_censor: config.prob_user_is_censor,
  97. prob_user_submits_reports: config.prob_user_submits_reports,
  98. };
  99. let mut rng = rand::thread_rng();
  100. // Set up censor
  101. let mut censor = Censor::new(&sconfig);
  102. // Set up bridges (no bridges yet)
  103. let mut bridges = HashMap::<[u8; 20], Bridge>::new();
  104. // Set up users
  105. let mut users = Vec::<User>::new();
  106. if config.num_initial_trusted_users > 0 {
  107. // Add some number of trusted users initially
  108. for _ in 0..config.num_initial_trusted_users {
  109. users.push(User::trusted_user(&sconfig).await);
  110. }
  111. // Level trusted users up to level 4
  112. // Advance LA's time
  113. la_net_test
  114. .request(
  115. "/advancedays".to_string(),
  116. serde_json::to_string(&(UNTRUSTED_INTERVAL as u16))
  117. .unwrap()
  118. .into(),
  119. )
  120. .await;
  121. // Advance simulated time
  122. set_simulated_date(get_date() + UNTRUSTED_INTERVAL);
  123. for user in &mut users {
  124. user.primary_cred = trust_migration(
  125. &sconfig.la_net,
  126. &user.primary_cred,
  127. &trust_promotion(
  128. &sconfig.la_net,
  129. &user.primary_cred,
  130. get_lox_pub(&sconfig.la_pubkeys),
  131. )
  132. .await,
  133. get_lox_pub(&sconfig.la_pubkeys),
  134. get_migration_pub(&sconfig.la_pubkeys),
  135. )
  136. .await;
  137. }
  138. for i in 1..LEVEL_INTERVAL.len() - 2 {
  139. // Advance LA's time
  140. la_net_test
  141. .request(
  142. "/advancedays".to_string(),
  143. serde_json::to_string(&(LEVEL_INTERVAL[i] as u16))
  144. .unwrap()
  145. .into(),
  146. )
  147. .await;
  148. // Advance simulated time
  149. set_simulated_date(get_date() + LEVEL_INTERVAL[i]);
  150. for user in &mut users {
  151. let reachcred = get_bucket(&sconfig.la_net, &user.primary_cred).await.1;
  152. user.primary_cred = level_up(
  153. &sconfig.la_net,
  154. &user.primary_cred,
  155. &reachcred.unwrap(),
  156. get_lox_pub(&sconfig.la_pubkeys),
  157. get_reachability_pub(&sconfig.la_pubkeys),
  158. )
  159. .await;
  160. }
  161. }
  162. // Have Troll Patrol run its update process so we have a negative
  163. // report key for tomorrow
  164. tp_net_test.request("/update".to_string(), vec![]).await;
  165. // Advance LA's time to tomorrow
  166. la_net_test
  167. .request(
  168. "/advancedays".to_string(),
  169. serde_json::to_string(&(1 as u16)).unwrap().into(),
  170. )
  171. .await;
  172. // Advance simulated time to tomorrow
  173. increment_simulated_date();
  174. }
  175. // Set up extra-infos server
  176. spawn(async move {
  177. extra_infos_server::server().await;
  178. });
  179. sleep(Duration::from_millis(1)).await;
  180. let mut fp = 0;
  181. let mut tp = 0;
  182. // Main loop
  183. for day in 1..=config.num_days {
  184. println!("Starting day {} of the simulation", day);
  185. // USER TASKS
  186. // Add some new users
  187. let num_new_users: u32 =
  188. rng.gen_range(config.min_new_users_per_day..=config.max_new_users_per_day);
  189. for _ in 0..num_new_users {
  190. users.push(User::new(&sconfig).await);
  191. }
  192. let mut new_users = Vec::<User>::new();
  193. // Users do daily actions
  194. for user in &mut users {
  195. let mut invited_friends = user.daily_tasks(&sconfig, &mut bridges, &mut censor).await;
  196. // If this user invited any friends, add them to the list of users
  197. new_users.append(&mut invited_friends);
  198. }
  199. // Add new users
  200. users.append(&mut new_users);
  201. // CENSOR TASKS
  202. censor.end_of_day_tasks(&sconfig, &mut bridges).await;
  203. // BRIDGE TASKS
  204. let mut new_extra_infos = HashSet::<ExtraInfo>::new();
  205. for (_, bridge) in bridges.iter_mut() {
  206. // Bridge reports its connections for the day
  207. new_extra_infos.insert(bridge.gen_extra_info(&sconfig.country));
  208. // Bridge resets for tomorrow
  209. bridge.reset_for_tomorrow();
  210. }
  211. // Publish all the bridges' extra-infos for today
  212. extra_infos_net
  213. .request(
  214. "/add".to_string(),
  215. serde_json::to_string(&new_extra_infos).unwrap().into(),
  216. )
  217. .await;
  218. // TROLL PATROL TASKS
  219. let new_blockages_resp = tp_net_test.request("/update".to_string(), vec![]).await;
  220. let new_blockages: HashMap<String, HashSet<String>> =
  221. serde_json::from_slice(&new_blockages_resp).unwrap();
  222. // TODO: Track more stats about new blockages
  223. for (bridge, ccs) in new_blockages {
  224. let fingerprint = array_bytes::hex2array(bridge).unwrap();
  225. for cc in ccs {
  226. if cc == sconfig.country {
  227. if censor.knows_bridge(&fingerprint) {
  228. tp += 1;
  229. } else {
  230. fp += 1;
  231. }
  232. }
  233. }
  234. }
  235. // LOX AUTHORITY TASKS
  236. // Advance LA's time to tomorrow
  237. la_net_test
  238. .request(
  239. "/advancedays".to_string(),
  240. serde_json::to_string(&(1 as u16)).unwrap().into(),
  241. )
  242. .await;
  243. // SIMULATION TASKS
  244. // Advance simulated time to tomorrow
  245. increment_simulated_date();
  246. }
  247. println!("True Positives: {}", tp);
  248. println!("False Positives: {}", fp);
  249. }