Track whether bridge has actually been distributed to users
This commit is contained in:
parent
fcbffdc53e
commit
25d1fb96a6
|
@ -15,6 +15,9 @@ pub struct Bridge {
|
|||
// we created this Bridge object
|
||||
pub first_distributed: u32,
|
||||
|
||||
// Date the bridge was first distributed to a non-censor user
|
||||
pub first_real_user: u32,
|
||||
|
||||
// First date a censor blocked this bridge
|
||||
pub first_blocked: u32,
|
||||
|
||||
|
@ -35,6 +38,7 @@ impl Bridge {
|
|||
Self {
|
||||
fingerprint: *fingerprint,
|
||||
first_distributed: get_date(),
|
||||
first_real_user: 0, // set this afterwards if user is non-censor
|
||||
first_blocked: 0,
|
||||
first_detected_blocked: 0,
|
||||
first_positive_report: 0,
|
||||
|
|
89
src/main.rs
89
src/main.rs
|
@ -126,11 +126,21 @@ pub async fn main() {
|
|||
});
|
||||
sleep(Duration::from_millis(1)).await;
|
||||
|
||||
// Only consider bridges that have been distributed to users
|
||||
let mut false_neg = 0;
|
||||
let mut false_pos = 0;
|
||||
let mut true_neg = 0;
|
||||
let mut true_pos = 0;
|
||||
|
||||
// All bridges, including those only known to the censor
|
||||
let mut total_fn = 0;
|
||||
let mut total_fp = 0;
|
||||
let mut total_tn = 0;
|
||||
let mut total_tp = 0;
|
||||
|
||||
// Track daily percentage of users who have at least one working bridge
|
||||
let mut percent_users_can_connect = Vec::<f64>::new();
|
||||
|
||||
// Track memory use during simulation
|
||||
let mut max_physical_mem = 0;
|
||||
let mut max_virtual_mem = 0;
|
||||
|
@ -140,6 +150,10 @@ pub async fn main() {
|
|||
// Save some function calls by storing this
|
||||
let date = get_date();
|
||||
|
||||
// Count of users who could use at least one bridge today
|
||||
let mut count_users_can_connect = 0;
|
||||
let mut count_users_cannot_connect = 0;
|
||||
|
||||
println!("Starting day {} of the simulation", day);
|
||||
println!(
|
||||
" We have {} users and {} bridges",
|
||||
|
@ -195,8 +209,37 @@ pub async fn main() {
|
|||
new_users.append(&mut invited_friends);
|
||||
}
|
||||
}
|
||||
|
||||
// Count the number of non-censor users who are able to
|
||||
// connect to at least one bridge
|
||||
if !user.is_censor {
|
||||
if user.able_to_connect {
|
||||
count_users_can_connect += 1;
|
||||
} else {
|
||||
count_users_cannot_connect += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also count number of new users with/without connections
|
||||
for user in &new_users {
|
||||
// Count the number of non-censor users who are able to
|
||||
// connect to at least one bridge
|
||||
if !user.is_censor {
|
||||
if user.able_to_connect {
|
||||
count_users_can_connect += 1;
|
||||
} else {
|
||||
count_users_cannot_connect += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add percent of users who can connect to vector
|
||||
percent_users_can_connect.push(
|
||||
count_users_can_connect as f64
|
||||
/ (count_users_can_connect + count_users_cannot_connect) as f64,
|
||||
);
|
||||
|
||||
// Add new users
|
||||
users.append(&mut new_users);
|
||||
|
||||
|
@ -285,14 +328,30 @@ pub async fn main() {
|
|||
if really_blocked && bridge.first_blocked == 0 {
|
||||
bridge.first_blocked = date;
|
||||
}
|
||||
|
||||
// Increase appropriate count. Only increase main count if
|
||||
// this is a bridge that has actually been distributed to a
|
||||
// non-censor user. Increase the total count regardless.
|
||||
if detected_blocked && really_blocked {
|
||||
true_pos += 1;
|
||||
if bridge.first_real_user > 0 {
|
||||
true_pos += 1;
|
||||
}
|
||||
total_tp += 1;
|
||||
} else if detected_blocked {
|
||||
false_pos += 1;
|
||||
if bridge.first_real_user > 0 {
|
||||
false_pos += 1;
|
||||
}
|
||||
total_fp += 1;
|
||||
} else if really_blocked {
|
||||
false_neg += 1;
|
||||
if bridge.first_real_user > 0 {
|
||||
false_neg += 1;
|
||||
}
|
||||
total_fn += 1;
|
||||
} else {
|
||||
true_neg += 1;
|
||||
if bridge.first_real_user > 0 {
|
||||
true_neg += 1;
|
||||
}
|
||||
total_tn += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,6 +393,13 @@ pub async fn main() {
|
|||
max_virtual_mem
|
||||
);
|
||||
|
||||
println!("\nThese total values include bridges never distributed to real users...");
|
||||
println!("Total true positives: {}", total_tp);
|
||||
println!("Total true negatives: {}", total_tn);
|
||||
println!("Total false positives: {}", total_fp);
|
||||
println!("Total false negatives: {}", total_fn);
|
||||
|
||||
println!("\nThese values only include bridges actually distributed to users...");
|
||||
println!("True Positives: {}", true_pos);
|
||||
println!("True Negatives: {}", true_neg);
|
||||
println!("False Positives: {}", false_pos);
|
||||
|
@ -342,16 +408,27 @@ pub async fn main() {
|
|||
println!("\nFull stats per bridge:");
|
||||
|
||||
println!(
|
||||
"Fingerprint,first_distributed,first_blocked,first_detected_blocked,first_positive_report"
|
||||
"Fingerprint,first_distributed,first_real_user,first_blocked,first_detected_blocked,first_positive_report"
|
||||
);
|
||||
for (fingerprint, bridge) in bridges {
|
||||
println!(
|
||||
"{},{},{},{},{}",
|
||||
"{},{},{},{},{},{}",
|
||||
array_bytes::bytes2hex("", fingerprint),
|
||||
bridge.first_distributed,
|
||||
bridge.first_real_user,
|
||||
bridge.first_blocked,
|
||||
bridge.first_detected_blocked,
|
||||
bridge.first_positive_report
|
||||
);
|
||||
}
|
||||
println!("End full stats per bridge\n");
|
||||
|
||||
println!("\nWhich users can connect:");
|
||||
println!("join_date,able_to_connect");
|
||||
for user in users {
|
||||
if !user.is_censor {
|
||||
println!("{},{}", user.join_date, user.able_to_connect);
|
||||
}
|
||||
}
|
||||
println!("End which users can connect");
|
||||
}
|
||||
|
|
129
src/user.rs
129
src/user.rs
|
@ -90,19 +90,27 @@ impl User {
|
|||
.unwrap();
|
||||
if is_censor {
|
||||
censor.learn_bridge(&bridgeline.get_hashed_fingerprint());
|
||||
} else if Self::connect(in_censorship_range, config, bridge, censor) {
|
||||
able_to_connect = true;
|
||||
} else if submits_reports {
|
||||
// New user only has one bridge, so no need
|
||||
// to collect the negative reports before
|
||||
// sending. Just send one now.
|
||||
let mut negative_reports = Vec::<NegativeReport>::new();
|
||||
negative_reports.push(NegativeReport::from_bridgeline(
|
||||
bridgeline,
|
||||
config.country.to_string(),
|
||||
BridgeDistributor::Lox,
|
||||
));
|
||||
Self::send_negative_reports(&config, negative_reports).await?;
|
||||
} else {
|
||||
// If this is the first time the bridge has been
|
||||
// distributed to a real user, store that info
|
||||
if bridge.first_real_user == 0 {
|
||||
bridge.first_real_user = get_date();
|
||||
}
|
||||
|
||||
if Self::connect(in_censorship_range, config, bridge, censor) {
|
||||
able_to_connect = true;
|
||||
} else if submits_reports {
|
||||
// New user only has one bridge, so no need
|
||||
// to collect the negative reports before
|
||||
// sending. Just send one now.
|
||||
let mut negative_reports = Vec::<NegativeReport>::new();
|
||||
negative_reports.push(NegativeReport::from_bridgeline(
|
||||
bridgeline,
|
||||
config.country.to_string(),
|
||||
BridgeDistributor::Lox,
|
||||
));
|
||||
Self::send_negative_reports(&config, negative_reports).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,16 +146,28 @@ impl User {
|
|||
)
|
||||
.await?;
|
||||
self.primary_cred = new_cred;
|
||||
if self.is_censor {
|
||||
// Make sure censor has access to each bridge and each
|
||||
// credential
|
||||
let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
|
||||
for bl in bucket {
|
||||
// Make sure bridge is in list of bridges and that censor has
|
||||
// access if applicable
|
||||
let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
|
||||
for bl in bucket {
|
||||
if bl != BridgeLine::default() {
|
||||
let fingerprint = bl.get_hashed_fingerprint();
|
||||
censor.learn_bridge(&fingerprint);
|
||||
censor.give_lox_cred(&fingerprint, &self.primary_cred);
|
||||
if !bridges.contains_key(&fingerprint) {
|
||||
let bridge = Bridge::from_bridge_line(&bl);
|
||||
bridges.insert(fingerprint, bridge);
|
||||
}
|
||||
let bridge = bridges.get_mut(&fingerprint).unwrap();
|
||||
if self.is_censor {
|
||||
censor.learn_bridge(&fingerprint);
|
||||
censor.give_lox_cred(&fingerprint, &self.primary_cred);
|
||||
// If this is the first time the bridge has been
|
||||
// distributed to a real user, store that info
|
||||
} else if bridge.first_real_user == 0 {
|
||||
bridge.first_real_user = get_date();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let friend_cred = redeem_invite(
|
||||
&config.la_net,
|
||||
&invite,
|
||||
|
@ -184,24 +204,31 @@ impl User {
|
|||
let mut negative_reports = Vec::<NegativeReport>::new();
|
||||
let (bucket, _reachcred) = get_bucket(&config.la_net, &friend_cred).await?;
|
||||
for bridgeline in bucket {
|
||||
let fingerprint = bridgeline.get_hashed_fingerprint();
|
||||
if bridgeline != BridgeLine::default() {
|
||||
if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
|
||||
if !bridges.contains_key(&fingerprint) {
|
||||
let bridge = Bridge::from_bridge_line(&bridgeline);
|
||||
bridges.insert(bridgeline.get_hashed_fingerprint(), bridge);
|
||||
bridges.insert(fingerprint, bridge);
|
||||
}
|
||||
let bridge = bridges
|
||||
.get_mut(&bridgeline.get_hashed_fingerprint())
|
||||
.unwrap();
|
||||
let bridge = bridges.get_mut(&fingerprint).unwrap();
|
||||
if is_censor {
|
||||
censor.learn_bridge(&bridgeline.get_hashed_fingerprint());
|
||||
} else if Self::connect(in_censorship_range, config, bridge, censor) {
|
||||
able_to_connect = true;
|
||||
} else if submits_reports {
|
||||
negative_reports.push(NegativeReport::from_bridgeline(
|
||||
bridgeline,
|
||||
config.country.to_string(),
|
||||
BridgeDistributor::Lox,
|
||||
));
|
||||
censor.learn_bridge(&fingerprint);
|
||||
} else {
|
||||
// If this is the first time the bridge has been
|
||||
// distributed to a real user, store that info
|
||||
if bridge.first_real_user == 0 {
|
||||
bridge.first_real_user = get_date();
|
||||
}
|
||||
|
||||
if Self::connect(in_censorship_range, config, bridge, censor) {
|
||||
able_to_connect = true;
|
||||
} else if submits_reports {
|
||||
negative_reports.push(NegativeReport::from_bridgeline(
|
||||
bridgeline,
|
||||
config.country.to_string(),
|
||||
BridgeDistributor::Lox,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -370,9 +397,17 @@ impl User {
|
|||
// Make sure each bridge in bucket is in the global bridges set
|
||||
for bridgeline in bucket {
|
||||
if bridgeline != BridgeLine::default() {
|
||||
if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
|
||||
let fingerprint = bridgeline.get_hashed_fingerprint();
|
||||
if !bridges.contains_key(&fingerprint) {
|
||||
let bridge = Bridge::from_bridge_line(&bridgeline);
|
||||
bridges.insert(bridgeline.get_hashed_fingerprint(), bridge);
|
||||
bridges.insert(fingerprint, bridge);
|
||||
}
|
||||
|
||||
// If this is the first time the bridge has been
|
||||
// distributed to a real user, store that info
|
||||
let bridge = bridges.get_mut(&fingerprint).unwrap();
|
||||
if bridge.first_real_user == 0 {
|
||||
bridge.first_real_user = get_date();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -437,21 +472,23 @@ impl User {
|
|||
get_bucket(&config.la_net, &second_cred).await?;
|
||||
for bridgeline in second_bucket {
|
||||
if bridgeline != BridgeLine::default() {
|
||||
if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
|
||||
let fingerprint = bridgeline.get_hashed_fingerprint();
|
||||
if !bridges.contains_key(&fingerprint) {
|
||||
bridges.insert(
|
||||
bridgeline.get_hashed_fingerprint(),
|
||||
bridgeline.fingerprint,
|
||||
Bridge::from_bridge_line(&bridgeline),
|
||||
);
|
||||
}
|
||||
|
||||
// If this is the first time the bridge has been
|
||||
// distributed to a real user, store that info
|
||||
let bridge = bridges.get_mut(&fingerprint).unwrap();
|
||||
if bridge.first_real_user == 0 {
|
||||
bridge.first_real_user = get_date();
|
||||
}
|
||||
|
||||
// Attempt to connect to second cred's bridge
|
||||
if Self::connect(
|
||||
self.in_censorship_range,
|
||||
&config,
|
||||
bridges
|
||||
.get_mut(&bridgeline.get_hashed_fingerprint())
|
||||
.unwrap(),
|
||||
censor,
|
||||
) {
|
||||
if Self::connect(self.in_censorship_range, &config, bridge, censor) {
|
||||
succeeded.push(bridgeline);
|
||||
if second_reachcred.is_some()
|
||||
&& eligible_for_trust_promotion(&config.la_net, &second_cred).await
|
||||
|
|
Loading…
Reference in New Issue