mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 02:12:13 +00:00
add dynamic test
This commit is contained in:
parent
5d8133a92f
commit
954eedd40e
4 changed files with 104 additions and 11 deletions
|
|
@ -104,10 +104,14 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
||||||
|
|
||||||
let signature = self.utils.sign_data(&signed_data.encode_to_vec()).await?;
|
let signature = self.utils.sign_data(&signed_data.encode_to_vec()).await?;
|
||||||
|
|
||||||
|
debug_assert_eq!(threshold, config.threshold);
|
||||||
|
|
||||||
let verification_shares = self
|
let verification_shares = self
|
||||||
.setup_announcements(&config, signed_data, signature)
|
.setup_announcements(&config, signed_data, signature)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
debug_assert_eq!(verification_shares.len(), threshold as usize - 1);
|
||||||
|
|
||||||
config.public_id = public_id;
|
config.public_id = public_id;
|
||||||
config.announcement_version += 1;
|
config.announcement_version += 1;
|
||||||
config.verification_shares = verification_shares;
|
config.verification_shares = verification_shares;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ impl UserDiscoveryStore for InMemoryStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_shares(&self, shares: Vec<Vec<u8>>) -> Result<()> {
|
async fn set_shares(&self, shares: Vec<Vec<u8>>) -> Result<()> {
|
||||||
|
self.storage().used_shares.clear();
|
||||||
self.storage().unused_shares = shares;
|
self.storage().unused_shares = shares;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ impl<S: UserDiscoveryStore + Clone + Default> TestNetwork<S> {
|
||||||
self.names.push(name);
|
self.names.push(name);
|
||||||
self.friends.push(vec![]);
|
self.friends.push(vec![]);
|
||||||
self.announced_users_expected.push(vec![]);
|
self.announced_users_expected.push(vec![]);
|
||||||
|
|
||||||
let store = S::default();
|
let store = S::default();
|
||||||
self.uds.push(get_ud(id, threshold, store).await);
|
self.uds.push(get_ud(id, threshold, store).await);
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +52,10 @@ impl<S: UserDiscoveryStore + Clone + Default> TestNetwork<S> {
|
||||||
fn expect_announced_user(&mut self, user: &str, contact: &str, friends_of_contact: &[&str]) {
|
fn expect_announced_user(&mut self, user: &str, contact: &str, friends_of_contact: &[&str]) {
|
||||||
let user_id = self.ids_by_name[user];
|
let user_id = self.ids_by_name[user];
|
||||||
let contact_id = self.ids_by_name[contact];
|
let contact_id = self.ids_by_name[contact];
|
||||||
let f_ids: Vec<usize> = friends_of_contact.iter().map(|f| self.ids_by_name[*f]).collect();
|
let f_ids: Vec<usize> = friends_of_contact
|
||||||
|
.iter()
|
||||||
|
.map(|f| self.ids_by_name[*f])
|
||||||
|
.collect();
|
||||||
self.announced_users_expected[user_id].push((contact_id, f_ids));
|
self.announced_users_expected[user_id].push((contact_id, f_ids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,17 +75,17 @@ async fn get_with_five_users<S: UserDiscoveryStore + Default + Clone>() -> TestN
|
||||||
network.set_friends("DAVID", &["BOB", "CHARLIE"]);
|
network.set_friends("DAVID", &["BOB", "CHARLIE"]);
|
||||||
network.set_friends("FRANK", &["CHARLIE"]);
|
network.set_friends("FRANK", &["CHARLIE"]);
|
||||||
|
|
||||||
network.add_message_flow("ALICE", 1); // ALICE: own announcement sending to BOB and CHARLIE
|
network.add_message_flow("ALICE", 1); // ALICE: own announcement sending to BOB and CHARLIE
|
||||||
network.add_message_flow("BOB", 2); // BOB: own announcement + promotion for ALICE
|
network.add_message_flow("BOB", 2); // BOB: own announcement + promotion for ALICE
|
||||||
network.add_message_flow("BOB", 0); // BOBs version should not have any new messages for his friends
|
network.add_message_flow("BOB", 0); // BOBs version should not have any new messages for his friends
|
||||||
network.add_message_flow("ALICE", 1); // ALICE: promotion for BOB
|
network.add_message_flow("ALICE", 1); // ALICE: promotion for BOB
|
||||||
network.add_message_flow("CHARLIE", 3); // CHARLIE: own announcement + promotion for ALICE, BOB
|
network.add_message_flow("CHARLIE", 3); // CHARLIE: own announcement + promotion for ALICE, BOB
|
||||||
network.add_message_flow("DAVID", 3); // DAVID: own announcement + promotion for BOB, CHARLIE
|
network.add_message_flow("DAVID", 3); // DAVID: own announcement + promotion for BOB, CHARLIE
|
||||||
network.add_message_flow("BOB", 2); // BOB: promotion for CHARLIE, DAVID
|
network.add_message_flow("BOB", 2); // BOB: promotion for CHARLIE, DAVID
|
||||||
network.add_message_flow("CHARLIE", 1); // CHARLIE: promotion for DAVID
|
network.add_message_flow("CHARLIE", 1); // CHARLIE: promotion for DAVID
|
||||||
network.add_message_flow("FRANK", 2); // FRANK: own announcement + promotion for CHARLIE
|
network.add_message_flow("FRANK", 2); // FRANK: own announcement + promotion for CHARLIE
|
||||||
network.add_message_flow("CHARLIE", 1); // CHARLIE: promotion for FRANK
|
network.add_message_flow("CHARLIE", 1); // CHARLIE: promotion for FRANK
|
||||||
network.add_message_flow("ALICE", 1); // ALICE: promotion for CHARLIE
|
network.add_message_flow("ALICE", 1); // ALICE: promotion for CHARLIE
|
||||||
|
|
||||||
// ALICE should now know that BOB and CHARLIE, BOB and DAVID and CHARLIE and DAVID are friends.
|
// ALICE should now know that BOB and CHARLIE, BOB and DAVID and CHARLIE and DAVID are friends.
|
||||||
// Alice should also have one protected share from Frank.
|
// Alice should also have one protected share from Frank.
|
||||||
|
|
@ -108,6 +111,91 @@ async fn get_with_five_users<S: UserDiscoveryStore + Default + Clone>() -> TestN
|
||||||
network
|
network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_user_discovery_dynamic_threshold_in_memory_store() {
|
||||||
|
let _ = pretty_env_logger::try_init();
|
||||||
|
|
||||||
|
let mut network = TestNetwork::<InMemoryStore>::new();
|
||||||
|
|
||||||
|
// Start ALICE with a more strict threshold of 3.
|
||||||
|
// David only has 2 paths to Alice (via Bob and Charlie). Since 2 < 3, David cannot discover Alice.
|
||||||
|
network.add_user("ALICE", 3).await;
|
||||||
|
network.add_user("BOB", 2).await;
|
||||||
|
network.add_user("CHARLIE", 2).await;
|
||||||
|
network.add_user("DAVID", 2).await;
|
||||||
|
network.add_user("FRANK", 2).await;
|
||||||
|
|
||||||
|
// Same topology as the initial 5 users
|
||||||
|
network.set_friends("ALICE", &["BOB", "CHARLIE"]);
|
||||||
|
network.set_friends("BOB", &["ALICE", "CHARLIE", "DAVID"]);
|
||||||
|
network.set_friends("CHARLIE", &["ALICE", "BOB", "DAVID", "FRANK"]);
|
||||||
|
network.set_friends("DAVID", &["BOB", "CHARLIE"]);
|
||||||
|
network.set_friends("FRANK", &["CHARLIE"]);
|
||||||
|
|
||||||
|
let david_idx = network.ids_by_name["DAVID"];
|
||||||
|
let alice_idx = network.ids_by_name["ALICE"];
|
||||||
|
let charlie_idx = network.ids_by_name["CHARLIE"];
|
||||||
|
|
||||||
|
// Phase 1: Exchange with ALICE threshold = 3
|
||||||
|
step0_exchange_random::<InMemoryStore>(&network).await;
|
||||||
|
step1_verify_no_new_messages::<InMemoryStore>(&network).await;
|
||||||
|
|
||||||
|
let version = network.uds[david_idx]
|
||||||
|
.get_contact_version(charlie_idx as UserID)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(version, get_version_bytes(1, 4));
|
||||||
|
|
||||||
|
// DAVID should NOT know ALICE yet because ALICE's threshold is 3, but David only has 2 shares.
|
||||||
|
let david_knows = network.uds[david_idx]
|
||||||
|
.get_all_announced_users()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let knows_alice = david_knows
|
||||||
|
.iter()
|
||||||
|
.any(|(u, _)| u.user_id == alice_idx as UserID);
|
||||||
|
|
||||||
|
assert!(!knows_alice, "David should not know Alice yet because Alice's threshold is 3 and David only receives 2 shares");
|
||||||
|
|
||||||
|
// Phase 2: Update ALICE's threshold to 2
|
||||||
|
network.uds[alice_idx]
|
||||||
|
.initialize_or_update(2, alice_idx as UserID, vec![alice_idx as u8; 32])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let version = network.uds[alice_idx].get_current_version().await.unwrap();
|
||||||
|
assert_eq!(version, get_version_bytes(2, 2));
|
||||||
|
|
||||||
|
// ALICE's new announcement with threshold 2 should propagate further.
|
||||||
|
step0_exchange_random::<InMemoryStore>(&network).await;
|
||||||
|
step1_verify_no_new_messages::<InMemoryStore>(&network).await;
|
||||||
|
|
||||||
|
let version = network.uds[david_idx]
|
||||||
|
.get_contact_version(charlie_idx as UserID)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(version, get_version_bytes(1, 5));
|
||||||
|
|
||||||
|
let version = network.uds[alice_idx].get_current_version().await.unwrap();
|
||||||
|
assert_eq!(version, get_version_bytes(2, 2));
|
||||||
|
|
||||||
|
// Now DAVID SHOULD know ALICE
|
||||||
|
let david_knows = network.uds[david_idx]
|
||||||
|
.get_all_announced_users()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let knows_alice_now = david_knows
|
||||||
|
.iter()
|
||||||
|
.any(|(u, _)| u.user_id == alice_idx as UserID);
|
||||||
|
assert!(
|
||||||
|
knows_alice_now,
|
||||||
|
"David should know Alice now because her threshold was updated to 2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_user_discovery_in_memory_store() {
|
async fn test_user_discovery_in_memory_store() {
|
||||||
let _ = pretty_env_logger::try_init();
|
let _ = pretty_env_logger::try_init();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct OtherPromotion {
|
||||||
pub public_key_verified_timestamp: Option<i64>,
|
pub public_key_verified_timestamp: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
||||||
pub struct AnnouncedUser {
|
pub struct AnnouncedUser {
|
||||||
pub user_id: UserID,
|
pub user_id: UserID,
|
||||||
pub public_key: Vec<u8>,
|
pub public_key: Vec<u8>,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue