From 690019f4c54c80e45365e8e362cf0f251ea55b2f Mon Sep 17 00:00:00 2001 From: Vecna Date: Fri, 24 May 2024 18:16:30 -0400 Subject: [PATCH] Censor user gives bridges and creds to censor --- src/lib.rs | 1 + src/simulation/censor.rs | 21 +++++++------ src/simulation/user.rs | 67 +++++++++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7294170..64e7272 100644 --- a/src/lib.rs +++ b/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() } diff --git a/src/simulation/censor.rs b/src/simulation/censor.rs index 4d96245..d0f15b9 100644 --- a/src/simulation/censor.rs +++ b/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); } } } diff --git a/src/simulation/user.rs b/src/simulation/user.rs index e255c59..dca4a23 100644 --- a/src/simulation/user.rs +++ b/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) { let date = get_date(); - //let pubkey = state.tp_pubkeys.get(&date).unwrap(); let pubkey = serde_json::from_slice::>( &state .net_tp @@ -239,22 +238,35 @@ impl User { bridges: &mut HashMap<[u8; 20], Bridge>, censors: &mut HashMap, ) -> (Vec, 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());