From 3345a2a297c68d22c32191f36da2f58ab13869c7 Mon Sep 17 00:00:00 2001 From: otsmr Date: Sun, 2 Aug 2026 14:40:44 +0200 Subject: [PATCH] fix multiple bugs in the POC --- rust/Cargo.lock | 10 +- rust/Cargo.toml | 4 +- rust/src/backup/backup_passwordless/mod.rs | 1 - rust/src/backup/backup_passwordless/types.rs | 84 ------------- rust/src/backup/mod.rs | 1 - rust/src/bridge/wrapper/user_discovery.rs | 116 ++++++++++-------- .../migrations/0002_create_signal_tables.sql | 3 +- rust/src/signal/engine.rs | 39 ++++-- rust/src/signal/store.rs | 50 +++----- rust/src/user_discovery/README.md | 74 ----------- rust/tests/pqxdh_tests.rs | 18 ++- 11 files changed, 133 insertions(+), 267 deletions(-) delete mode 100644 rust/src/backup/backup_passwordless/mod.rs delete mode 100644 rust/src/backup/backup_passwordless/types.rs delete mode 100644 rust/src/user_discovery/README.md diff --git a/rust/Cargo.lock b/rust/Cargo.lock index e122d59b..7b9f3537 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1801,7 +1801,7 @@ dependencies = [ [[package]] name = "libsignal-core" version = "0.1.0" -source = "git+https://github.com/signalapp/libsignal#622d0d52471f3cc9215fe4e9abaac1970018f79c" +source = "git+https://github.com/signalapp/libsignal?rev=44a6dd8fc9f9d6903b32842b80b3894a75678418#44a6dd8fc9f9d6903b32842b80b3894a75678418" dependencies = [ "curve25519-dalek", "derive_more", @@ -1819,8 +1819,8 @@ dependencies = [ [[package]] name = "libsignal-debug" -version = "0.99.3" -source = "git+https://github.com/signalapp/libsignal#622d0d52471f3cc9215fe4e9abaac1970018f79c" +version = "0.97.5" +source = "git+https://github.com/signalapp/libsignal?rev=44a6dd8fc9f9d6903b32842b80b3894a75678418#44a6dd8fc9f9d6903b32842b80b3894a75678418" dependencies = [ "cfg-if", ] @@ -1828,7 +1828,7 @@ dependencies = [ [[package]] name = "libsignal-protocol" version = "0.1.0" -source = "git+https://github.com/signalapp/libsignal#622d0d52471f3cc9215fe4e9abaac1970018f79c" +source = "git+https://github.com/signalapp/libsignal?rev=44a6dd8fc9f9d6903b32842b80b3894a75678418#44a6dd8fc9f9d6903b32842b80b3894a75678418" dependencies = [ "aes 0.9.2", "aes-gcm-siv", @@ -2776,7 +2776,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-crypto" version = "0.1.0" -source = "git+https://github.com/signalapp/libsignal#622d0d52471f3cc9215fe4e9abaac1970018f79c" +source = "git+https://github.com/signalapp/libsignal?rev=44a6dd8fc9f9d6903b32842b80b3894a75678418#44a6dd8fc9f9d6903b32842b80b3894a75678418" dependencies = [ "aes 0.9.2", "cbc", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 63b33bde..76032fd2 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -21,7 +21,7 @@ sqlx = { version = "0.9.0-alpha.1", default-features = false, features = [ libsqlite3-sys = { version = "0.35.0", features = [ "bundled-sqlcipher-vendored-openssl", ] } -tokio = { version = "1.44", features = ["full"] } +tokio = { version = "1.44", features = ["full", "macros"] } tracing = "0.1.44" prost = "0.14.1" blahaj = "0.6.0" @@ -43,7 +43,7 @@ chrono = { version = "0.4", features = ["serde"] } zip = { version = "2.2.2", default-features = false, features = ["deflate"] } scrypt = { version = "0.12", default-features = false } walkdir = "2.5.0" -libsignal-protocol = { git = "https://github.com/signalapp/libsignal", version = "0.1.0" } +libsignal-protocol = { git = "https://github.com/signalapp/libsignal", version = "0.1.0", rev = "44a6dd8fc9f9d6903b32842b80b3894a75678418" } rand08 = { version = "0.8.5", package = "rand" } rand = "0.9.4" async-trait = "0.1.91" diff --git a/rust/src/backup/backup_passwordless/mod.rs b/rust/src/backup/backup_passwordless/mod.rs deleted file mode 100644 index 6f8b3dee..00000000 --- a/rust/src/backup/backup_passwordless/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod types; diff --git a/rust/src/backup/backup_passwordless/types.rs b/rust/src/backup/backup_passwordless/types.rs deleted file mode 100644 index 8cba833c..00000000 --- a/rust/src/backup/backup_passwordless/types.rs +++ /dev/null @@ -1,84 +0,0 @@ -#![allow(dead_code)] -use serde::{Deserialize, Serialize}; - -/// Send from the person who tries to recover their account. -/// This can be done via a link, which will then be opened in the app of the contact. -/// The contact then has to manually select from which user he got the request. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct RecoveryRequest { - pub temp_id: i64, - pub public_key: Vec, -} - -/// Used as envelope for TrustedFriendShare and RecoveryData -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct EncryptedEnvelope { - pub encrypted_data: Vec, - pub iv: Vec, - pub mac: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct User { - pub user_id: i64, - pub display_name: String, - pub avatar: Vec, -} - -/// Send from the trusted friend. -/// This is encrypted with the received public key. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct TrustedFriendShare { - /// This allows to display the user which user has send him his recovery data. - pub trusted_friend: User, - /// This allows to display the userdata, showing that he is recovering the correct person. - pub share_user: User, - /// The minimum threshold required to decrypt the shares. - pub threshold: i32, - /// The actual share which will become: SecretSharedData - pub share: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct SecondFactorPin { - /// Required to try the PIN to get the share from the server. - /// This prevents that someone else can lock the pin, as the server only - /// allows 3 tries then after 1 day again 3 tries until the key is deleted. - pub unlock_token: Vec, - /// This never is send to the server but used to hash the pin before sending it to the server. - /// This prevents that the server every knows the short 4-digit PIN. - pub pin_seed: Vec, - /// The recovery data in case a second factor was used - /// The decryption key is loaded from the server either using the PIN or the MAIL - pub recovery_data_encrypted: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct SecondFactorMail { - /// The users selected mail which will be send to the server - /// To this mail the encryption key for the recovery_data is send - pub mail: String, - /// Required to try the PIN to get the share from the server. - /// This prevents that someone else can lock the pin, as the server only - /// allows 3 tries then after 1 day again 3 tries until the key is deleted. - pub unlock_token: Vec, - /// The recovery data in case a second factor was used - /// The decryption key is loaded from the server either using the PIN or the MAIL - pub recovery_data_encrypted: Vec, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum SecretSharedData { - None(RecoveryData), - Mail(SecondFactorMail), - Pin(SecondFactorPin), -} - -/// The data which is recovered at the end. -/// The backup_master_key allows to recover the actual backup uploaded in the background to the server. -/// In case the backup is not available any more the user can use its user_id and his private_key to register as a new user. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct RecoveryData { - pub user_id: i64, - pub master_key: Vec, -} diff --git a/rust/src/backup/mod.rs b/rust/src/backup/mod.rs index 512a160c..7d3cd538 100644 --- a/rust/src/backup/mod.rs +++ b/rust/src/backup/mod.rs @@ -1,3 +1,2 @@ pub(crate) mod backup_archive; pub(crate) mod backup_identity; -pub(crate) mod backup_passwordless; diff --git a/rust/src/bridge/wrapper/user_discovery.rs b/rust/src/bridge/wrapper/user_discovery.rs index c19ec41f..53de44d2 100644 --- a/rust/src/bridge/wrapper/user_discovery.rs +++ b/rust/src/bridge/wrapper/user_discovery.rs @@ -12,29 +12,33 @@ impl FlutterUserDiscovery { public_key: Vec, share_promotion: bool, ) -> Result<()> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - tracing::info!("Rust bridge: initialize_or_update started"); - let twonly = get_twonly_flutter()?; - tracing::info!("Rust bridge: getting user_discovery lock"); - let user_discovery = twonly.user_discovery.get().await; - tracing::info!("Rust bridge: calling initialize_or_update on protocols"); - let res = user_discovery - .initialize_or_update(threshold, user_id, public_key, share_promotion) - .await; - tracing::info!("Rust bridge: initialize_or_update on protocols finished"); - Ok(res?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + tracing::info!("Rust bridge: initialize_or_update started"); + let twonly = get_twonly_flutter()?; + tracing::info!("Rust bridge: getting user_discovery lock"); + let user_discovery = twonly.user_discovery.get().await; + tracing::info!("Rust bridge: calling initialize_or_update on protocols"); + let res = user_discovery + .initialize_or_update(threshold, user_id, public_key, share_promotion) + .await; + tracing::info!("Rust bridge: initialize_or_update on protocols finished"); + Ok(res?) + }) + .await } pub async fn get_current_version(callback_id: u32) -> Result> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - Ok(get_twonly_flutter()? - .user_discovery - .get() - .await - .get_current_version() - .await?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .get_current_version() + .await?) + }) + .await } pub async fn get_new_messages( @@ -42,14 +46,16 @@ impl FlutterUserDiscovery { contact_id: i64, received_version: &[u8], ) -> Result>> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - Ok(get_twonly_flutter()? - .user_discovery - .get() - .await - .get_new_messages(contact_id, received_version) - .await?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .get_new_messages(contact_id, received_version) + .await?) + }) + .await } pub async fn should_request_new_messages( @@ -57,14 +63,16 @@ impl FlutterUserDiscovery { contact_id: i64, version: &[u8], ) -> Result>> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - Ok(get_twonly_flutter()? - .user_discovery - .get() - .await - .should_request_new_messages(contact_id, version) - .await?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .should_request_new_messages(contact_id, version) + .await?) + }) + .await } pub async fn handle_new_messages( @@ -73,14 +81,16 @@ impl FlutterUserDiscovery { public_key_verified_timestamp: Option, messages: Vec>, ) -> Result<()> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - Ok(get_twonly_flutter()? - .user_discovery - .get() - .await - .handle_new_messages(contact_id, public_key_verified_timestamp, messages) - .await?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .handle_new_messages(contact_id, public_key_verified_timestamp, messages) + .await?) + }) + .await } pub async fn update_verification_state_for_user( @@ -88,13 +98,15 @@ impl FlutterUserDiscovery { contact_id: i64, public_key_verified_timestamp: Option, ) -> Result<()> { - CURRENT_CALLBACK_ID.scope(callback_id, async move { - Ok(get_twonly_flutter()? - .user_discovery - .get() - .await - .update_verification_state_for_user(contact_id, public_key_verified_timestamp) - .await?) - }).await + CURRENT_CALLBACK_ID + .scope(callback_id, async move { + Ok(get_twonly_flutter()? + .user_discovery + .get() + .await + .update_verification_state_for_user(contact_id, public_key_verified_timestamp) + .await?) + }) + .await } } diff --git a/rust/src/database/migrations/0002_create_signal_tables.sql b/rust/src/database/migrations/0002_create_signal_tables.sql index 53b397cb..53b68ca9 100644 --- a/rust/src/database/migrations/0002_create_signal_tables.sql +++ b/rust/src/database/migrations/0002_create_signal_tables.sql @@ -1,10 +1,9 @@ -- Signal Identities (Stores remote IdentityKeys) CREATE TABLE IF NOT EXISTS signal_identities ( name TEXT NOT NULL, - device_id INTEGER NOT NULL, identity_key BLOB NOT NULL, timestamp INTEGER NOT NULL, - PRIMARY KEY (name, device_id) + PRIMARY KEY (name) ); -- Signal PreKeys (Stores local one-time prekeys) diff --git a/rust/src/signal/engine.rs b/rust/src/signal/engine.rs index 62160be8..ed4a6830 100644 --- a/rust/src/signal/engine.rs +++ b/rust/src/signal/engine.rs @@ -13,6 +13,7 @@ use crate::signal::store::DbSignalProtocolStore; pub struct RustSignalEngine { store: Arc>, + local_name: String, } pub struct FrbPreKeyBundle { @@ -30,7 +31,7 @@ pub struct FrbPreKeyBundle { } impl RustSignalEngine { - pub async fn new() -> Result { + pub async fn new(local_name: String) -> Result { let twonly = crate::bridge::get_twonly_flutter()?; let pool = twonly.rust_db.pool.clone(); @@ -52,6 +53,7 @@ impl RustSignalEngine { Ok(Self { store: Arc::new(Mutex::new(store)), + local_name, }) } @@ -59,6 +61,7 @@ impl RustSignalEngine { pool: sqlx::SqlitePool, identity_key_pair_bytes: Vec, local_registration_id: u32, + local_name: String, ) -> Result { let identity_key_pair = IdentityKeyPair::try_from(&identity_key_pair_bytes[..]) .map_err(|e| TwonlyError::Signal(e.to_string()))?; @@ -67,6 +70,7 @@ impl RustSignalEngine { Ok(Self { store: Arc::new(Mutex::new(store)), + local_name, }) } @@ -80,6 +84,7 @@ impl RustSignalEngine { &self, pre_key_id: u32, signed_pre_key_id: u32, + kyber_pre_key_id: u32, ) -> Result { let mut store_guard = self.store.lock().await; let store = &mut *store_guard; @@ -110,7 +115,7 @@ impl RustSignalEngine { let timestamp = Timestamp::from_epoch_millis( SystemTime::now() .duration_since(UNIX_EPOCH) - .unwrap() + .map_err(|e| TwonlyError::Signal(e.to_string()))? .as_millis() as u64, ); store @@ -127,7 +132,6 @@ impl RustSignalEngine { .await .map_err(|e| TwonlyError::Signal(e.to_string()))?; - let kyber_pre_key_id = 1; let kyber_key_pair = libsignal_protocol::kem::KeyPair::generate( libsignal_protocol::kem::KeyType::Kyber1024, &mut csprng, @@ -143,7 +147,9 @@ impl RustSignalEngine { &mut csprng, ) .map_err(|e| TwonlyError::Signal(e.to_string()))?; - let kyber_sig_arr: [u8; 64] = kyber_signature[..].try_into().unwrap(); + let kyber_sig_arr: [u8; 64] = kyber_signature[..] + .try_into() + .map_err(|e: std::array::TryFromSliceError| TwonlyError::Signal(e.to_string()))?; store .kyber_pre_key_store .save_kyber_pre_key( @@ -196,8 +202,11 @@ impl RustSignalEngine { let d_id = DeviceId::try_from(device_id) .map_err(|_| TwonlyError::Generic(format!("Invalid device id: {}", device_id)))?; let remote_address = ProtocolAddress::new(name, d_id); - let local_address = - ProtocolAddress::new("local".to_string(), DeviceId::try_from(1).unwrap()); + let local_address = ProtocolAddress::new( + self.local_name.clone(), + DeviceId::try_from(1) + .map_err(|_| TwonlyError::Generic("Invalid device id 1".to_string()))?, + ); let identity_key = IdentityKey::decode(&bundle.identity_key) .map_err(|e| TwonlyError::Signal(e.to_string()))?; @@ -221,7 +230,9 @@ impl RustSignalEngine { let pre_key_bundle = PreKeyBundle::new( bundle.registration_id, - DeviceId::try_from(bundle.device_id).unwrap_or(DeviceId::try_from(1).unwrap()), + DeviceId::try_from(bundle.device_id).map_err(|_| { + TwonlyError::Generic(format!("Invalid device id: {}", bundle.device_id)) + })?, pre_key, SignedPreKeyId::from(bundle.signed_pre_key_id), signed_pre_key_public, @@ -261,8 +272,11 @@ impl RustSignalEngine { let d_id = DeviceId::try_from(device_id) .map_err(|_| TwonlyError::Generic(format!("Invalid device id: {}", device_id)))?; let remote_address = ProtocolAddress::new(name, d_id); - let local_address = - ProtocolAddress::new("local".to_string(), DeviceId::try_from(1).unwrap()); + let local_address = ProtocolAddress::new( + self.local_name.clone(), + DeviceId::try_from(1) + .map_err(|_| TwonlyError::Generic("Invalid device id 1".to_string()))?, + ); let mut csprng = rand::rng(); let now = SystemTime::now(); @@ -295,8 +309,11 @@ impl RustSignalEngine { let d_id = DeviceId::try_from(device_id) .map_err(|_| TwonlyError::Generic(format!("Invalid device id: {}", device_id)))?; let remote_address = ProtocolAddress::new(name, d_id); - let local_address = - ProtocolAddress::new("local".to_string(), DeviceId::try_from(1).unwrap()); + let local_address = ProtocolAddress::new( + self.local_name.clone(), + DeviceId::try_from(1) + .map_err(|_| TwonlyError::Generic("Invalid device id 1".to_string()))?, + ); let plaintext = if is_prekey_message { let message = PreKeySignalMessage::try_from(&ciphertext_bytes[..]) diff --git a/rust/src/signal/store.rs b/rust/src/signal/store.rs index b8d962ad..267f087e 100644 --- a/rust/src/signal/store.rs +++ b/rust/src/signal/store.rs @@ -57,21 +57,18 @@ impl IdentityKeyStore for DbIdentityKeyStore { identity: &IdentityKey, ) -> Result { let name = address.name(); - let device_id: u32 = address.device_id().into(); let identity_bytes = identity.serialize(); let timestamp = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) - .unwrap() + .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))? .as_millis() as i64; - let existing: Option<(Vec,)> = sqlx::query_as( - "SELECT identity_key FROM signal_identities WHERE name = ? AND device_id = ?", - ) - .bind(name) - .bind(device_id) - .fetch_optional(&self.pool) - .await - .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; + let existing: Option<(Vec,)> = + sqlx::query_as("SELECT identity_key FROM signal_identities WHERE name = ?") + .bind(name) + .fetch_optional(&self.pool) + .await + .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; let changed = if let Some(row) = existing { row.0 != identity_bytes.as_ref() @@ -79,9 +76,8 @@ impl IdentityKeyStore for DbIdentityKeyStore { false }; - sqlx::query("INSERT INTO signal_identities (name, device_id, identity_key, timestamp) VALUES (?, ?, ?, ?) ON CONFLICT(name, device_id) DO UPDATE SET identity_key = excluded.identity_key, timestamp = excluded.timestamp") + sqlx::query("INSERT INTO signal_identities (name, identity_key, timestamp) VALUES (?, ?, ?) ON CONFLICT(name) DO UPDATE SET identity_key = excluded.identity_key, timestamp = excluded.timestamp") .bind(name) - .bind(device_id) .bind(identity_bytes.as_ref()) .bind(timestamp) .execute(&self.pool) @@ -98,17 +94,14 @@ impl IdentityKeyStore for DbIdentityKeyStore { _direction: Direction, ) -> Result { let name = address.name(); - let device_id: u32 = address.device_id().into(); let identity_bytes = identity.serialize(); - let row: Option<(Vec,)> = sqlx::query_as( - "SELECT identity_key FROM signal_identities WHERE name = ? AND device_id = ?", - ) - .bind(name) - .bind(device_id) - .fetch_optional(&self.pool) - .await - .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; + let row: Option<(Vec,)> = + sqlx::query_as("SELECT identity_key FROM signal_identities WHERE name = ?") + .bind(name) + .fetch_optional(&self.pool) + .await + .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; if let Some((stored_key,)) = row { Ok(stored_key == identity_bytes.as_ref()) @@ -122,16 +115,13 @@ impl IdentityKeyStore for DbIdentityKeyStore { address: &ProtocolAddress, ) -> Result, SignalProtocolError> { let name = address.name(); - let device_id: u32 = address.device_id().into(); - let row: Option<(Vec,)> = sqlx::query_as( - "SELECT identity_key FROM signal_identities WHERE name = ? AND device_id = ?", - ) - .bind(name) - .bind(device_id) - .fetch_optional(&self.pool) - .await - .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; + let row: Option<(Vec,)> = + sqlx::query_as("SELECT identity_key FROM signal_identities WHERE name = ?") + .bind(name) + .fetch_optional(&self.pool) + .await + .map_err(|_| SignalProtocolError::UntrustedIdentity(address.clone()))?; if let Some((bytes,)) = row { let key = IdentityKey::decode(&bytes) diff --git a/rust/src/user_discovery/README.md b/rust/src/user_discovery/README.md deleted file mode 100644 index af442b96..00000000 --- a/rust/src/user_discovery/README.md +++ /dev/null @@ -1,74 +0,0 @@ - -# User Discovery - -User Discovery is a feature that allows users to discover other users in a decentralized system without any central authority. It uses Shamir's Secret Sharing to securely share and discover user information. - -## Getting started - -The User Discovery module is composed of the following components: - -- **UserDiscovery** - The main struct which initializes the user discovery and provides access to the user discovery functionality. - -- **UserDiscoveryStore** - A trait which has to be implemented. It is used to store and retrieve the user discovery data. -- **UserDiscoveryUtils** - A trait which has to be implemented. It is used to perform signature verification and signing. - -```rust -use crate::user_discovery::{UserDiscovery, UserID}; -use crate::user_discovery::stores::InMemoryStore; // Replace with your persistent store -use crate::user_discovery::traits::tests::TestingUtils; // Replace with your utils - -const THRESHOLD: u8 = 2; - -// Initialize user discovery for Alice -const ALICE_ID: UserID = 1; -let alice_ud = UserDiscovery::new(InMemoryStore::default(), TestingUtils::default()).unwrap(); - -// Set threshold, user ID, and the user's public key -alice_ud.initialize_or_update(THRESHOLD, ALICE_ID, vec![0; 32]).unwrap(); - -// Initialize user discovery for Bob -const BOB_ID: UserID = 2; -let bob_ud = UserDiscovery::new(InMemoryStore::default(), TestingUtils::default()).unwrap(); -bob_ud.initialize_or_update(THRESHOLD, BOB_ID, vec![0; 32]).unwrap(); - - - -// Simulate network communication: Alice sends her current version to Bob -let bob_received_version_from_alice = alice_ud.get_current_version().unwrap(); - -// SEND FROM ALICE TO BOB: bob_received_version_from_alice - -// Bob checks if he should request new messages -if bob_ud.should_request_new_messages(ALICE_ID, &bob_received_version_from_alice).unwrap() { - - // Bob has a old version and must now request to get the new messages - - // Bob fetches his current known version and sends it via the network to Alice - let bob_stored_alice_version = bob_ud.get_contact_version(ALICE_ID) - .unwrap() - .unwrap_or_else(|| vec![0, 0]); // Note: In practice use actual default encoded version - - // SEND FROM BOB TO ALICE: bob_stored_alice_version - - // Alice loads the new messages for Bob. These only conclude changes since the provided version. - let new_messages = alice_ud.get_new_messages(BOB_ID, &bob_stored_alice_version).unwrap(); - - // SEND FROM ALICE TO BOB: new_messages - - // Bob processes the received user discovery messages - bob_ud.handle_user_discovery_messages(ALICE_ID, new_messages).unwrap(); - - // BOB is now able to promote ALICE to his other contacts -} - -// - -// 4. Retrieve all newly discovered users and relationships -// In this example now new users where discovered, to see a more comprehensive example -// see the test in the `mod.rs` fil. -let discovered_users = bob_ud.get_all_announced_users().unwrap(); -for (user, connections) in discovered_users { - println!("Discovered User: {} (Public ID: {})", user.user_id, user.public_id); -} -``` - diff --git a/rust/tests/pqxdh_tests.rs b/rust/tests/pqxdh_tests.rs index 5a2d25c4..feb308cd 100644 --- a/rust/tests/pqxdh_tests.rs +++ b/rust/tests/pqxdh_tests.rs @@ -17,13 +17,21 @@ async fn test_twonly_api_100_messages() -> Result<(), Box let bob_identity_bytes = RustSignalEngine::generate_identity_key_pair()?; // 3. Initialize engines with the DB pools - let alice_engine = - RustSignalEngine::new_with_pool(alice_db.pool.clone(), alice_identity_bytes, 1234)?; - let bob_engine = - RustSignalEngine::new_with_pool(bob_db.pool.clone(), bob_identity_bytes, 5678)?; + let alice_engine = RustSignalEngine::new_with_pool( + alice_db.pool.clone(), + alice_identity_bytes, + 1234, + "alice".to_string(), + )?; + let bob_engine = RustSignalEngine::new_with_pool( + bob_db.pool.clone(), + bob_identity_bytes, + 5678, + "bob".to_string(), + )?; // 4. Bob generates a bundle - let bob_bundle = bob_engine.generate_bundle(1, 1).await?; + let bob_bundle = bob_engine.generate_bundle(1, 1, 1).await?; // 5. Alice processes Bob's bundle alice_engine