Kaynağa Gözat

Censor user gives bridges and creds to censor

Vecna 9 ay önce
ebeveyn
işleme
690019f4c5
3 değiştirilmiş dosya ile 58 ekleme ve 31 silme
  1. 1 0
      src/lib.rs
  2. 11 10
      src/simulation/censor.rs
  3. 46 21
      src/simulation/user.rs

+ 1 - 0
src/lib.rs

@@ -65,6 +65,7 @@ pub fn get_date() -> u32 {
     return get_simulated_date();
 
     // If we're not running a simulation, return today's date
+    #[allow(unreachable_code)]
     get_real_date()
 }
 

+ 11 - 10
src/simulation/censor.rs

@@ -1,4 +1,4 @@
-use crate::{get_date, simulation::bridge::Bridge};
+use crate::get_date;
 
 use lox_library::{cred::Lox, scalar_u32};
 use rand::Rng;
@@ -53,26 +53,27 @@ impl Censor {
         }
     }
 
-    pub fn knows_bridge(&self, bridge: &Bridge) -> bool {
-        self.known_bridges.contains(&bridge.fingerprint)
+    pub fn knows_bridge(&self, fingerprint: &[u8; 20]) -> bool {
+        self.known_bridges.contains(fingerprint)
     }
 
     pub fn learn_bridge(&mut self, fingerprint: &[u8; 20]) {
         self.known_bridges.insert(*fingerprint);
     }
 
-    pub fn has_lox_cred(&self, bridge: &Bridge) -> bool {
-        self.lox_credentials.contains_key(&bridge.fingerprint)
+    pub fn has_lox_cred(&self, fingerprint: &[u8; 20]) -> bool {
+        self.lox_credentials.contains_key(fingerprint)
     }
 
-    pub fn give_lox_cred(&mut self, bridge: &Bridge, cred: Lox) {
+    pub fn give_lox_cred(&mut self, fingerprint: &[u8; 20], cred: &Lox) {
         // We only need one level 3+ credential per bridge. (This will
         // change if we restrict positive reports to one per bridge per
         // credential.)
-        if !self.lox_credentials.contains_key(&bridge.fingerprint)
-            && scalar_u32(&cred.trust_level).unwrap() >= 3
-        {
-            self.lox_credentials.insert(bridge.fingerprint, cred);
+        if !self.has_lox_cred(fingerprint) && scalar_u32(&cred.trust_level).unwrap() >= 3 {
+            // We want to clone the credential, but that's not allowed,
+            // so we're going to serialize it and then deserialize it.
+            let cloned_cred = bincode::deserialize(&bincode::serialize(&cred).unwrap()).unwrap();
+            self.lox_credentials.insert(*fingerprint, cloned_cred);
         }
     }
 }

+ 46 - 21
src/simulation/user.rs

@@ -162,10 +162,10 @@ impl User {
 
     // Attempt to "connect" to the bridge, returns true if successful
     pub fn connect(&self, state: &State, bridge: &mut Bridge, censor: &Censor) -> bool {
-        if censor.knows_bridge(bridge) {
+        if censor.knows_bridge(&bridge.fingerprint) {
             if censor.speed == Fast
                 || censor.speed == Random && censor.delay_date <= get_date()
-                || censor.speed == Lox && censor.has_lox_cred(bridge)
+                || censor.speed == Lox && censor.has_lox_cred(&bridge.fingerprint)
             {
                 if censor.totality == Full
                     || censor.totality == Partial && event_happens(censor.partial_blocking_percent)
@@ -196,7 +196,6 @@ impl User {
 
     pub async fn send_negative_reports(state: &State, reports: Vec<NegativeReport>) {
         let date = get_date();
-        //let pubkey = state.tp_pubkeys.get(&date).unwrap();
         let pubkey = serde_json::from_slice::<Option<PublicKey>>(
             &state
                 .net_tp
@@ -239,22 +238,35 @@ impl User {
         bridges: &mut HashMap<[u8; 20], Bridge>,
         censors: &mut HashMap<String, Censor>,
     ) -> (Vec<User>, Vec<[u8; 20]>) {
-        let censor = censors.get(&self.country).unwrap();
-
         // 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 assume that this step can be done even if the user can't actually
-            // talk to the LA.)
+            // Download bucket to see if bridge is still reachable. (We
+            // assume that this step can be done even if the user can't
+            // actually talk to the LA.)
             let (bucket, reachcred) = get_bucket(&state.net, &self.primary_cred).await;
             let level = scalar_u32(&self.primary_cred.trust_level).unwrap();
 
             // Make sure each bridge in bucket is in the global bridges set
-            for bridge in bucket {
-                if !bridges.contains_key(&bridge.fingerprint) {
-                    bridges
-                        .insert(bridge.fingerprint, Bridge::from_bridge_line(&bridge))
-                        .unwrap();
+            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);
+                            }
+                        }
+                    } else {
+                        let censor = censors.get_mut(&self.country).unwrap();
+                        if !censor.knows_bridge(&bridgeline.fingerprint) {
+                            censor.learn_bridge(&bridgeline.fingerprint);
+                        }
+                    }
                 }
             }
 
@@ -278,7 +290,7 @@ impl User {
                     if self.connect(
                         &state,
                         bridges.get_mut(&bucket[i].fingerprint).unwrap(),
-                        &censor,
+                        &censors.get(&self.country).unwrap(),
                     ) {
                         succeeded.push(bucket[i]);
                     } else {
@@ -319,7 +331,7 @@ impl User {
                 if self.connect(
                     &state,
                     bridges.get_mut(&second_bucket[0].fingerprint).unwrap(),
-                    &censor,
+                    &censors.get(&self.country).unwrap(),
                 ) {
                     succeeded.push(second_bucket[0]);
                     if second_reachcred.is_some()
@@ -358,8 +370,9 @@ impl User {
                 }
             }
 
-            // We might restrict these steps to succeeded.len() > 0, but we do
-            // assume the user can contact the LA somehow, so let's just allow it.
+            // We might restrict these steps to succeeded.len() > 0, but
+            // we do assume the user can contact the LA somehow, so
+            // let's just allow it.
             if can_level_up {
                 let cred = level_up(
                     &state.net,
@@ -371,6 +384,17 @@ impl User {
                 .await;
                 self.primary_cred = cred;
                 self.secondary_cred = None;
+
+                if self.censor {
+                    // Make sure censor has access to each bridge and
+                    // each credential
+                    let censor = censors.get_mut(&self.country).unwrap();
+                    let (bucket, reachcred) = get_bucket(&state.net, &self.primary_cred).await;
+                    for bl in bucket {
+                        censor.learn_bridge(&bl.fingerprint);
+                        censor.give_lox_cred(&bl.fingerprint, &self.primary_cred);
+                    }
+                }
             }
             // We favor starting over at level 1 to migrating
             else if second_level_up {
@@ -424,8 +448,9 @@ impl User {
                 if event_happens(state.prob_user_invites_friend) {
                     match self.invite(&state).await {
                         Ok(friend) => {
-                            // You really shouldn't push your friends, especially
-                            // new ones whose boundaries you might not know well.
+                            // You really shouldn't push your friends,
+                            // especially new ones whose boundaries you
+                            // might not know well.
                             new_friends.push(friend);
                         }
                         Err(e) => {
@@ -435,8 +460,8 @@ impl User {
                 }
             }
 
-            // List of fingerprints we contacted. This should not actually be more
-            // than one.
+            // 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());