|
@@ -327,6 +327,237 @@ fn test_negative_reports() {
|
|
|
|
|
|
assert!(!invalid_report_4.verify(&bridge_info_1));
|
|
|
assert!(!invalid_report_5.verify(&bridge_info_2));
|
|
|
+
|
|
|
+ // Test that reports with duplicate nonces are rejected
|
|
|
+
|
|
|
+ // Open test database
|
|
|
+ let db: Db = sled::open("test_db").unwrap();
|
|
|
+
|
|
|
+ // Delete all data in test DB
|
|
|
+ db.clear().unwrap();
|
|
|
+ assert!(!db.contains_key("nrs-to-process").unwrap());
|
|
|
+
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+
|
|
|
+ // A valid report
|
|
|
+ let valid_report_1 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&bridges[0], date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report which reuses this nonce
|
|
|
+ let invalid_report_1 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&bridges[0], date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // This is the same report
|
|
|
+ assert_eq!(valid_report_1, invalid_report_1);
|
|
|
+
|
|
|
+ // Report which reuses this nonce for a different bridge
|
|
|
+ let invalid_report_2 = NegativeReport::new(
|
|
|
+ bridges[1].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&bridges[1], date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report which uses this nonce but on a different day
|
|
|
+ let valid_report_2 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(
|
|
|
+ &bridges[0],
|
|
|
+ date - 1,
|
|
|
+ nonce,
|
|
|
+ )),
|
|
|
+ "ru".to_string(),
|
|
|
+ date - 1,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report with different nonce
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+
|
|
|
+ let valid_report_3 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&bridges[0], date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ let map_key_1 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", valid_report_1.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, valid_report_1);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ save_negative_report_to_process(&db, invalid_report_1); // no change
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ let map_key_2 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", invalid_report_2.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, invalid_report_2); // no change
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ assert!(!nrs_to_process.contains_key(&map_key_2));
|
|
|
+
|
|
|
+ let map_key_3 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", valid_report_2.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date - 1
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, valid_report_2);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_3).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ save_negative_report_to_process(&db, valid_report_3);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 2);
|
|
|
+
|
|
|
+ // Same tests, but use hash of bucket
|
|
|
+
|
|
|
+ // Delete all data in test DB
|
|
|
+ db.clear().unwrap();
|
|
|
+ assert!(!db.contains_key("nrs-to-process").unwrap());
|
|
|
+
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+
|
|
|
+ // A valid report
|
|
|
+ let valid_report_1 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&cred.bucket, date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report which reuses this nonce
|
|
|
+ let invalid_report_1 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&cred.bucket, date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // This is the same report
|
|
|
+ assert_eq!(valid_report_1, invalid_report_1);
|
|
|
+
|
|
|
+ // Report which reuses this nonce for a different bridge
|
|
|
+ let invalid_report_2 = NegativeReport::new(
|
|
|
+ bridges[1].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&cred.bucket, date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report which uses this nonce but on a different day
|
|
|
+ let valid_report_2 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&cred.bucket, date - 1, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date - 1,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ // Report with different nonce
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+
|
|
|
+ let valid_report_3 = NegativeReport::new(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&cred.bucket, date, nonce)),
|
|
|
+ "ru".to_string(),
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ );
|
|
|
+
|
|
|
+ let map_key_1 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", valid_report_1.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, valid_report_1);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ save_negative_report_to_process(&db, invalid_report_1); // no change
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ let map_key_2 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", invalid_report_2.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, invalid_report_2); // no change
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ assert!(!nrs_to_process.contains_key(&map_key_2));
|
|
|
+
|
|
|
+ let map_key_3 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", valid_report_2.fingerprint),
|
|
|
+ "ru".to_string(),
|
|
|
+ date - 1
|
|
|
+ );
|
|
|
+ save_negative_report_to_process(&db, valid_report_2);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_3).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 1);
|
|
|
+
|
|
|
+ save_negative_report_to_process(&db, valid_report_3);
|
|
|
+ let nrs_to_process: BTreeMap<String, Vec<SerializableNegativeReport>> =
|
|
|
+ bincode::deserialize(&db.get("nrs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let negative_reports = nrs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(negative_reports.len(), 2);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
@@ -469,4 +700,76 @@ fn test_positive_reports() {
|
|
|
|
|
|
assert!(invalid_report_4.to_report().is_err());
|
|
|
assert!(invalid_report_5.to_report().is_err());
|
|
|
+
|
|
|
+ // Test storing to-be-processed positive reports to database
|
|
|
+
|
|
|
+ // Create reports
|
|
|
+ let report_1 = PositiveReport::from_lox_credential(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ None,
|
|
|
+ &cred,
|
|
|
+ &th.ba.lox_pub,
|
|
|
+ "ru".to_string(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ let report_2 = PositiveReport::from_lox_credential(
|
|
|
+ bridges[0].fingerprint,
|
|
|
+ None,
|
|
|
+ &cred,
|
|
|
+ &th.ba.lox_pub,
|
|
|
+ "ru".to_string(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ let report_3 = PositiveReport::from_lox_credential(
|
|
|
+ bridges[1].fingerprint,
|
|
|
+ None,
|
|
|
+ &cred,
|
|
|
+ &th.ba.lox_pub,
|
|
|
+ "ru".to_string(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ // Open test database
|
|
|
+ let db: Db = sled::open("test_db").unwrap();
|
|
|
+
|
|
|
+ // Delete all data in test DB
|
|
|
+ db.clear().unwrap();
|
|
|
+ assert!(!db.contains_key("prs-to-process").unwrap());
|
|
|
+
|
|
|
+ let map_key_1 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", report_1.fingerprint),
|
|
|
+ &report_1.country,
|
|
|
+ &report_1.date
|
|
|
+ );
|
|
|
+ let map_key_2 = format!(
|
|
|
+ "{}_{}_{}",
|
|
|
+ array_bytes::bytes2hex("", report_3.fingerprint),
|
|
|
+ &report_3.country,
|
|
|
+ &report_3.date
|
|
|
+ );
|
|
|
+
|
|
|
+ save_positive_report_to_process(&db, report_1);
|
|
|
+ let prs_to_process: BTreeMap<String, Vec<SerializablePositiveReport>> =
|
|
|
+ bincode::deserialize(&db.get("prs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let positive_reports = prs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(positive_reports.len(), 1);
|
|
|
+ assert!(!prs_to_process.contains_key(&map_key_2));
|
|
|
+
|
|
|
+ save_positive_report_to_process(&db, report_2);
|
|
|
+ let prs_to_process: BTreeMap<String, Vec<SerializablePositiveReport>> =
|
|
|
+ bincode::deserialize(&db.get("prs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ let positive_reports = prs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(positive_reports.len(), 2);
|
|
|
+ assert!(!prs_to_process.contains_key(&map_key_2));
|
|
|
+
|
|
|
+ save_positive_report_to_process(&db, report_3);
|
|
|
+ let prs_to_process: BTreeMap<String, Vec<SerializablePositiveReport>> =
|
|
|
+ bincode::deserialize(&db.get("prs-to-process").unwrap().unwrap()).unwrap();
|
|
|
+ // Check that this has not changed
|
|
|
+ let positive_reports = prs_to_process.get(&map_key_1).unwrap();
|
|
|
+ assert_eq!(positive_reports.len(), 2);
|
|
|
+ // New report added to its own collection
|
|
|
+ let positive_reports = prs_to_process.get(&map_key_2).unwrap();
|
|
|
+ assert_eq!(positive_reports.len(), 1);
|
|
|
}
|