Test dropping NRs with repeated nonces and DB storage before processing
This commit is contained in:
parent
c82e604e3d
commit
c5a05be6d8
|
@ -20,7 +20,7 @@ pub enum NegativeReportError {
|
|||
}
|
||||
|
||||
/// A report that the user was unable to connect to the bridge
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct NegativeReport {
|
||||
/// hashed fingerprint (SHA-1 hash of 20-byte bridge ID)
|
||||
pub fingerprint: [u8; 20],
|
||||
|
@ -200,7 +200,7 @@ impl SerializableNegativeReport {
|
|||
}
|
||||
|
||||
/// Proof that the user knows (and should be able to access) a given bridge
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub enum ProofOfBridgeKnowledge {
|
||||
/// Hash of bridge line as proof of knowledge of bridge line
|
||||
HashOfBridgeLine(HashOfBridgeLine),
|
||||
|
@ -210,7 +210,7 @@ pub enum ProofOfBridgeKnowledge {
|
|||
}
|
||||
|
||||
/// Hash of bridge line to prove knowledge of that bridge
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct HashOfBridgeLine {
|
||||
hash: [u8; 32],
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ impl HashOfBridgeLine {
|
|||
}
|
||||
|
||||
/// Hash of bucket ID to prove knowledge of bridges in that bucket
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct HashOfBucket {
|
||||
hash: [u8; 32],
|
||||
}
|
||||
|
|
303
src/tests.rs
303
src/tests.rs
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue