Add support for verifying Troll Patrol's inferences

This commit is contained in:
Vecna 2025-05-23 13:08:28 -04:00
parent 1e3cb62822
commit ff3aa2d718
2 changed files with 76 additions and 2 deletions

View File

@ -837,6 +837,71 @@ pub fn guess_blockages(
blockages
}
/// Verify bridges suspected of being blocked, return only the ones that are
/// actually blocked
pub async fn verify_blockages(
verify_blockages_url: &str,
suspected_blockages: HashMap<[u8; 20], HashSet<String>>,
) -> HashMap<[u8; 20], HashSet<String>> {
// If we don't have a resource for checking if bridges are blocked, assume
// that Troll Patrol guessed correctly
if verify_blockages_url.is_empty() {
return suspected_blockages;
}
// Convert map keys from [u8; 20] to 40-character hex strings
let mut suspected_blockages_str = HashMap::<String, HashSet<String>>::new();
for (fingerprint, countries) in &suspected_blockages {
let fpr_string = array_bytes::bytes2hex("", fingerprint);
if !countries.is_empty() {
suspected_blockages_str.insert(fpr_string, countries.clone());
}
}
if !suspected_blockages_str.is_empty() {
// Send suspected blockages to verification endpoint for verification
let client = Client::new();
let req = Request::builder()
.method(Method::POST)
.uri(verify_blockages_url)
.body(Body::from(
serde_json::to_string(&suspected_blockages_str).unwrap(),
))
.unwrap();
let resp = client.request(req).await.unwrap();
let buf = hyper::body::to_bytes(resp).await.unwrap();
let resp_str = String::from_utf8(buf.to_vec()).unwrap();
// Deserialize map
let blockages_str: HashMap<String, HashSet<String>> = match serde_json::from_str(&resp_str)
{
Ok(v) => v,
Err(e) => {
eprintln!(
"Failed to deserialize response from verification endpoint: {:?}",
e
);
HashMap::<String, HashSet<String>>::new()
}
};
// Convert map so it uses [u8; 20]s as keys again
let mut blockages = HashMap::<[u8; 20], HashSet<String>>::new();
for (fingerprint, countries) in blockages_str {
if let Ok(fpr) = array_bytes::hex2array(fingerprint) {
if !countries.is_empty() {
blockages.insert(fpr, countries);
}
}
}
// Return map of confirmed blockages
blockages
} else {
suspected_blockages
}
}
/// Commit blocked bridges to database
pub fn commit_blockages(db: &Db, blockages: &HashMap<[u8; 20], HashSet<String>>) {
// For each bridge:<set of countries>, mark the bridge as blocked in each country

View File

@ -51,6 +51,7 @@ pub struct Config {
// map of distributor name to IP:port to contact it
pub distributors: BTreeMap<BridgeDistributor, String>,
extra_infos_base_url: String,
verify_blockages_url: String,
// confidence required to consider a bridge blocked
confidence: f64,
@ -92,6 +93,7 @@ async fn update_daily_info(
db: &Db,
distributors: &BTreeMap<BridgeDistributor, String>,
extra_infos_base_url: &str,
verify_blockages_url: &str,
confidence: f64,
max_threshold: u32,
scaling_factor: f64,
@ -109,7 +111,10 @@ async fn update_daily_info(
min_historical_days,
max_historical_days,
);
// TODO: Verify the new blockages
// This implementation will vary based on scanning infrastructure
let new_blockages = verify_blockages(verify_blockages_url, new_blockages).await;
commit_blockages(db, &new_blockages);
report_blockages(distributors, new_blockages.clone()).await;
@ -132,6 +137,7 @@ async fn create_context_manager(
db_config: DbConfig,
distributors: BTreeMap<BridgeDistributor, String>,
extra_infos_base_url: &str,
verify_blockages_url: &str,
confidence: f64,
max_threshold: u32,
scaling_factor: f64,
@ -141,7 +147,7 @@ async fn create_context_manager(
mut kill: broadcast::Receiver<()>,
) {
tokio::select! {
create_context = context_manager(db_config, distributors, extra_infos_base_url, confidence, max_threshold, scaling_factor, min_historical_days, max_historical_days, context_rx) => create_context,
create_context = context_manager(db_config, distributors, extra_infos_base_url, verify_blockages_url, confidence, max_threshold, scaling_factor, min_historical_days, max_historical_days, context_rx) => create_context,
_ = kill.recv() => {println!("Shut down manager");},
}
}
@ -150,6 +156,7 @@ async fn context_manager(
db_config: DbConfig,
distributors: BTreeMap<BridgeDistributor, String>,
extra_infos_base_url: &str,
verify_blockages_url: &str,
confidence: f64,
max_threshold: u32,
scaling_factor: f64,
@ -202,6 +209,7 @@ async fn context_manager(
&db,
&distributors,
extra_infos_base_url,
verify_blockages_url,
confidence,
max_threshold,
scaling_factor,
@ -296,6 +304,7 @@ async fn main() {
config.db,
config.distributors,
&config.extra_infos_base_url,
&config.verify_blockages_url,
config.confidence,
config.max_threshold,
config.scaling_factor,