Compare commits

..

No commits in common. "498d6b4cee1a43588308aca97c2cf49a16df7394" and "9495c8cbdadbc6a21f719ee5ba8531b92b0d1e6f" have entirely different histories.

6 changed files with 68 additions and 119 deletions

View File

@ -7,7 +7,6 @@ edition = "2021"
[dependencies]
aes-gcm = "0.10"
anyhow = "1.0"
array-bytes = "6.2.0"
bincode = "1"
chrono = "0.4"

View File

@ -44,7 +44,7 @@ pub struct Config {
pub la_test_port: u16,
pub tp_port: u16,
pub tp_test_port: u16,
pub censor_secrecy: censor::Secrecy,
pub censor_hides: censor::Hides,
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_secrecy: config.censor_secrecy,
censor_hides: config.censor_hides,
censor_speed: config.censor_speed,
censor_event_duration: config.censor_event_duration,
censor_totality: config.censor_totality,
@ -141,8 +141,7 @@ pub async fn main() {
.unwrap()
.into(),
)
.await
.unwrap();
.await;
// Advance simulated time
set_simulated_date(get_date() + UNTRUSTED_INTERVAL);
@ -177,8 +176,7 @@ pub async fn main() {
.unwrap()
.into(),
)
.await
.unwrap();
.await;
// Advance simulated time
set_simulated_date(get_date() + LEVEL_INTERVAL[i]);
@ -209,8 +207,7 @@ pub async fn main() {
"/advancedays".to_string(),
serde_json::to_string(&(1 as u16)).unwrap().into(),
)
.await
.unwrap();
.await;
// Advance simulated time to tomorrow
increment_simulated_date();
@ -369,14 +366,10 @@ pub async fn main() {
"/add".to_string(),
serde_json::to_string(&new_extra_infos).unwrap().into(),
)
.await
.unwrap();
.await;
// TROLL PATROL TASKS
let new_blockages_resp = tp_net_test
.request("/update".to_string(), vec![])
.await
.unwrap();
let new_blockages_resp = tp_net_test.request("/update".to_string(), vec![]).await;
let new_blockages: HashMap<String, HashSet<String>> =
serde_json::from_slice(&new_blockages_resp).unwrap();
@ -422,8 +415,7 @@ pub async fn main() {
"/advancedays".to_string(),
serde_json::to_string(&(1 as u16)).unwrap().into(),
)
.await
.unwrap();
.await;
// SIMULATION TASKS

View File

@ -26,8 +26,8 @@ pub struct Bridge {
// bridge (for identifying stage three)
pub first_positive_report: u32,
pub real_connections: u32,
pub total_connections: u32,
real_connections: u32,
total_connections: u32,
}
impl Bridge {

View File

@ -8,10 +8,7 @@ use lox_cli::{get_lox_pub, networking::Networking};
use lox_library::{cred::Lox, scalar_u32};
use rand::Rng;
use serde::Deserialize;
use std::{
cmp::min,
collections::{HashMap, HashSet},
};
use std::collections::{HashMap, HashSet};
pub struct Censor {
pub known_bridges: HashSet<[u8; 20]>,
@ -115,22 +112,17 @@ impl Censor {
config.country.clone(),
)
.unwrap();
if config
config
.tp_net
.request("/positivereport".to_string(), pr.to_json().into_bytes())
.await
.is_err()
{
// failed to send positive report
return false;
}
.await;
true
}
// 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_secrecy == Secrecy::Flooding {
if config.censor_hides == Hides::Flooding {
for fingerprint in &self.known_bridges {
// Only do this if we're blocking the bridge
if config.censor_speed == Speed::Fast
@ -164,38 +156,6 @@ 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
@ -215,14 +175,10 @@ impl Censor {
config: &Config,
bridges: &mut HashMap<[u8; 20], Bridge>,
) {
if config.censor_secrecy == Secrecy::Flooding
if config.censor_hides == Hides::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);
@ -237,7 +193,7 @@ pub enum Speed {
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
pub enum Secrecy {
pub enum Hides {
Overt,
Hiding,
Flooding,

View File

@ -8,7 +8,7 @@ pub struct Config {
pub la_net: HyperNet,
pub tp_net: HyperNet,
// Define censor behavior
pub censor_secrecy: censor::Secrecy,
pub censor_hides: censor::Hides,
pub censor_speed: censor::Speed,
pub censor_event_duration: u32,
pub censor_totality: censor::Totality,

View File

@ -6,17 +6,17 @@ use crate::{
positive_report::PositiveReport,
simulation::{
bridge::Bridge,
censor::{Censor, Secrecy::*, Totality::*},
censor::{Censor, Hides::*, Totality::*},
config::Config,
},
BridgeDistributor,
};
use anyhow::{anyhow, Result};
use lox_cli::{networking::*, *};
use lox_library::{
bridge_table::BridgeLine, cred::Lox, proto::check_blockage::MIN_TRUST_LEVEL, scalar_u32,
};
use rand::Rng;
use serde_json::error::Error;
use std::{cmp::min, collections::HashMap};
use x25519_dalek::PublicKey;
@ -45,7 +45,7 @@ pub struct User {
}
impl User {
pub async fn new(config: &Config, is_censor: bool) -> Result<Self> {
pub async fn new(config: &Config, is_censor: bool) -> Result<Self, Error> {
let cred = get_lox_credential(
&config.la_net,
&get_open_invitation(&config.la_net).await?,
@ -75,7 +75,7 @@ impl User {
})
}
pub async fn trusted_user(config: &Config) -> Result<Self> {
pub async fn trusted_user(config: &Config) -> Result<Self, Error> {
let cred = get_lox_credential(
&config.la_net,
&get_open_invitation(&config.la_net).await?,
@ -98,7 +98,7 @@ impl User {
config: &Config,
censor: &mut Censor,
invited_user_is_censor: bool,
) -> Result<Self> {
) -> Result<Self, Error> {
let etable = get_reachability_credential(&config.la_net).await?;
let (new_cred, invite) = issue_invite(
&config.la_net,
@ -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 fn connect(&self, config: &Config, bridge: &mut Bridge, censor: &Censor) -> bool {
pub async 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_secrecy == Hiding {
if config.censor_hides == Hiding {
bridge.connect_total();
}
@ -179,6 +179,15 @@ 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;
@ -196,7 +205,7 @@ impl User {
true
}
pub async fn get_new_credential(config: &Config) -> Result<(Lox, BridgeLine)> {
pub async fn get_new_credential(config: &Config) -> Result<(Lox, BridgeLine), Error> {
get_lox_credential(
&config.la_net,
&get_open_invitation(&config.la_net).await?,
@ -205,10 +214,7 @@ impl User {
.await
}
pub async fn send_negative_reports(
config: &Config,
reports: Vec<NegativeReport>,
) -> Result<()> {
pub async fn send_negative_reports(config: &Config, reports: Vec<NegativeReport>) {
let date = get_date();
let pubkey = serde_json::from_slice::<Option<PublicKey>>(
&config
@ -217,8 +223,9 @@ impl User {
"/nrkey".to_string(),
serde_json::to_string(&date).unwrap().into(),
)
.await?,
)?
.await,
)
.unwrap()
.unwrap();
for report in reports {
config
@ -227,22 +234,17 @@ impl User {
"/negativereport".to_string(),
bincode::serialize(&report.encrypt(&pubkey)).unwrap(),
)
.await?;
.await;
}
Ok(())
}
pub async fn send_positive_reports(
config: &Config,
reports: Vec<PositiveReport>,
) -> Result<()> {
pub async fn send_positive_reports(config: &Config, reports: Vec<PositiveReport>) {
for report in reports {
config
.tp_net
.request("/positivereport".to_string(), report.to_json().into_bytes())
.await?;
.await;
}
Ok(())
}
pub async fn daily_tasks(
@ -252,7 +254,7 @@ impl User {
num_censor_invites: u32,
bridges: &mut HashMap<[u8; 20], Bridge>,
censor: &mut Censor,
) -> Result<Vec<User>> {
) -> Result<Vec<User>, Error> {
if self.is_censor {
self.daily_tasks_censor(config, bridges, censor).await
} else {
@ -278,17 +280,14 @@ impl User {
num_censor_invites: u32,
bridges: &mut HashMap<[u8; 20], Bridge>,
censor: &mut Censor,
) -> Result<Vec<User>> {
) -> Result<Vec<User>, Error> {
// 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.)
let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
let level = match scalar_u32(&self.primary_cred.trust_level) {
Some(v) => v,
None => return Err(anyhow!("Failed to get trust level from credential")),
};
let level = scalar_u32(&self.primary_cred.trust_level).unwrap();
// Make sure each bridge in bucket is in the global bridges set
for bridgeline in bucket {
@ -319,13 +318,16 @@ 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,
) {
if self
.connect(
&config,
bridges
.get_mut(&bucket[i].get_hashed_fingerprint())
.unwrap(),
&censor,
)
.await
{
succeeded.push(bucket[i]);
} else {
failed.push(bucket[i]);
@ -366,13 +368,16 @@ impl User {
);
}
// Attempt to connect to second cred's bridge
if self.connect(
&config,
bridges
.get_mut(&bridgeline.get_hashed_fingerprint())
.unwrap(),
censor,
) {
if self
.connect(
&config,
bridges
.get_mut(&bridgeline.get_hashed_fingerprint())
.unwrap(),
censor,
)
.await
{
succeeded.push(bridgeline);
if second_reachcred.is_some()
&& eligible_for_trust_promotion(&config.la_net, &second_cred).await
@ -501,17 +506,14 @@ impl User {
}
if negative_reports.len() > 0 {
Self::send_negative_reports(&config, negative_reports).await?;
Self::send_negative_reports(&config, negative_reports).await;
}
if positive_reports.len() > 0 {
Self::send_positive_reports(&config, positive_reports).await?;
Self::send_positive_reports(&config, positive_reports).await;
}
// Invite friends if applicable
let invitations = match scalar_u32(&self.primary_cred.invites_remaining) {
Some(v) => v,
None => 0, // This is probably an error case that should not happen
};
let invitations = scalar_u32(&self.primary_cred.invites_remaining).unwrap();
let mut new_friends = Vec::<User>::new();
for _i in 0..min(invitations, num_users_requesting_invites) {
if event_happens(config.prob_user_invites_friend) {
@ -559,7 +561,7 @@ impl User {
config: &Config,
bridges: &mut HashMap<[u8; 20], Bridge>,
censor: &mut Censor,
) -> Result<Vec<User>> {
) -> Result<Vec<User>, Error> {
// Download bucket to see if bridge is still reachable and if we
// have any new bridges
let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;