Add probability of user treating throttling as interference
This commit is contained in:
parent
bff304eef0
commit
c3b1908120
|
@ -61,6 +61,7 @@ pub struct Config {
|
||||||
pub prob_user_invites_friend: f64,
|
pub prob_user_invites_friend: f64,
|
||||||
pub prob_user_is_censor: f64,
|
pub prob_user_is_censor: f64,
|
||||||
pub prob_user_submits_reports: f64,
|
pub prob_user_submits_reports: f64,
|
||||||
|
pub prob_user_treats_throttling_as_blocking: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -105,6 +106,7 @@ pub async fn main() {
|
||||||
prob_user_invites_friend: config.prob_user_invites_friend,
|
prob_user_invites_friend: config.prob_user_invites_friend,
|
||||||
prob_user_is_censor: config.prob_user_is_censor,
|
prob_user_is_censor: config.prob_user_is_censor,
|
||||||
prob_user_submits_reports: config.prob_user_submits_reports,
|
prob_user_submits_reports: config.prob_user_submits_reports,
|
||||||
|
prob_user_treats_throttling_as_blocking: config.prob_user_treats_throttling_as_blocking,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
|
@ -94,6 +94,31 @@ impl Censor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Censor sends a positive report for the given bridge. Returns true
|
||||||
|
// if successful, false otherwise.
|
||||||
|
pub async fn send_positive_report(&self, config: &Config, fingerprint: &[u8; 20]) -> bool {
|
||||||
|
// If we don't have an appropriate Lox credential, we can't send
|
||||||
|
// a report. Return false.
|
||||||
|
if !self.has_lox_cred(fingerprint) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (cred, _) = &self.lox_credentials.get(fingerprint).unwrap();
|
||||||
|
let pr = PositiveReport::from_lox_credential(
|
||||||
|
*fingerprint,
|
||||||
|
None,
|
||||||
|
cred,
|
||||||
|
get_lox_pub(&config.la_pubkeys),
|
||||||
|
config.country.clone(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
config
|
||||||
|
.tp_net
|
||||||
|
.request("/positivereport".to_string(), pr.to_json().into_bytes())
|
||||||
|
.await;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
// Make a bunch of connections and submit positive reports if possible
|
// Make a bunch of connections and submit positive reports if possible
|
||||||
async fn flood(&self, config: &Config, bridges: &mut HashMap<[u8; 20], Bridge>) {
|
async fn flood(&self, config: &Config, bridges: &mut HashMap<[u8; 20], Bridge>) {
|
||||||
// Only do this if Flooding censor
|
// Only do this if Flooding censor
|
||||||
|
@ -115,8 +140,7 @@ impl Censor {
|
||||||
// If we have a lv3+ credential, submit a bunch of
|
// If we have a lv3+ credential, submit a bunch of
|
||||||
// positive reports
|
// positive reports
|
||||||
if self.has_lox_cred(fingerprint) {
|
if self.has_lox_cred(fingerprint) {
|
||||||
let lox_pub = get_lox_pub(&config.la_pubkeys);
|
let (_cred, cred_count) =
|
||||||
let (cred, cred_count) =
|
|
||||||
&self.lox_credentials.get(&bridge.fingerprint).unwrap();
|
&self.lox_credentials.get(&bridge.fingerprint).unwrap();
|
||||||
let num_prs = if config.one_positive_report_per_cred {
|
let num_prs = if config.one_positive_report_per_cred {
|
||||||
*cred_count
|
*cred_count
|
||||||
|
@ -124,18 +148,7 @@ impl Censor {
|
||||||
rng.gen_range(1000..30000)
|
rng.gen_range(1000..30000)
|
||||||
};
|
};
|
||||||
for _ in 0..num_prs {
|
for _ in 0..num_prs {
|
||||||
let pr = PositiveReport::from_lox_credential(
|
self.send_positive_report(config, &bridge.fingerprint).await;
|
||||||
bridge.fingerprint,
|
|
||||||
None,
|
|
||||||
cred,
|
|
||||||
lox_pub,
|
|
||||||
config.country.clone(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
config
|
|
||||||
.tp_net
|
|
||||||
.request("/positivereport".to_string(), pr.to_json().into_bytes())
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,5 @@ pub struct Config {
|
||||||
pub prob_user_invites_friend: f64,
|
pub prob_user_invites_friend: f64,
|
||||||
pub prob_user_is_censor: f64,
|
pub prob_user_is_censor: f64,
|
||||||
pub prob_user_submits_reports: f64,
|
pub prob_user_submits_reports: f64,
|
||||||
|
pub prob_user_treats_throttling_as_blocking: f64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,23 +156,45 @@ impl User {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to "connect" to the bridge, returns true if successful
|
// Attempt to "connect" to the bridge, returns true if successful.
|
||||||
pub fn connect(&self, config: &Config, bridge: &mut Bridge, censor: &Censor) -> bool {
|
// 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 {
|
||||||
if censor.blocks_bridge(config, &bridge.fingerprint) {
|
if censor.blocks_bridge(config, &bridge.fingerprint) {
|
||||||
if config.censor_totality == Full
|
if config.censor_totality == Full
|
||||||
|| config.censor_totality == Partial
|
|| config.censor_totality == Partial
|
||||||
&& event_happens(censor.partial_blocking_percent)
|
&& event_happens(censor.partial_blocking_percent)
|
||||||
|| config.censor_totality == Throttling
|
|
||||||
{
|
{
|
||||||
// If censor tries to hide its censorship or
|
// If censor tries to hide its censorship, record a
|
||||||
// throttles rather than actually blocking, record a
|
|
||||||
// false connection
|
// false connection
|
||||||
if config.censor_hides == Hiding || config.censor_totality == Throttling {
|
if config.censor_hides == Hiding {
|
||||||
bridge.connect_total();
|
bridge.connect_total();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return false because the connection failed
|
// Return false because the connection failed
|
||||||
return false;
|
return false;
|
||||||
|
} else if config.censor_totality == Throttling {
|
||||||
|
// With some probability, the user connects but gives up
|
||||||
|
// because there is too much interference. In this case,
|
||||||
|
// a real connection occurs, but we treat it like a
|
||||||
|
// false connection from the censor.
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,13 +313,16 @@ impl User {
|
||||||
for i in 0..bucket.len() {
|
for i in 0..bucket.len() {
|
||||||
// At level 0, we only have 1 bridge
|
// At level 0, we only have 1 bridge
|
||||||
if bucket[i] != BridgeLine::default() {
|
if bucket[i] != BridgeLine::default() {
|
||||||
if self.connect(
|
if self
|
||||||
&config,
|
.connect(
|
||||||
bridges
|
&config,
|
||||||
.get_mut(&bucket[i].get_hashed_fingerprint())
|
bridges
|
||||||
.unwrap(),
|
.get_mut(&bucket[i].get_hashed_fingerprint())
|
||||||
&censor,
|
.unwrap(),
|
||||||
) {
|
&censor,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
succeeded.push(bucket[i]);
|
succeeded.push(bucket[i]);
|
||||||
} else {
|
} else {
|
||||||
failed.push(bucket[i]);
|
failed.push(bucket[i]);
|
||||||
|
@ -338,13 +363,16 @@ impl User {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Attempt to connect to second cred's bridge
|
// Attempt to connect to second cred's bridge
|
||||||
if self.connect(
|
if self
|
||||||
&config,
|
.connect(
|
||||||
bridges
|
&config,
|
||||||
.get_mut(&bridgeline.get_hashed_fingerprint())
|
bridges
|
||||||
.unwrap(),
|
.get_mut(&bridgeline.get_hashed_fingerprint())
|
||||||
censor,
|
.unwrap(),
|
||||||
) {
|
censor,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
succeeded.push(bridgeline);
|
succeeded.push(bridgeline);
|
||||||
if second_reachcred.is_some()
|
if second_reachcred.is_some()
|
||||||
&& eligible_for_trust_promotion(&config.la_net, &second_cred).await
|
&& eligible_for_trust_promotion(&config.la_net, &second_cred).await
|
||||||
|
|
Loading…
Reference in New Issue