mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-04-18 14:22:53 +00:00
working tests
This commit is contained in:
parent
87ba1c23e5
commit
51f51f768b
7 changed files with 576 additions and 194 deletions
127
rust/Cargo.lock
generated
127
rust/Cargo.lock
generated
|
|
@ -437,6 +437,19 @@ dependencies = [
|
|||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
|
||||
dependencies = [
|
||||
"humantime",
|
||||
"is-terminal",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
|
|
@ -786,6 +799,12 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
|
|
@ -819,6 +838,12 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
|
|
@ -964,6 +989,17 @@ dependencies = [
|
|||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi 0.5.2",
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
|
|
@ -1107,15 +1143,6 @@ version = "0.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.6"
|
||||
|
|
@ -1168,7 +1195,7 @@ version = "1.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.3.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -1335,6 +1362,16 @@ dependencies = [
|
|||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_env_logger"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.37"
|
||||
|
|
@ -1541,6 +1578,7 @@ dependencies = [
|
|||
"blahaj",
|
||||
"flutter_rust_bridge",
|
||||
"postcard",
|
||||
"pretty_env_logger",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"rand 0.10.1",
|
||||
|
|
@ -1549,7 +1587,6 @@ dependencies = [
|
|||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1675,15 +1712,6 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
|
@ -2011,6 +2039,15 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
|
|
@ -2031,15 +2068,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpool"
|
||||
version = "1.8.1"
|
||||
|
|
@ -2143,32 +2171,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
|
||||
dependencies = [
|
||||
"nu-ansi-term",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2228,12 +2230,6 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
|
|
@ -2396,6 +2392,15 @@ dependencies = [
|
|||
"wasite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
|
|
|
|||
|
|
@ -23,10 +23,12 @@ tracing = "0.1.44"
|
|||
serde = "1.0.228"
|
||||
prost = "0.14.1"
|
||||
rand = "0.10.1"
|
||||
tracing-subscriber = "0.3.23"
|
||||
blahaj = "0.6.0"
|
||||
postcard = { version = "1.1.3", features = ["alloc"] }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_env_logger = "0.5.0"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.14.1"
|
||||
|
|
|
|||
|
|
@ -2,17 +2,23 @@ mod error;
|
|||
pub mod stores;
|
||||
mod traits;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use blahaj::{Share, Sharks};
|
||||
use postcard::{from_bytes, to_allocvec};
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::user_discovery::error::{Result, UserDiscoveryError};
|
||||
use crate::user_discovery::traits::UserDiscoveryUtils;
|
||||
use crate::user_discovery::traits::{AnnouncedUser, OtherPromotion, UserDiscoveryUtils};
|
||||
use crate::user_discovery::user_discovery_message::{UserDiscoveryAnnouncement, UserDiscoveryPromotion};
|
||||
use crate::user_discovery::user_discovery_message::user_discovery_promotion::AnnouncementShareDecrypted;
|
||||
use crate::user_discovery::user_discovery_message::user_discovery_promotion::announcement_share_decrypted::SignedData;
|
||||
pub use traits::UserDiscoveryStore;
|
||||
|
||||
#[cfg(test)]
|
||||
static TRANSMITTED_NETWORK_BYTES: std::sync::OnceLock<std::sync::Mutex<usize>> =
|
||||
std::sync::OnceLock::new();
|
||||
|
||||
pub type UserID = i64;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/_.rs"));
|
||||
|
|
@ -31,6 +37,8 @@ struct UserDiscoveryConfig {
|
|||
public_id: u64,
|
||||
/// Verification shares
|
||||
verification_shares: Vec<Vec<u8>>,
|
||||
// The users' id:
|
||||
user_id: UserID,
|
||||
}
|
||||
|
||||
impl Default for UserDiscoveryConfig {
|
||||
|
|
@ -42,6 +50,7 @@ impl Default for UserDiscoveryConfig {
|
|||
promotion_version: 0,
|
||||
verification_shares: vec![],
|
||||
public_id: 0,
|
||||
user_id: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,6 +83,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
}
|
||||
Err(_) => UserDiscoveryConfig {
|
||||
threshold,
|
||||
user_id,
|
||||
..Default::default()
|
||||
},
|
||||
};
|
||||
|
|
@ -86,7 +96,7 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
public_key,
|
||||
};
|
||||
|
||||
let signature = self.utils.sign_data(signed_data.encode_to_vec())?;
|
||||
let signature = self.utils.sign_data(&signed_data.encode_to_vec())?;
|
||||
|
||||
let verification_shares = self.setup_announcements(&config, signed_data, signature)?;
|
||||
|
||||
|
|
@ -164,6 +174,13 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
.encode_to_vec())
|
||||
}
|
||||
|
||||
/// Returns all users discovery though the user discovery and there relations
|
||||
pub fn get_all_announced_users(
|
||||
&self,
|
||||
) -> Result<HashMap<AnnouncedUser, Vec<(UserID, Option<i64>)>>> {
|
||||
self.store.get_all_announced_users()
|
||||
}
|
||||
|
||||
/// Returns all new user discovery messages for the provided contact
|
||||
pub fn get_new_messages(
|
||||
&self,
|
||||
|
|
@ -206,9 +223,17 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
tracing::info!("New promotion message available for user {}", contact_id);
|
||||
let promoting_messages = self
|
||||
.store
|
||||
.get_promotions_after_version(received_version.promotion)?;
|
||||
.get_own_promotions_after_version(received_version.promotion)?;
|
||||
messages.extend_from_slice(&promoting_messages);
|
||||
}
|
||||
#[cfg(test)]
|
||||
{
|
||||
let mut count = TRANSMITTED_NETWORK_BYTES.get().unwrap().lock().unwrap();
|
||||
for message in &messages {
|
||||
*count += message.len();
|
||||
}
|
||||
}
|
||||
// static TRANSMITTED_NETWORK_BYTES: std::sync::OnceLock<usize> = std::sync::OnceLock::new();
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
|
|
@ -223,8 +248,9 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
promotion: 0,
|
||||
},
|
||||
};
|
||||
// tracing::debug!("{received_version:?} > {stored_version:?}");
|
||||
Ok(received_version.announcement > stored_version.announcement
|
||||
|| received_version.promotion < received_version.promotion)
|
||||
|| received_version.promotion > stored_version.promotion)
|
||||
}
|
||||
|
||||
pub(crate) fn get_contact_version(&self, contact_id: UserID) -> Result<Option<Vec<u8>>> {
|
||||
|
|
@ -246,10 +272,11 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
|
||||
if let Some(uda) = message.user_discovery_announcement {
|
||||
self.handle_user_discovery_announcement(contact_id, uda)?;
|
||||
}
|
||||
if let Some(udp) = message.user_discovery_promotion {
|
||||
self.handle
|
||||
tracing::info!("Got UDP from {contact_id}");
|
||||
} else if let Some(udp) = message.user_discovery_promotion {
|
||||
self.handle_user_discovery_promotion(contact_id, udp)?;
|
||||
} else {
|
||||
tracing::warn!("Got unknown user discovery messaging. Ignoring it.");
|
||||
continue;
|
||||
}
|
||||
|
||||
self.store
|
||||
|
|
@ -301,17 +328,26 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
)));
|
||||
}
|
||||
|
||||
if !self.utils.verify_pubkey_and_signature_from(
|
||||
contact_id,
|
||||
signed_data.encode_to_vec(),
|
||||
signed_data.public_key,
|
||||
asd.signature,
|
||||
)? {
|
||||
if !self
|
||||
.utils
|
||||
.verify_stored_pubkey(contact_id, &signed_data.public_key)?
|
||||
{
|
||||
return Err(UserDiscoveryError::MaliciousAnnouncementData(format!(
|
||||
"signature invalid or public key does not match with stored one",
|
||||
"public key does not match with stored one",
|
||||
)));
|
||||
}
|
||||
|
||||
if !self.utils.verify_signature(
|
||||
&signed_data.encode_to_vec(),
|
||||
&signed_data.public_key,
|
||||
&asd.signature,
|
||||
)? {
|
||||
return Err(UserDiscoveryError::MaliciousAnnouncementData(format!(
|
||||
"signature invalid",
|
||||
)));
|
||||
}
|
||||
|
||||
tracing::debug!("Increased promotion version id.");
|
||||
let mut config = self.get_config()?;
|
||||
config.promotion_version += 1;
|
||||
self.store.update_config(to_allocvec(&config)?)?;
|
||||
|
|
@ -326,50 +362,160 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
|
|||
public_id: signed_data.public_id,
|
||||
threshold: uda.threshold,
|
||||
announcement_share: uda.announcement_share,
|
||||
verification_state: None,
|
||||
public_key_verified_timestamp: None,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.store
|
||||
.push_promotion(config.promotion_version, message.encode_to_vec())?;
|
||||
self.store.push_own_promotion(
|
||||
contact_id,
|
||||
config.promotion_version,
|
||||
message.encode_to_vec(),
|
||||
)?;
|
||||
|
||||
let announced_user = AnnouncedUser {
|
||||
user_id: signed_data.user_id,
|
||||
public_key: signed_data.public_key,
|
||||
public_id: uda.public_id,
|
||||
};
|
||||
|
||||
tracing::debug!(
|
||||
"NEW PROMOTION: {} knows {}",
|
||||
contact_id,
|
||||
announced_user.user_id
|
||||
);
|
||||
// User is known, so add him to thr users relations
|
||||
self.store.push_new_user_relation(
|
||||
contact_id,
|
||||
announced_user,
|
||||
None, // This flag mus be handled by the applications as this comes from an announcement.
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(UserDiscoveryError::ShamirsSecret(err.to_string()));
|
||||
}
|
||||
Err(err) => Err(UserDiscoveryError::ShamirsSecret(err.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_user_discovery_promotion(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
uda: UserDiscoveryPromotion,
|
||||
) {
|
||||
from_contact_id: UserID,
|
||||
udp: UserDiscoveryPromotion,
|
||||
) -> Result<()> {
|
||||
tracing::debug!("Received a new UDP with public_id = {}.", &udp.public_id);
|
||||
|
||||
// contact_id
|
||||
// uda.promotion_id
|
||||
// uda.public_id
|
||||
// uda.threshold
|
||||
// uda.announcement_share
|
||||
// uda.verification_state
|
||||
self.store.store_other_promotion(OtherPromotion {
|
||||
from_contact_id,
|
||||
promotion_id: udp.promotion_id,
|
||||
threshold: udp.threshold as u8,
|
||||
public_id: udp.public_id,
|
||||
announcement_share: udp.announcement_share,
|
||||
public_key_verified_timestamp: udp.public_key_verified_timestamp,
|
||||
})?;
|
||||
|
||||
// store this into the received_promotion_table
|
||||
// check if the threshold is reached
|
||||
// in case thr threshold is reached -> CALL STORE -> NEW USER
|
||||
// otherwise do nothing
|
||||
if let Some(contact) = self.store.get_announced_user_by_public_id(udp.public_id)? {
|
||||
tracing::debug!(
|
||||
"NEW PROMOTION 2: {} knows {}",
|
||||
from_contact_id,
|
||||
contact.user_id
|
||||
);
|
||||
// The user is already known, just propagate the relation ship
|
||||
self.store.push_new_user_relation(
|
||||
from_contact_id,
|
||||
contact,
|
||||
udp.public_key_verified_timestamp,
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let promotions = self.store.get_other_promotions_by_public_id(udp.public_id);
|
||||
|
||||
if promotions.len() < udp.threshold as usize {
|
||||
tracing::debug!(
|
||||
"Not enough shares ({} < {}) to decrypt announcement. Waiting for next share.",
|
||||
promotions.len(),
|
||||
udp.threshold
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
tracing::debug!("Enough shares decrypting announcement.");
|
||||
|
||||
let shares: Vec<_> = promotions
|
||||
.iter()
|
||||
.map(|x| x.announcement_share.to_owned())
|
||||
.filter_map(|x| Share::try_from(x.as_slice()).ok())
|
||||
.collect();
|
||||
|
||||
match Sharks(udp.threshold as u8).recover(&shares) {
|
||||
Ok(secret) => {
|
||||
tracing::debug!("Could decrypt announcement.");
|
||||
let asd = AnnouncementShareDecrypted::decode(secret.as_slice())?;
|
||||
if let Some(signed_data) = asd.signed_data {
|
||||
if udp.public_id != signed_data.public_id {
|
||||
tracing::error!(
|
||||
"Mismatch of the announced public id and the signed public id "
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !self.utils.verify_signature(
|
||||
&signed_data.encode_to_vec(),
|
||||
&signed_data.public_key,
|
||||
&asd.signature,
|
||||
)? {
|
||||
return Err(UserDiscoveryError::MaliciousAnnouncementData(format!(
|
||||
"signature is invalid",
|
||||
)));
|
||||
}
|
||||
|
||||
tracing::debug!("Announcement valid.");
|
||||
|
||||
let announced_user = AnnouncedUser {
|
||||
user_id: signed_data.user_id,
|
||||
public_key: signed_data.public_key,
|
||||
public_id: udp.public_id,
|
||||
};
|
||||
|
||||
let user_id = self.get_config()?.user_id;
|
||||
for promotion in promotions {
|
||||
// Do not store the announcement of the users itself.
|
||||
// Or in case the promotion promotes myself
|
||||
if promotion.from_contact_id == announced_user.user_id
|
||||
|| announced_user.user_id == user_id
|
||||
{
|
||||
continue;
|
||||
}
|
||||
tracing::debug!(
|
||||
"NEW PROMOTION: {} knows {}",
|
||||
promotion.from_contact_id,
|
||||
announced_user.user_id
|
||||
);
|
||||
self.store.push_new_user_relation(
|
||||
promotion.from_contact_id,
|
||||
announced_user.clone(),
|
||||
promotion.public_key_verified_timestamp,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => Err(UserDiscoveryError::ShamirsSecret(err.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::vec;
|
||||
|
||||
use crate::user_discovery::stores::InMemoryStore;
|
||||
use crate::user_discovery::traits::tests::TestingUtils;
|
||||
use crate::user_discovery::{UserDiscovery, UserDiscoveryVersion, UserID};
|
||||
use crate::user_discovery::{
|
||||
UserDiscovery, UserDiscoveryVersion, UserID, TRANSMITTED_NETWORK_BYTES,
|
||||
};
|
||||
use prost::Message;
|
||||
|
||||
fn get_version_bytes(announcement: u32, promotion: u32) -> Vec<u8> {
|
||||
|
|
@ -380,16 +526,11 @@ mod tests {
|
|||
.encode_to_vec()
|
||||
}
|
||||
|
||||
fn zero() -> Vec<u8> {
|
||||
get_version_bytes(0, 0)
|
||||
}
|
||||
|
||||
fn get_ud(user_id: UserID, friends: &[UserID]) -> UserDiscovery<InMemoryStore, TestingUtils> {
|
||||
fn get_ud(user_id: usize) -> UserDiscovery<InMemoryStore, TestingUtils> {
|
||||
let store = InMemoryStore::default();
|
||||
store.set_friends(friends.iter().copied().collect());
|
||||
let ud = UserDiscovery::new(store.to_owned(), TestingUtils::default()).unwrap();
|
||||
|
||||
ud.initialize_or_update(3, user_id, vec![user_id as u8; 32])
|
||||
ud.initialize_or_update(2, user_id as UserID, vec![user_id as u8; 32])
|
||||
.unwrap();
|
||||
|
||||
let version = ud.get_current_version().unwrap();
|
||||
|
|
@ -398,74 +539,236 @@ mod tests {
|
|||
ud
|
||||
}
|
||||
|
||||
fn init() {
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(tracing::Level::DEBUG)
|
||||
.init();
|
||||
fn assert_new_messages(
|
||||
from: (usize, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
to: (usize, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
has_new_messages: bool,
|
||||
) {
|
||||
// From sends a message with his current version to To
|
||||
let to_received_version = &from.1.get_current_version().unwrap();
|
||||
assert_eq!(
|
||||
to.1.should_request_new_messages(from.0 as UserID, to_received_version)
|
||||
.unwrap(),
|
||||
has_new_messages
|
||||
);
|
||||
}
|
||||
|
||||
fn request_and_handle_messages(
|
||||
from: (UserID, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
to: (UserID, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
from: (usize, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
to: (usize, &UserDiscovery<InMemoryStore, TestingUtils>),
|
||||
messages_count: usize,
|
||||
) {
|
||||
// From sends a message with his current version to To
|
||||
let to_received_version = &from.1.get_current_version().unwrap();
|
||||
assert_eq!(
|
||||
to.1.should_request_new_messages(from.0, to_received_version)
|
||||
to.1.should_request_new_messages(from.0 as UserID, to_received_version)
|
||||
.unwrap(),
|
||||
true
|
||||
);
|
||||
|
||||
// As To has a older version stored he sends a request to From: Give me all messages since version.
|
||||
let from_request_version_from_to =
|
||||
to.1.get_contact_version(from.0).unwrap().unwrap_or(zero());
|
||||
to.1.get_contact_version(from.0 as UserID)
|
||||
.unwrap()
|
||||
.unwrap_or(get_version_bytes(0, 0));
|
||||
|
||||
let new_messages = from
|
||||
.1
|
||||
.get_new_messages(to.0, &from_request_version_from_to)
|
||||
.get_new_messages(to.0 as UserID, &from_request_version_from_to)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(new_messages.len(), messages_count);
|
||||
assert!(new_messages.len() <= messages_count);
|
||||
|
||||
to.1.handle_user_discovery_messages(from.0, new_messages)
|
||||
to.1.handle_user_discovery_messages(from.0 as UserID, new_messages)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
to.1.should_request_new_messages(from.0, &from.1.get_current_version().unwrap())
|
||||
.unwrap(),
|
||||
to.1.should_request_new_messages(
|
||||
from.0 as UserID,
|
||||
&from.1.get_current_version().unwrap()
|
||||
)
|
||||
.unwrap(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
const ALICE: usize = 0;
|
||||
const BOB: usize = 1;
|
||||
const CHARLIE: usize = 2;
|
||||
const DAVID: usize = 3;
|
||||
const FRANK: usize = 4;
|
||||
const TEST_USER_COUNT: usize = 5;
|
||||
struct TestUsers {
|
||||
names: [&'static str; TEST_USER_COUNT],
|
||||
friends: [Vec<usize>; TEST_USER_COUNT],
|
||||
uds: Vec<UserDiscovery<InMemoryStore, TestingUtils>>,
|
||||
}
|
||||
|
||||
impl TestUsers {
|
||||
fn get() -> Self {
|
||||
let names = ["ALICE", "BOB", "CHARLIE", "DAVID", "FRANK"];
|
||||
let mut uds = vec![];
|
||||
for index in 0..names.len() {
|
||||
uds.push(get_ud(index));
|
||||
}
|
||||
let friends = [
|
||||
vec![BOB, CHARLIE],
|
||||
vec![ALICE, CHARLIE, DAVID],
|
||||
vec![ALICE, BOB, DAVID, FRANK],
|
||||
vec![BOB, CHARLIE],
|
||||
vec![CHARLIE],
|
||||
];
|
||||
Self {
|
||||
names,
|
||||
uds,
|
||||
friends,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_initialize_user_discovery() {
|
||||
init();
|
||||
pretty_env_logger::init();
|
||||
let counter = TRANSMITTED_NETWORK_BYTES.get_or_init(|| std::sync::Mutex::new(0));
|
||||
|
||||
const ALICE: UserID = 0;
|
||||
const BOB: UserID = 1;
|
||||
const CHARLIE: UserID = 2;
|
||||
const DAVID: UserID = 3;
|
||||
const FRANK: UserID = 4;
|
||||
let users = TestUsers::get();
|
||||
|
||||
let alice_ud = get_ud(ALICE, &[BOB, CHARLIE]);
|
||||
let bob_ud = get_ud(BOB, &[ALICE, CHARLIE, DAVID]);
|
||||
let charlie_ud = get_ud(CHARLIE, &[ALICE, BOB, DAVID, FRANK]);
|
||||
let david_ud = get_ud(DAVID, &[BOB, CHARLIE]);
|
||||
let frank_ud = get_ud(FRANK, &[CHARLIE]);
|
||||
fn to_all_friends(from: usize, message_count: usize, users: &TestUsers) {
|
||||
for friend in &users.friends[from] {
|
||||
tracing::debug!("From {} to {}", users.names[from], users.names[*friend]);
|
||||
|
||||
{
|
||||
// Alice send UDA to Bob and Charlie
|
||||
request_and_handle_messages((ALICE, &alice_ud), (BOB, &bob_ud), 1);
|
||||
request_and_handle_messages((ALICE, &alice_ud), (CHARLIE, &charlie_ud), 1);
|
||||
if message_count == 0 {
|
||||
assert_new_messages(
|
||||
(from, &users.uds[from]),
|
||||
(*friend, &users.uds[*friend]),
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
request_and_handle_messages(
|
||||
(from, &users.uds[from]),
|
||||
(*friend, &users.uds[*friend]),
|
||||
message_count,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// This now contains Bob's own announcement in addition this now also contains the promotion from Alice
|
||||
request_and_handle_messages((BOB, &bob_ud), (DAVID, &david_ud), 2);
|
||||
request_and_handle_messages((BOB, &bob_ud), (CHARLIE, &charlie_ud), 2);
|
||||
let message_flows = [
|
||||
// ALICE: own announcement sending to BOB and CHARLIE
|
||||
(ALICE, 1),
|
||||
// BOB: own announcement + promotion for ALICE
|
||||
(BOB, 2),
|
||||
// BOBs version should not have any new messages for his friends
|
||||
(BOB, 0),
|
||||
// ALICE: promotion for BOB
|
||||
(ALICE, 1),
|
||||
// CHARLIE: own announcement + promotion for ALICE, BOB
|
||||
(CHARLIE, 3),
|
||||
// DAVID: own announcement + promotion for BOB, CHARLIE
|
||||
(DAVID, 3),
|
||||
// BOB: promotion for CHARLIE, DAVID
|
||||
(BOB, 2),
|
||||
// CHARLIE: promotion for DAVID
|
||||
(CHARLIE, 1),
|
||||
// FRANK: own announcement + promotion for CHARLIE
|
||||
(FRANK, 2),
|
||||
// CHARLIE: promotion for FRANK
|
||||
(CHARLIE, 1),
|
||||
// ALICE: promotion for CHARLIE
|
||||
(ALICE, 1),
|
||||
];
|
||||
|
||||
for (i, (from, count)) in message_flows.into_iter().enumerate() {
|
||||
tracing::debug!("MESSAGE FLOW: {i}");
|
||||
to_all_friends(from, count, &users);
|
||||
}
|
||||
|
||||
todo!();
|
||||
tracing::debug!("Now all users should have the newest version.");
|
||||
|
||||
for from in 0..TEST_USER_COUNT {
|
||||
for to in &users.friends[from] {
|
||||
tracing::debug!(
|
||||
"Does {} has open messages for {}?",
|
||||
&users.names[from],
|
||||
&users.names[*to]
|
||||
);
|
||||
assert_new_messages((from, &users.uds[from]), (*to, &users.uds[*to]), false);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!("Test if all exchanges where successful.");
|
||||
|
||||
let announced_users_expected = [
|
||||
// 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,
|
||||
vec![
|
||||
(BOB, vec![CHARLIE]), // ALICE knows Bob and that CHARLIE is connected with BOB
|
||||
(CHARLIE, vec![BOB]), // ALICE knows CHARLIE and that BOB is connected with CHARLIE
|
||||
(DAVID, vec![BOB, CHARLIE]), // ALICE knows DAVID and that BOB and CHARLIE are connected with DAVID
|
||||
],
|
||||
),
|
||||
(
|
||||
BOB,
|
||||
vec![
|
||||
(ALICE, vec![CHARLIE]),
|
||||
(CHARLIE, vec![ALICE, DAVID]),
|
||||
(DAVID, vec![CHARLIE]),
|
||||
],
|
||||
),
|
||||
(
|
||||
CHARLIE,
|
||||
vec![
|
||||
(ALICE, vec![BOB]),
|
||||
(BOB, vec![ALICE, DAVID]),
|
||||
(DAVID, vec![BOB]),
|
||||
(FRANK, vec![]),
|
||||
],
|
||||
),
|
||||
(
|
||||
DAVID,
|
||||
vec![
|
||||
(ALICE, vec![BOB, CHARLIE]),
|
||||
(BOB, vec![CHARLIE]),
|
||||
(CHARLIE, vec![BOB]),
|
||||
],
|
||||
),
|
||||
(FRANK, vec![(CHARLIE, vec![])]),
|
||||
];
|
||||
|
||||
for (user, announcements) in announced_users_expected {
|
||||
let announced_users2 = users.uds[user].get_all_announced_users().unwrap();
|
||||
let mut announced_users = HashMap::new();
|
||||
for a in announced_users2 {
|
||||
announced_users.insert(a.0.user_id, a.1.iter().map(|x| x.0).collect::<Vec<_>>());
|
||||
}
|
||||
tracing::debug!("{} knows now: {}", users.names[user], announced_users.len());
|
||||
assert_eq!(announced_users.len(), announcements.len());
|
||||
for (contact_id, announced_users_expected) in announcements {
|
||||
let announced_users = announced_users.get(&(contact_id as i64)).unwrap();
|
||||
tracing::debug!(
|
||||
"{} knows now that {} has the following friends: {}",
|
||||
users.names[user],
|
||||
users.names[contact_id],
|
||||
announced_users
|
||||
.iter()
|
||||
.map(|x| users.names[*x as usize])
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
let announced_users: HashSet<i64> = announced_users.iter().cloned().collect();
|
||||
let announced_users_expected: HashSet<i64> = announced_users_expected
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|x| x as i64)
|
||||
.collect();
|
||||
assert_eq!(announced_users, announced_users_expected);
|
||||
}
|
||||
}
|
||||
|
||||
let count = TRANSMITTED_NETWORK_BYTES.get().unwrap().lock().unwrap();
|
||||
|
||||
tracing::info!("Transmitted a total of {} bytes.", *count);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::user_discovery::error::UserDiscoveryError;
|
||||
use crate::user_discovery::traits::UserDiscoveryStore;
|
||||
use crate::user_discovery::error::{Result, UserDiscoveryError};
|
||||
use crate::user_discovery::traits::{AnnouncedUser, OtherPromotion, UserDiscoveryStore};
|
||||
use crate::user_discovery::UserID;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -10,8 +10,9 @@ pub(crate) struct Storage {
|
|||
unused_shares: Vec<Vec<u8>>,
|
||||
used_shares: HashMap<UserID, Vec<u8>>,
|
||||
contact_versions: HashMap<UserID, Vec<u8>>,
|
||||
friends: HashSet<UserID>,
|
||||
promotions: Vec<Vec<u8>>,
|
||||
other_promotions: Vec<OtherPromotion>,
|
||||
announced_users: HashMap<AnnouncedUser, Vec<(UserID, Option<i64>)>>,
|
||||
own_promotions: Vec<(UserID, Vec<u8>)>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
|
|
@ -23,33 +24,27 @@ impl InMemoryStore {
|
|||
fn storage(&self) -> std::sync::MutexGuard<'_, Storage> {
|
||||
self.storage.lock().unwrap()
|
||||
}
|
||||
pub fn set_friends(&self, friends: HashSet<UserID>) {
|
||||
self.storage().friends = friends;
|
||||
}
|
||||
}
|
||||
|
||||
impl UserDiscoveryStore for InMemoryStore {
|
||||
fn get_config(&self) -> crate::user_discovery::error::Result<Vec<u8>> {
|
||||
fn get_config(&self) -> Result<Vec<u8>> {
|
||||
if let Some(storage) = self.storage().config.clone() {
|
||||
return Ok(storage);
|
||||
}
|
||||
Err(UserDiscoveryError::NotInitialized)
|
||||
}
|
||||
|
||||
fn update_config(&self, update: Vec<u8>) -> crate::user_discovery::error::Result<()> {
|
||||
fn update_config(&self, update: Vec<u8>) -> Result<()> {
|
||||
self.storage().config = Some(update);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_shares(&self, shares: Vec<Vec<u8>>) -> crate::user_discovery::error::Result<()> {
|
||||
fn set_shares(&self, shares: Vec<Vec<u8>>) -> Result<()> {
|
||||
self.storage().unused_shares = shares;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_share_for_contact(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
) -> crate::user_discovery::error::Result<Vec<u8>> {
|
||||
fn get_share_for_contact(&self, contact_id: UserID) -> Result<Vec<u8>> {
|
||||
let mut storage = self.storage();
|
||||
if let Some(share) = storage.used_shares.get(&contact_id) {
|
||||
return Ok(share.to_vec());
|
||||
|
|
@ -61,42 +56,82 @@ impl UserDiscoveryStore for InMemoryStore {
|
|||
Err(UserDiscoveryError::NoSharesLeft)
|
||||
}
|
||||
|
||||
fn get_contact_version(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
) -> crate::user_discovery::error::Result<Option<Vec<u8>>> {
|
||||
fn get_contact_version(&self, contact_id: UserID) -> Result<Option<Vec<u8>>> {
|
||||
Ok(self.storage().contact_versions.get(&contact_id).cloned())
|
||||
}
|
||||
|
||||
fn set_contact_version(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
update: Vec<u8>,
|
||||
) -> crate::user_discovery::error::Result<()> {
|
||||
fn set_contact_version(&self, contact_id: UserID, update: Vec<u8>) -> Result<()> {
|
||||
self.storage().contact_versions.insert(contact_id, update);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_promotion(
|
||||
fn push_own_promotion(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
version: u32,
|
||||
promotion: Vec<u8>,
|
||||
) -> crate::user_discovery::error::Result<()> {
|
||||
) -> Result<()> {
|
||||
let mut storage = self.storage();
|
||||
// println!("{} != {}", version, storage.promotions.len());
|
||||
if version as usize != storage.promotions.len() + 1 {
|
||||
if version as usize != storage.own_promotions.len() + 1 {
|
||||
return Err(UserDiscoveryError::PushedInvalidVersion);
|
||||
}
|
||||
storage.promotions.push(promotion);
|
||||
storage.own_promotions.push((contact_id, promotion));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_promotions_after_version(
|
||||
&self,
|
||||
version: u32,
|
||||
) -> crate::user_discovery::error::Result<Vec<Vec<u8>>> {
|
||||
fn get_own_promotions_after_version(&self, version: u32) -> Result<Vec<Vec<u8>>> {
|
||||
let storage = self.storage();
|
||||
let elements = storage.promotions[(version as usize)..].to_vec();
|
||||
let elements = storage.own_promotions[(version as usize)..]
|
||||
.into_iter()
|
||||
.map(|(_, promotion)| promotion.to_owned())
|
||||
.collect();
|
||||
Ok(elements)
|
||||
}
|
||||
|
||||
fn store_other_promotion(&self, promotion: OtherPromotion) -> Result<()> {
|
||||
self.storage().other_promotions.push(promotion);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_other_promotions_by_public_id(&self, public_id: u64) -> Vec<OtherPromotion> {
|
||||
self.storage()
|
||||
.other_promotions
|
||||
.iter()
|
||||
.filter(|other| other.public_id == public_id)
|
||||
.map(OtherPromotion::to_owned)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_announced_user_by_public_id(&self, public_id: u64) -> Result<Option<AnnouncedUser>> {
|
||||
Ok(self
|
||||
.storage()
|
||||
.announced_users
|
||||
.iter()
|
||||
.find(|(u, _)| u.public_id == public_id)
|
||||
.map(|u| u.0.to_owned()))
|
||||
}
|
||||
|
||||
fn get_all_announced_users(
|
||||
&self,
|
||||
) -> Result<HashMap<AnnouncedUser, Vec<(UserID, Option<i64>)>>> {
|
||||
Ok(self.storage().announced_users.clone())
|
||||
}
|
||||
|
||||
fn push_new_user_relation(
|
||||
&self,
|
||||
from_contact_id: UserID,
|
||||
announced_user: AnnouncedUser,
|
||||
public_key_verified_timestamp: Option<i64>,
|
||||
) -> Result<()> {
|
||||
let mut storage = self.storage();
|
||||
let entry = storage
|
||||
.announced_users
|
||||
.entry(announced_user.clone())
|
||||
.or_insert(vec![]);
|
||||
if announced_user.user_id != from_contact_id {
|
||||
entry.push((from_contact_id, public_key_verified_timestamp));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::user_discovery::error::Result;
|
||||
use crate::user_discovery::UserID;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OtherPromotion {
|
||||
pub promotion_id: u32,
|
||||
pub public_id: u64,
|
||||
pub from_contact_id: UserID,
|
||||
pub threshold: u8,
|
||||
pub announcement_share: Vec<u8>,
|
||||
pub public_key_verified_timestamp: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||
pub struct AnnouncedUser {
|
||||
pub user_id: UserID,
|
||||
pub public_key: Vec<u8>,
|
||||
pub public_id: u64,
|
||||
}
|
||||
|
||||
pub trait UserDiscoveryStore {
|
||||
fn get_config(&self) -> Result<Vec<u8>>;
|
||||
fn update_config(&self, update: Vec<u8>) -> Result<()>;
|
||||
|
|
@ -8,22 +27,38 @@ pub trait UserDiscoveryStore {
|
|||
|
||||
fn get_share_for_contact(&self, contact_id: UserID) -> Result<Vec<u8>>;
|
||||
|
||||
fn push_promotion(&self, version: u32, promotion: Vec<u8>) -> Result<()>;
|
||||
fn get_promotions_after_version(&self, version: u32) -> Result<Vec<Vec<u8>>>;
|
||||
fn push_own_promotion(
|
||||
&self,
|
||||
contact_id: UserID,
|
||||
version: u32,
|
||||
promotion: Vec<u8>,
|
||||
) -> Result<()>;
|
||||
|
||||
fn get_own_promotions_after_version(&self, version: u32) -> Result<Vec<Vec<u8>>>;
|
||||
|
||||
fn store_other_promotion(&self, promotion: OtherPromotion) -> Result<()>;
|
||||
fn get_other_promotions_by_public_id(&self, public_id: u64) -> Vec<OtherPromotion>;
|
||||
|
||||
fn get_announced_user_by_public_id(&self, public_id: u64) -> Result<Option<AnnouncedUser>>;
|
||||
|
||||
fn push_new_user_relation(
|
||||
&self,
|
||||
from_contact_id: UserID,
|
||||
announced_user: AnnouncedUser,
|
||||
public_key_verified_timestamp: Option<i64>,
|
||||
) -> Result<()>;
|
||||
|
||||
fn get_all_announced_users(&self)
|
||||
-> Result<HashMap<AnnouncedUser, Vec<(UserID, Option<i64>)>>>;
|
||||
|
||||
fn get_contact_version(&self, contact_id: UserID) -> Result<Option<Vec<u8>>>;
|
||||
fn set_contact_version(&self, contact_id: UserID, update: Vec<u8>) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait UserDiscoveryUtils {
|
||||
fn sign_data(&self, input_data: Vec<u8>) -> Result<Vec<u8>>;
|
||||
fn verify_pubkey_and_signature_from(
|
||||
&self,
|
||||
from_contact_id: UserID,
|
||||
data: Vec<u8>,
|
||||
pubkey: Vec<u8>,
|
||||
signature: Vec<u8>,
|
||||
) -> Result<bool>;
|
||||
fn sign_data(&self, input_data: &[u8]) -> Result<Vec<u8>>;
|
||||
fn verify_signature(&self, input_data: &[u8], pubkey: &[u8], signature: &[u8]) -> Result<bool>;
|
||||
fn verify_stored_pubkey(&self, from_contact_id: UserID, pubkey: &[u8]) -> Result<bool>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -33,16 +68,23 @@ pub(crate) mod tests {
|
|||
#[derive(Default)]
|
||||
pub(crate) struct TestingUtils {}
|
||||
impl UserDiscoveryUtils for TestingUtils {
|
||||
fn sign_data(&self, _input_data: Vec<u8>) -> crate::user_discovery::error::Result<Vec<u8>> {
|
||||
fn sign_data(&self, _input_data: &[u8]) -> crate::user_discovery::error::Result<Vec<u8>> {
|
||||
Ok(vec![0; 64])
|
||||
}
|
||||
|
||||
fn verify_pubkey_and_signature_from(
|
||||
fn verify_signature(
|
||||
&self,
|
||||
from_contact_id: crate::user_discovery::UserID,
|
||||
data: Vec<u8>,
|
||||
pubkey: Vec<u8>,
|
||||
signature: Vec<u8>,
|
||||
_data: &[u8],
|
||||
_pubkey: &[u8],
|
||||
_signature: &[u8],
|
||||
) -> crate::user_discovery::error::Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn verify_stored_pubkey(
|
||||
&self,
|
||||
_from_contact_id: crate::user_discovery::UserID,
|
||||
_pubkey: &[u8],
|
||||
) -> crate::user_discovery::error::Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ message UserDiscoveryMessage {
|
|||
uint64 public_id = 1;
|
||||
uint32 threshold = 2;
|
||||
bytes announcement_share = 4;
|
||||
repeated bytes verification_shares = 5;
|
||||
repeated bytes verification_shares = 6;
|
||||
}
|
||||
|
||||
message UserDiscoveryPromotion {
|
||||
|
|
@ -26,7 +26,7 @@ message UserDiscoveryMessage {
|
|||
uint32 threshold = 3;
|
||||
bytes announcement_share = 5;
|
||||
|
||||
optional VerificationState verification_state = 6;
|
||||
optional int64 public_key_verified_timestamp = 6;
|
||||
|
||||
message AnnouncementShareDecrypted {
|
||||
message SignedData {
|
||||
|
|
@ -38,11 +38,6 @@ message UserDiscoveryMessage {
|
|||
bytes signature = 2;
|
||||
}
|
||||
|
||||
message VerificationState {
|
||||
int64 timestamp = 1;
|
||||
bytes signature = 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message UserDiscoveryRecall {
|
||||
|
|
|
|||
Loading…
Reference in a new issue