Pārlūkot izejas kodu

Fix a bunch of issues with the simulation

Vecna 10 mēneši atpakaļ
vecāks
revīzija
c4828d691f
6 mainītis faili ar 130 papildinājumiem un 96 dzēšanām
  1. 40 8
      src/bin/simulation.rs
  2. 16 12
      src/lib.rs
  3. 3 0
      src/main.rs
  4. 8 18
      src/simulation/bridge.rs
  5. 3 1
      src/simulation/extra_infos_server.rs
  6. 60 57
      src/simulation/user.rs

+ 40 - 8
src/bin/simulation.rs

@@ -5,8 +5,14 @@
 
 use troll_patrol::{
     extra_info::ExtraInfo,
-    increment_simulated_date,
-    simulation::{bridge::Bridge, censor::Censor, extra_infos_server, state::State, user::User},
+    get_date, increment_simulated_date,
+    simulation::{
+        bridge::Bridge,
+        censor::{Censor, Hides::*, Speed::*, Totality::*},
+        extra_infos_server,
+        state::State,
+        user::User,
+    },
 };
 
 use clap::Parser;
@@ -18,8 +24,9 @@ use std::{
     fs::File,
     io::BufReader,
     path::PathBuf,
+    time::Duration,
 };
-use tokio::spawn;
+use tokio::{spawn, time::sleep};
 
 #[derive(Parser, Debug)]
 #[command(author, version, about, long_about = None)]
@@ -70,7 +77,7 @@ pub async fn main() {
         hostname: format!("http://localhost:{}", config.tp_test_port),
     };
     let extra_infos_net = HyperNet {
-        hostname: "http://localhost:8003".to_string(),
+        hostname: "http://localhost:8004".to_string(),
     };
 
     let la_pubkeys = get_lox_auth_keys(&la_net).await;
@@ -84,7 +91,7 @@ pub async fn main() {
         prob_user_invites_friend: config.prob_user_invites_friend,
         prob_user_is_censor: config.prob_user_is_censor,
         prob_user_submits_reports: config.prob_user_submits_reports,
-        probs_user_in_country: config.probs_user_in_country,
+        probs_user_in_country: config.probs_user_in_country.clone(),
         sharing: config.sharing,
     };
 
@@ -92,6 +99,10 @@ pub async fn main() {
 
     // Set up censors
     let mut censors = HashMap::<String, Censor>::new();
+    for i in 0..config.probs_user_in_country.len() {
+        let cc = config.probs_user_in_country[i].0.clone();
+        censors.insert(cc.clone(), Censor::new(cc, Fast, Overt, Full));
+    }
 
     // Set up bridges (no bridges yet)
     let mut bridges = HashMap::<[u8; 20], Bridge>::new();
@@ -103,9 +114,17 @@ pub async fn main() {
     spawn(async move {
         extra_infos_server::server().await;
     });
+    sleep(Duration::from_millis(1)).await;
+
+    let mut fp = 0;
+    let mut tp = 0;
 
     // Main loop
     for _ in 0..config.num_days {
+        let la_net = HyperNet {
+            hostname: format!("http://localhost:{}", config.la_port),
+        };
+
         // USER TASKS
 
         // Add some new users
@@ -120,8 +139,7 @@ pub async fn main() {
         // Users do daily actions
         for user in &mut users {
             // TODO: Refactor out connections from return
-            let (mut invited_friends, _connections) =
-                user.daily_tasks(&state, &mut bridges, &mut censors).await;
+            let mut invited_friends = user.daily_tasks(&state, &mut bridges, &mut censors).await;
 
             // If this user invited any friends, add them to the list of users
             new_users.append(&mut invited_friends);
@@ -158,7 +176,18 @@ pub async fn main() {
         let new_blockages: HashMap<String, HashSet<String>> =
             serde_json::from_slice(&new_blockages_resp).unwrap();
 
-        // TODO: Track stats about new blockages
+        // TODO: Track more stats about new blockages
+        for (bridge, ccs) in new_blockages {
+            let fingerprint = array_bytes::hex2array(bridge).unwrap();
+            for cc in ccs {
+                let censor = censors.get(&cc).unwrap();
+                if censor.knows_bridge(&fingerprint) {
+                    tp += 1;
+                } else {
+                    fp += 1;
+                }
+            }
+        }
 
         // LOX AUTHORITY TASKS
 
@@ -175,4 +204,7 @@ pub async fn main() {
         // Advance simulated time to tomorrow
         increment_simulated_date();
     }
+
+    println!("True Positives: {}", tp);
+    println!("False Positives: {}", fp);
 }

+ 16 - 12
src/lib.rs

@@ -871,20 +871,24 @@ pub async fn report_blockages(
     let mut blockages_str = HashMap::<String, HashSet<String>>::new();
     for (fingerprint, countries) in blockages {
         let fpr_string = array_bytes::bytes2hex("", fingerprint);
-        blockages_str.insert(fpr_string, countries);
+        if countries.len() > 0 {
+            blockages_str.insert(fpr_string, countries);
+        }
     }
 
-    // Report blocked bridges to bridge distributor
-    let client = Client::new();
-    let req = Request::builder()
-        .method(Method::POST)
-        .uri(uri)
-        .body(Body::from(serde_json::to_string(&blockages_str).unwrap()))
-        .unwrap();
-    let resp = client.request(req).await.unwrap();
-    let buf = hyper::body::to_bytes(resp).await.unwrap();
-    let resp_str: String = serde_json::from_slice(&buf).unwrap();
-    assert_eq!("OK", resp_str);
+    if blockages_str.len() > 0 {
+        // Report blocked bridges to bridge distributor
+        let client = Client::new();
+        let req = Request::builder()
+            .method(Method::POST)
+            .uri(uri)
+            .body(Body::from(serde_json::to_string(&blockages_str).unwrap()))
+            .unwrap();
+        let resp = client.request(req).await.unwrap();
+        let buf = hyper::body::to_bytes(resp).await.unwrap();
+        let resp_str: String = serde_json::from_slice(&buf).unwrap();
+        assert_eq!("OK", resp_str);
+    }
 }
 
 // Unit tests

+ 3 - 0
src/main.rs

@@ -155,6 +155,9 @@ async fn context_manager(
 ) {
     let db: Db = sled::open(&db_config.db_path).unwrap();
 
+    // Create negative report key for today if we don't have one
+    new_negative_report_key(&db, get_date());
+
     while let Some(cmd) = context_rx.recv().await {
         use Command::*;
         match cmd {

+ 8 - 18
src/simulation/bridge.rs

@@ -19,19 +19,15 @@ impl Bridge {
     }
 
     pub fn from_bridge_line(bridgeline: &BridgeLine) -> Self {
-        Self::new(&bridgeline.fingerprint)
+        Self::new(&bridgeline.get_hashed_fingerprint())
     }
 
     pub fn connect_real(&mut self, country: &str) {
         if self.real_connections.contains_key(country) {
             let prev = self.real_connections.get(country).unwrap();
-            self.real_connections
-                .insert(country.to_string(), prev + 1)
-                .unwrap();
+            self.real_connections.insert(country.to_string(), prev + 1);
         } else {
-            self.real_connections
-                .insert(country.to_string(), 1)
-                .unwrap();
+            self.real_connections.insert(country.to_string(), 1);
         }
         self.connect_total(country);
     }
@@ -39,13 +35,9 @@ impl Bridge {
     pub fn connect_total(&mut self, country: &str) {
         if self.total_connections.contains_key(country) {
             let prev = self.total_connections.get(country).unwrap();
-            self.total_connections
-                .insert(country.to_string(), prev + 1)
-                .unwrap();
+            self.total_connections.insert(country.to_string(), prev + 1);
         } else {
-            self.total_connections
-                .insert(country.to_string(), 1)
-                .unwrap();
+            self.total_connections.insert(country.to_string(), 1);
         }
     }
 
@@ -54,19 +46,17 @@ impl Bridge {
         if self.total_connections.contains_key(country) {
             let prev = self.total_connections.get(country).unwrap();
             self.total_connections
-                .insert(country.to_string(), prev + num_connections)
-                .unwrap();
+                .insert(country.to_string(), prev + num_connections);
         } else {
             self.total_connections
-                .insert(country.to_string(), num_connections)
-                .unwrap();
+                .insert(country.to_string(), num_connections);
         }
     }
 
     // Generate an extra-info report for today
     pub fn gen_extra_info(&self) -> ExtraInfo {
         ExtraInfo {
-            nickname: String::default(),
+            nickname: String::from("simulation-bridge"),
             fingerprint: self.fingerprint,
             date: get_date(),
             bridge_ips: self.total_connections.clone(),

+ 3 - 1
src/simulation/extra_infos_server.rs

@@ -130,7 +130,9 @@ fn add_extra_infos(extra_infos_pages: &mut Vec<String>, request: Bytes) -> Respo
     for extra_info in extra_infos {
         extra_infos_file.push_str(extra_info.to_string().as_str());
     }
-    extra_infos_pages.push(extra_infos_file);
+    if extra_infos_file.len() > 0 {
+        extra_infos_pages.push(extra_infos_file);
+    }
     prepare_header("OK".to_string())
 }
 

+ 60 - 57
src/simulation/user.rs

@@ -9,7 +9,7 @@ use crate::{
         censor::{Censor, Hides::*, Speed::*, Totality::*},
         state::State,
     },
-    BridgeDistributor,
+    BridgeDistributor, COUNTRY_CODES,
 };
 use lox_cli::{networking::*, *};
 use lox_library::{
@@ -69,7 +69,7 @@ impl User {
             let mut cc = String::default();
             for (country, prob) in &state.probs_user_in_country {
                 let prob = *prob;
-                if prob < num {
+                if num < prob {
                     cc = country.to_string();
                     break;
                 } else {
@@ -78,6 +78,7 @@ impl User {
             }
             cc
         };
+        assert!(COUNTRY_CODES.contains(cc.as_str()));
 
         // Randomly determine how likely this user is to use bridges on
         // a given day
@@ -135,7 +136,7 @@ impl User {
             let mut cc = String::default();
             for (country, prob) in &state.probs_user_in_country {
                 let prob = *prob;
-                if prob < num {
+                if num < prob {
                     cc = country.to_string();
                     break;
                 } else {
@@ -237,7 +238,7 @@ impl User {
         state: &State,
         bridges: &mut HashMap<[u8; 20], Bridge>,
         censors: &mut HashMap<String, Censor>,
-    ) -> (Vec<User>, Vec<[u8; 20]>) {
+    ) -> Vec<User> {
         // Probabilistically decide if the user should use bridges today
         if event_happens(self.prob_use_bridges) {
             // Download bucket to see if bridge is still reachable. (We
@@ -248,23 +249,25 @@ impl User {
 
             // Make sure each bridge in bucket is in the global bridges set
             for bridgeline in bucket {
-                if !bridges.contains_key(&bridgeline.fingerprint) {
-                    let bridge = Bridge::from_bridge_line(&bridgeline);
-                    bridges.insert(bridgeline.fingerprint, bridge).unwrap();
-                }
-                // Also, if this user cooperates with censors, make sure
-                // each applicable censor knows about their bridges.
-                if self.censor {
-                    if state.sharing {
-                        for c in censors.values_mut() {
-                            if !c.knows_bridge(&bridgeline.fingerprint) {
-                                c.learn_bridge(&bridgeline.fingerprint);
+                if bridgeline != BridgeLine::default() {
+                    if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
+                        let bridge = Bridge::from_bridge_line(&bridgeline);
+                        bridges.insert(bridgeline.get_hashed_fingerprint(), bridge);
+                    }
+                    // Also, if this user cooperates with censors, make sure
+                    // each applicable censor knows about their bridges.
+                    if self.censor {
+                        if state.sharing {
+                            for c in censors.values_mut() {
+                                if !c.knows_bridge(&bridgeline.get_hashed_fingerprint()) {
+                                    c.learn_bridge(&bridgeline.get_hashed_fingerprint());
+                                }
+                            }
+                        } else {
+                            let censor = censors.get_mut(&self.country).unwrap();
+                            if !censor.knows_bridge(&bridgeline.get_hashed_fingerprint()) {
+                                censor.learn_bridge(&bridgeline.get_hashed_fingerprint());
                             }
-                        }
-                    } else {
-                        let censor = censors.get_mut(&self.country).unwrap();
-                        if !censor.knows_bridge(&bridgeline.fingerprint) {
-                            censor.learn_bridge(&bridgeline.fingerprint);
                         }
                     }
                 }
@@ -282,14 +285,17 @@ impl User {
             // Can we level up the secondary credential?
             let mut second_level_up = false;
 
+            // Attempt to connect to each bridge
             let mut failed = Vec::<BridgeLine>::new();
             let mut succeeded = Vec::<BridgeLine>::new();
             for i in 0..bucket.len() {
                 // At level 0, we only have 1 bridge
-                if level > 0 || i == 0 {
+                if bucket[i] != BridgeLine::default() {
                     if self.connect(
                         &state,
-                        bridges.get_mut(&bucket[i].fingerprint).unwrap(),
+                        bridges
+                            .get_mut(&bucket[i].get_hashed_fingerprint())
+                            .unwrap(),
                         &censors.get(&self.country).unwrap(),
                     ) {
                         succeeded.push(bucket[i]);
@@ -321,45 +327,49 @@ impl User {
                 let second_cred = second_cred.as_ref().unwrap();
                 let (second_bucket, second_reachcred) =
                     get_bucket(&state.la_net, &second_cred).await;
-                if !bridges.contains_key(&second_bucket[0].fingerprint) {
-                    bridges
-                        .insert(
-                            second_bucket[0].fingerprint,
-                            Bridge::from_bridge_line(&second_bucket[0]),
-                        )
-                        .unwrap();
-                }
-                if self.connect(
-                    &state,
-                    bridges.get_mut(&second_bucket[0].fingerprint).unwrap(),
-                    &censors.get(&self.country).unwrap(),
-                ) {
-                    succeeded.push(second_bucket[0]);
-                    if second_reachcred.is_some()
-                        && eligible_for_trust_promotion(&state.la_net, &second_cred).await
-                    {
-                        second_level_up = true;
+                for bridgeline in second_bucket {
+                    if bridgeline != BridgeLine::default() {
+                        if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
+                            bridges.insert(
+                                bridgeline.get_hashed_fingerprint(),
+                                Bridge::from_bridge_line(&bridgeline),
+                            );
+                        }
+                        if self.connect(
+                            &state,
+                            bridges
+                                .get_mut(&bridgeline.get_hashed_fingerprint())
+                                .unwrap(),
+                            &censors.get(&self.country).unwrap(),
+                        ) {
+                            succeeded.push(bridgeline);
+                            if second_reachcred.is_some()
+                                && eligible_for_trust_promotion(&state.la_net, &second_cred).await
+                            {
+                                second_level_up = true;
+                            }
+                        } else {
+                            failed.push(bridgeline);
+                        }
                     }
-                } else {
-                    failed.push(second_bucket[0]);
                 }
             }
 
             let mut negative_reports = Vec::<NegativeReport>::new();
             let mut positive_reports = Vec::<PositiveReport>::new();
             if self.submits_reports {
-                for bridge in &failed {
+                for bridgeline in &failed {
                     negative_reports.push(NegativeReport::from_bridgeline(
-                        *bridge,
+                        *bridgeline,
                         self.country.to_string(),
                         BridgeDistributor::Lox,
                     ));
                 }
                 if level >= 3 {
-                    for bridge in &succeeded {
+                    for bridgeline in &succeeded {
                         positive_reports.push(
                             PositiveReport::from_lox_credential(
-                                bridge.fingerprint,
+                                bridgeline.get_hashed_fingerprint(),
                                 None,
                                 &self.primary_cred,
                                 get_lox_pub(&state.la_pubkeys),
@@ -392,8 +402,8 @@ impl User {
                     let censor = censors.get_mut(&self.country).unwrap();
                     let (bucket, reachcred) = get_bucket(&state.la_net, &self.primary_cred).await;
                     for bl in bucket {
-                        censor.learn_bridge(&bl.fingerprint);
-                        censor.give_lox_cred(&bl.fingerprint, &self.primary_cred);
+                        censor.learn_bridge(&bl.get_hashed_fingerprint());
+                        censor.give_lox_cred(&bl.get_hashed_fingerprint(), &self.primary_cred);
                     }
                 }
             }
@@ -461,16 +471,9 @@ impl User {
                 }
             }
 
-            // List of fingerprints we contacted. This should not
-            // actually be more than one.
-            let mut connections = Vec::<[u8; 20]>::new();
-            for bridge in succeeded {
-                connections.push(bridge.get_hashed_fingerprint());
-            }
-
-            (new_friends, connections)
+            new_friends
         } else {
-            (Vec::<User>::new(), Vec::<[u8; 20]>::new())
+            Vec::<User>::new()
         }
     }
 }