Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ members = [
"core/crypto",
"core/double-ratchets",
"core/integration_tests_core",
"core/shared-traits",
"core/sqlite",
"core/storage",
"crates/client-ffi",
Expand All @@ -23,6 +24,7 @@ default-members = [
"core/crypto",
"core/double-ratchets",
"core/integration_tests_core",
"core/shared-traits",
"core/sqlite",
"core/storage",
"crates/client-ffi",
Expand All @@ -31,11 +33,13 @@ default-members = [

[workspace.dependencies]
# Internal Workspace dependency declarations (sorted)
logos-account = { path = "core/account" }
chat-sqlite = { path = "core/sqlite" }
components = { path = "extensions/components" }
crypto = { path = "core/crypto" }
libchat = { path = "core/conversations" }
logos-chat = { path = "crates/client" }
shared-traits = { path = "core/shared-traits" }
storage = { path = "core/storage" }

# External Workspace dependency declarations (sorted)
Expand Down
1 change: 1 addition & 0 deletions core/account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ dev = []
# Workspace dependencies (sorted)
crypto = { workspace = true }
libchat = { workspace = true }
shared-traits = { workspace = true }

# External dependencies (sorted)
9 changes: 5 additions & 4 deletions core/account/src/account.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crypto::{Ed25519SigningKey, Ed25519VerifyingKey};
use shared_traits::{IdentId, IdentIdRef};

use libchat::{AccountId, IdentityProvider};
use libchat::IdentityProvider;

/// A Test Focused LogosAccount using a pre-defined identifier.
/// The test account is not persisted, and uses a single user provided id.
/// This account type should not be used in a production system.
pub struct TestLogosAccount {
id: AccountId,
id: IdentId,
signing_key: Ed25519SigningKey,
verifying_key: Ed25519VerifyingKey,
}
Expand All @@ -16,15 +17,15 @@ impl TestLogosAccount {
let signing_key = Ed25519SigningKey::generate();
let verifying_key = signing_key.verifying_key();
Self {
id: AccountId::new(explicit_id.into()),
id: IdentId::new(explicit_id.into()),
signing_key,
verifying_key,
}
}
}

impl IdentityProvider for TestLogosAccount {
fn account_id(&self) -> &AccountId {
fn id(&self) -> IdentIdRef<'_> {
&self.id
}

Expand Down
1 change: 1 addition & 0 deletions core/conversations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ crate-type = ["rlib","staticlib"]
blake2 = { workspace = true }
chat-sqlite = { workspace = true }
crypto = { workspace = true }
shared-traits = { workspace = true }
storage = { workspace = true }

# External dependencies (sorted)
Expand Down
63 changes: 0 additions & 63 deletions core/conversations/src/account.rs

This file was deleted.

7 changes: 3 additions & 4 deletions core/conversations/src/conversation.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
pub mod group_v1;
mod privatev1;

pub use crate::errors::ChatError;
use crate::outcomes::ConvoOutcome;
use crate::proto::EncryptedPayload;
use crate::service_context::{ExternalServices, ServiceContext};
use crate::types::AccountId;

pub use crate::errors::ChatError;
pub use group_v1::GroupV1Convo;
pub use privatev1::PrivateV1Convo;
use shared_traits::IdentIdRef;

pub type ConversationId = String;

Expand All @@ -34,6 +33,6 @@ pub(crate) trait GroupConvo<S: ExternalServices>: Convo<S> {
fn add_member(
&mut self,
cx: &mut ServiceContext<S>,
members: &[&AccountId],
members: &[IdentIdRef],
) -> Result<(), ChatError>;
}
9 changes: 5 additions & 4 deletions core/conversations/src/conversation/group_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use chat_proto::logoschat::reliability::ReliablePayload;
use openmls::prelude::tls_codec::Deserialize;
use openmls::prelude::*;
use prost::Message as _;
use shared_traits::IdentIdRef;

use crate::inbox_v2::MlsProvider;
use crate::service_context::{ExternalServices, ServiceContext};
use crate::types::AccountId;

use crate::{
DeliveryService, IdentityProvider,
conversation::{ChatError, Convo, GroupConvo},
Expand Down Expand Up @@ -140,7 +141,7 @@ impl GroupV1Convo {

fn key_package_for_account(
&self,
ident: &AccountId,
ident: IdentIdRef,
provider: &impl MlsProvider,
keypkg_provider: &impl KeyPackageProvider,
) -> Result<KeyPackage, ChatError> {
Expand Down Expand Up @@ -171,7 +172,7 @@ impl GroupV1Convo {
content: &[u8],
cx: &ServiceContext<S>,
) -> Result<Vec<AddressedEncryptedPayload>, ChatError> {
let sender_id = cx.mls_identity.account_id().as_str();
let sender_id = cx.mls_identity.id().as_str();
let reliable = cx.causal.on_send(&self.convo_id, sender_id, content);
let wire = reliable.encode_to_vec();

Expand Down Expand Up @@ -274,7 +275,7 @@ impl<S: ExternalServices> GroupConvo<S> for GroupV1Convo {
fn add_member(
&mut self,
cx: &mut ServiceContext<S>,
members: &[&AccountId],
members: &[IdentIdRef],
) -> Result<(), ChatError> {
if members.len() > 50 {
// This is a temporary limit that originates from the the De-MLS epoch time.
Expand Down
49 changes: 20 additions & 29 deletions core/conversations/src/core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::account::LogosAccount;
use crate::causal_history::{CausalHistoryStore, MissingMessage};
use crate::service_context::{ExternalServices, ServiceContext};
use crate::{DeliveryService, IdentityProvider, RegistrationService};
Expand All @@ -9,10 +8,10 @@ use crate::{
inbox_v2::{InboxV2, MlsEphemeralPqProvider, MlsIdentityProvider},
outcomes::{ConvoOutcome, InboxOutcome, PayloadOutcome},
proto::{EncryptedPayload, EnvelopeV1, Message},
types::AccountId,
};
use crypto::{Identity, PublicKey};
use openmls::prelude::GroupId;
use shared_traits::IdentIdRef;
use storage::{ChatStore, ConversationKind, ConversationStore};

pub use crate::conversation::ConversationId;
Expand All @@ -32,8 +31,9 @@ pub struct Core<S: ExternalServices> {

// Constructors live on the `(DS, RS, CS)` form: `S` can't be inferred backwards
// through `S::DS`, so the bundle is built from the three args here.
impl<DS, RS, CS> Core<(DS, RS, CS)>
impl<IP, DS, RS, CS> Core<(IP, DS, RS, CS)>
where
IP: IdentityProvider + 'static,
DS: DeliveryService + 'static,
RS: RegistrationService + 'static,
CS: ChatStore + 'static,
Expand All @@ -43,62 +43,53 @@ where
/// If an identity exists in storage, it will be restored.
/// Otherwise, a new identity will be created with the given name and saved.
pub fn new_from_store(
name: impl Into<String>,
ident: IP,
delivery: DS,
registration: RS,
mut store: CS,
) -> Result<Self, ChatError> {
let name = name.into();

// Load or create identity
let identity = if let Some(identity) = store.load_identity()? {
identity
} else {
let identity = Identity::new(&name);
let identity = Identity::new(ident.id().as_str().to_string());
store.save_identity(&identity)?;
identity
};

Self::assemble(name, identity, delivery, registration, store)
Self::assemble(ident, identity, delivery, registration, store)
}

/// Creates a new in-memory `Core` (for testing).
///
/// Uses in-memory SQLite database. Each call creates a new isolated database.
pub fn new_with_name(
name: impl Into<String>,
ident: IP,
delivery: DS,
registration: RS,
mut store: CS,
store: CS,
) -> Result<Self, ChatError> {
let name = name.into();
let identity = Identity::new(&name);
store
.save_identity(&identity)
.expect("in-memory storage should not fail");

let mut core = Self::assemble(name, identity, delivery, registration, store)?;
// TODO: (P2) Initialize Account in Core or upper client.
let identity = Identity::new(ident.id().as_str().to_string());
let mut core = Self::assemble(ident, identity, delivery, registration, store)?;

core.register_keypackage()?;
Ok(core)
}

/// Builds the inbox/account/MLS/causal state, subscribes both inbound
/// addresses, and assembles the service bundle — shared by both constructors.
fn assemble(
name: String,
ident: IP,
identity: Identity,
mut delivery: DS,
registration: RS,
store: CS,
) -> Result<Self, ChatError> {
let inbox = Inbox::new(&identity);
let account = LogosAccount::new_test(name);
let account_id = account.account_id().clone();
let mls_identity = MlsIdentityProvider::new(account);
let ident_id = ident.id().clone();
let mls_identity = MlsIdentityProvider::new(ident);
let mls_provider = MlsEphemeralPqProvider::new().map_err(ChatError::generic)?;
let causal = CausalHistoryStore::new();
let pq_inbox = InboxV2::new(account_id);
let pq_inbox = InboxV2::new(ident_id);

// Subscribe to inbound addresses for both conversation stacks.
delivery
Expand All @@ -124,7 +115,7 @@ where
}
}

impl<S: ExternalServices + 'static> Core<S> {
impl<'a, S: ExternalServices + 'static> Core<S> {
pub fn ds(&mut self) -> &mut S::DS {
&mut self.services.ds
}
Expand All @@ -138,8 +129,8 @@ impl<S: ExternalServices + 'static> Core<S> {
}

/// Returns the unique identifier associated with the account
pub fn account_id(&self) -> &AccountId {
self.pq_inbox.account_id()
pub fn ident_id(&'a self) -> IdentIdRef<'a> {
self.pq_inbox.ident_id()
}

/// Submit the local account's MLS KeyPackage to the registration service.
Expand Down Expand Up @@ -179,7 +170,7 @@ impl<S: ExternalServices + 'static> Core<S> {

pub fn create_group_convo(
&mut self,
participants: &[&AccountId],
participants: &[IdentIdRef],
) -> Result<ConversationId, ChatError> {
// TODO: (P1) Ensure errors are handled properly. This is a high chance for
// desynchronized state: MlsGroup persistence, conversation persistence, and
Expand All @@ -200,7 +191,7 @@ impl<S: ExternalServices + 'static> Core<S> {
pub fn group_add_member(
&mut self,
convo_id: &str,
members: &[&AccountId],
members: &[IdentIdRef],
) -> Result<(), ChatError> {
let mut convo = self.load_group_convo(convo_id)?;
convo.add_member(&mut self.services, members)
Expand Down
Loading
Loading