diff --git a/src/bin/simulation.rs b/src/bin/simulation.rs index 9e9d2db..1f33c12 100644 --- a/src/bin/simulation.rs +++ b/src/bin/simulation.rs @@ -44,7 +44,7 @@ pub struct Config { pub la_test_port: u16, pub tp_port: u16, pub tp_test_port: u16, - pub censor_hides: censor::Hides, + pub censor_secrecy: censor::Secrecy, pub censor_speed: censor::Speed, pub censor_event_duration: u32, pub censor_totality: censor::Totality, @@ -96,7 +96,7 @@ pub async fn main() { la_pubkeys, la_net, tp_net, - censor_hides: config.censor_hides, + censor_secrecy: config.censor_secrecy, censor_speed: config.censor_speed, censor_event_duration: config.censor_event_duration, censor_totality: config.censor_totality, diff --git a/src/simulation/bridge.rs b/src/simulation/bridge.rs index e7237ce..8b01cf3 100644 --- a/src/simulation/bridge.rs +++ b/src/simulation/bridge.rs @@ -26,8 +26,8 @@ pub struct Bridge { // bridge (for identifying stage three) pub first_positive_report: u32, - real_connections: u32, - total_connections: u32, + pub real_connections: u32, + pub total_connections: u32, } impl Bridge { diff --git a/src/simulation/censor.rs b/src/simulation/censor.rs index 5c5db59..ba8f4e8 100644 --- a/src/simulation/censor.rs +++ b/src/simulation/censor.rs @@ -8,7 +8,10 @@ use lox_cli::{get_lox_pub, networking::Networking}; use lox_library::{cred::Lox, scalar_u32}; use rand::Rng; use serde::Deserialize; -use std::collections::{HashMap, HashSet}; +use std::{ + cmp::min, + collections::{HashMap, HashSet}, +}; pub struct Censor { pub known_bridges: HashSet<[u8; 20]>, @@ -127,7 +130,7 @@ impl Censor { // Make a bunch of connections and submit positive reports if possible async fn flood(&self, config: &Config, bridges: &mut HashMap<[u8; 20], Bridge>) { // Only do this if Flooding censor - if config.censor_hides == Hides::Flooding { + if config.censor_secrecy == Secrecy::Flooding { for fingerprint in &self.known_bridges { // Only do this if we're blocking the bridge if config.censor_speed == Speed::Fast @@ -161,6 +164,38 @@ impl Censor { } } + // Send one positive report per connection we blocked + async fn send_positive_reports( + &self, + config: &Config, + bridges: &mut HashMap<[u8; 20], Bridge>, + ) { + // Only do this if Hiding censor. Flooding censors should use + // flood() instead. + if config.censor_secrecy == Secrecy::Hiding { + for fingerprint in &self.known_bridges { + // Only do this if we're blocking the bridge + if self.blocks_bridge(config, fingerprint) && self.has_lox_cred(fingerprint) { + let bridge = bridges.get_mut(fingerprint).unwrap(); + + // We may be restricted to one positive report per + // credential + let num_reports_to_send = if config.one_positive_report_per_cred { + min( + bridge.total_connections - bridge.real_connections, + self.lox_credentials.get(fingerprint).unwrap().1, + ) + } else { + bridge.total_connections - bridge.real_connections + }; + for _ in 0..num_reports_to_send { + self.send_positive_report(config, fingerprint).await; + } + } + } + } + } + fn recompute_delay(&mut self, config: &Config) { // Only do this if Random censor if config.censor_speed == Speed::Random @@ -180,10 +215,14 @@ impl Censor { config: &Config, bridges: &mut HashMap<[u8; 20], Bridge>, ) { - if config.censor_hides == Hides::Flooding + if config.censor_secrecy == Secrecy::Flooding && !(config.censor_speed == Speed::Random && self.delay_date <= get_date()) { self.flood(config, bridges).await; + } else if config.censor_secrecy == Secrecy::Hiding + && !(config.censor_speed == Speed::Random && self.delay_date <= get_date()) + { + self.send_positive_reports(config, bridges).await; } self.recompute_delay(config); @@ -198,7 +237,7 @@ pub enum Speed { } #[derive(Clone, Copy, Debug, Deserialize, PartialEq)] -pub enum Hides { +pub enum Secrecy { Overt, Hiding, Flooding, diff --git a/src/simulation/config.rs b/src/simulation/config.rs index d7a3b23..a9b2ad0 100644 --- a/src/simulation/config.rs +++ b/src/simulation/config.rs @@ -8,7 +8,7 @@ pub struct Config { pub la_net: HyperNet, pub tp_net: HyperNet, // Define censor behavior - pub censor_hides: censor::Hides, + pub censor_secrecy: censor::Secrecy, pub censor_speed: censor::Speed, pub censor_event_duration: u32, pub censor_totality: censor::Totality, diff --git a/src/simulation/user.rs b/src/simulation/user.rs index 35516c9..b2ac36a 100644 --- a/src/simulation/user.rs +++ b/src/simulation/user.rs @@ -6,7 +6,7 @@ use crate::{ positive_report::PositiveReport, simulation::{ bridge::Bridge, - censor::{Censor, Hides::*, Totality::*}, + censor::{Censor, Secrecy::*, Totality::*}, config::Config, }, BridgeDistributor, @@ -157,7 +157,7 @@ impl User { // Note that this does not involve making a real connection to a // real bridge. The function is async because the *censor* might // submit a positive report during this function. - pub async fn connect(&self, config: &Config, bridge: &mut Bridge, censor: &Censor) -> bool { + pub fn connect(&self, config: &Config, bridge: &mut Bridge, censor: &Censor) -> bool { if censor.blocks_bridge(config, &bridge.fingerprint) { if config.censor_totality == Full || config.censor_totality == Partial @@ -165,7 +165,7 @@ impl User { { // If censor tries to hide its censorship, record a // false connection - if config.censor_hides == Hiding { + if config.censor_secrecy == Hiding { bridge.connect_total(); } @@ -179,15 +179,6 @@ impl User { if event_happens(config.prob_user_treats_throttling_as_blocking) { bridge.connect_total(); - // A Hiding censor does not make an additional - // connection here, but it will make a false - // positive report if possible. - if config.censor_hides == Hiding && censor.has_lox_cred(&bridge.fingerprint) { - censor - .send_positive_report(config, &bridge.fingerprint) - .await; - } - // Return false because there was interference // detected in the connection return false; @@ -328,16 +319,13 @@ impl User { for i in 0..bucket.len() { // At level 0, we only have 1 bridge if bucket[i] != BridgeLine::default() { - if self - .connect( - &config, - bridges - .get_mut(&bucket[i].get_hashed_fingerprint()) - .unwrap(), - &censor, - ) - .await - { + if self.connect( + &config, + bridges + .get_mut(&bucket[i].get_hashed_fingerprint()) + .unwrap(), + &censor, + ) { succeeded.push(bucket[i]); } else { failed.push(bucket[i]); @@ -378,16 +366,13 @@ impl User { ); } // Attempt to connect to second cred's bridge - if self - .connect( - &config, - bridges - .get_mut(&bridgeline.get_hashed_fingerprint()) - .unwrap(), - censor, - ) - .await - { + if self.connect( + &config, + bridges + .get_mut(&bridgeline.get_hashed_fingerprint()) + .unwrap(), + censor, + ) { succeeded.push(bridgeline); if second_reachcred.is_some() && eligible_for_trust_promotion(&config.la_net, &second_cred).await