diff --git a/Cargo.lock b/Cargo.lock index cf5f4a245..5627ff5d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7518,6 +7518,7 @@ dependencies = [ "tracing-oslog", "tracing-subscriber", "uniffi", + "url", "uuid 1.11.0", "xmtp_api_grpc", "xmtp_common", diff --git a/bindings_ffi/benches/create_client.rs b/bindings_ffi/benches/create_client.rs index 2e6ca88da..770c7c2c4 100644 --- a/bindings_ffi/benches/create_client.rs +++ b/bindings_ffi/benches/create_client.rs @@ -6,7 +6,10 @@ use crate::tracing::Instrument; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use tokio::runtime::{Builder, Runtime}; -use xmtp_common::{bench::BENCH_ROOT_SPAN, tmp_path}; +use xmtp_common::{ + bench::{bench_async_setup, BENCH_ROOT_SPAN}, + tmp_path, +}; use xmtp_id::InboxOwner; use xmtp_mls::utils::test::HISTORY_SYNC_URL; use xmtpv3::generate_inbox_id; @@ -43,30 +46,32 @@ fn create_ffi_client(c: &mut Criterion) { let mut benchmark_group = c.benchmark_group("create_client"); // benchmark_group.sample_size(10); - benchmark_group.sampling_mode(criterion::SamplingMode::Flat); benchmark_group.bench_function("create_ffi_client", |b| { let span = trace_span!(BENCH_ROOT_SPAN); b.to_async(&runtime).iter_batched( || { - let wallet = xmtp_cryptography::utils::generate_local_wallet(); - let nonce = 1; - let inbox_id = generate_inbox_id(wallet.get_address(), nonce).unwrap(); - let path = tmp_path(); - let (network, is_secure) = network_url(); - ( - inbox_id, - wallet.get_address(), - nonce, - path, - network, - is_secure, - span.clone(), - ) + bench_async_setup(|| async { + let wallet = xmtp_cryptography::utils::generate_local_wallet(); + let nonce = 1; + let inbox_id = generate_inbox_id(wallet.get_address(), nonce).unwrap(); + let path = tmp_path(); + let (url, is_secure) = network_url(); + let api = xmtpv3::mls::connect_to_backend(url, is_secure) + .await + .unwrap(); + ( + api, + inbox_id, + wallet.get_address(), + nonce, + path, + span.clone(), + ) + }) }, - |(inbox_id, address, nonce, path, network, is_secure, span)| async move { + |(api, inbox_id, address, nonce, path, span)| async move { xmtpv3::mls::create_client( - network, - is_secure, + api, Some(path), Some(vec![0u8; 32]), &inbox_id, @@ -98,29 +103,44 @@ fn cached_create_ffi_client(c: &mut Criterion) { let inbox_id = generate_inbox_id(wallet.get_address(), nonce).unwrap(); let address = wallet.get_address(); let path = tmp_path(); + let (url, is_secure) = network_url(); + let api = runtime.block_on(async { + let api = xmtpv3::mls::connect_to_backend(url.clone(), is_secure) + .await + .unwrap(); + xmtpv3::mls::create_client( + api.clone(), + Some(path.clone()), + Some(vec![0u8; 32]), + &inbox_id.clone(), + address.clone(), + nonce, + None, + Some(HISTORY_SYNC_URL.to_string()), + ) + .await + .unwrap(); + api + }); // benchmark_group.sample_size(10); - benchmark_group.sampling_mode(criterion::SamplingMode::Flat); benchmark_group.bench_function("cached_create_ffi_client", |b| { let span = trace_span!(BENCH_ROOT_SPAN); b.to_async(&runtime).iter_batched( || { - let (network, is_secure) = network_url(); ( + api.clone(), inbox_id.clone(), address.clone(), nonce, path.clone(), HISTORY_SYNC_URL.to_string(), - network, - is_secure, span.clone(), ) }, - |(inbox_id, address, nonce, path, history_sync, network, is_secure, span)| async move { + |(api, inbox_id, address, nonce, path, history_sync, span)| async move { xmtpv3::mls::create_client( - network, - is_secure, + api, Some(path), Some(vec![0u8; 32]), &inbox_id, diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index 5893c24db..4a9851b1d 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -50,6 +50,26 @@ use xmtp_mls::{ use xmtp_proto::xmtp::mls::message_contents::DeviceSyncKind; pub type RustXmtpClient = MlsClient; +#[derive(uniffi::Object, Clone)] +pub struct XmtpApiClient(TonicApiClient); + +#[uniffi::export(async_runtime = "tokio")] +pub async fn connect_to_backend( + host: String, + is_secure: bool, +) -> Result, GenericError> { + init_logger(); + log::info!( + host, + is_secure, + "Creating API client for host: {}, isSecure: {}", + host, + is_secure + ); + let api_client = TonicApiClient::create(host, is_secure).await?; + Ok(Arc::new(XmtpApiClient(api_client))) +} + /// It returns a new client of the specified `inbox_id`. /// Note that the `inbox_id` must be either brand new or already associated with the `account_address`. /// i.e. `inbox_id` cannot be associated with another account address. @@ -72,8 +92,7 @@ pub type RustXmtpClient = MlsClient; #[allow(clippy::too_many_arguments)] #[uniffi::export(async_runtime = "tokio")] pub async fn create_client( - host: String, - is_secure: bool, + api: Arc, db: Option, encryption_key: Option>, inbox_id: &InboxId, @@ -83,12 +102,6 @@ pub async fn create_client( history_sync_url: Option, ) -> Result, GenericError> { init_logger(); - log::info!( - "Creating API client for host: {}, isSecure: {}", - host, - is_secure - ); - let api_client = TonicApiClient::create(host.clone(), is_secure).await?; log::info!( "Creating message store with path: {:?} and encryption key: {} of length {:?}", @@ -120,7 +133,7 @@ pub async fn create_client( ); let mut builder = ClientBuilder::new(identity_strategy) - .api_client(api_client) + .api_client(Arc::unwrap_or_clone(api).0) .store(store); if let Some(url) = &history_sync_url { @@ -1870,11 +1883,11 @@ mod tests { FfiPreferenceUpdate, FfiXmtpClient, }; use crate::{ - get_inbox_id_for_address, inbox_owner::SigningError, FfiConsent, FfiConsentEntityType, - FfiConsentState, FfiConversation, FfiConversationCallback, FfiConversationMessageKind, - FfiCreateGroupOptions, FfiGroupPermissionsOptions, FfiInboxOwner, - FfiListConversationsOptions, FfiListMessagesOptions, FfiMetadataField, FfiPermissionPolicy, - FfiPermissionPolicySet, FfiPermissionUpdateType, FfiSubscribeError, + connect_to_backend, get_inbox_id_for_address, inbox_owner::SigningError, FfiConsent, + FfiConsentEntityType, FfiConsentState, FfiConversation, FfiConversationCallback, + FfiConversationMessageKind, FfiCreateGroupOptions, FfiGroupPermissionsOptions, + FfiInboxOwner, FfiListConversationsOptions, FfiListMessagesOptions, FfiMetadataField, + FfiPermissionPolicy, FfiPermissionPolicySet, FfiPermissionUpdateType, FfiSubscribeError, }; use ethers::utils::hex; use std::sync::{ @@ -2076,10 +2089,10 @@ mod tests { let ffi_inbox_owner = LocalWalletInboxOwner::with_wallet(wallet); let nonce = 1; let inbox_id = generate_inbox_id(&ffi_inbox_owner.get_address(), &nonce).unwrap(); - let client = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &inbox_id, @@ -2143,8 +2156,9 @@ mod tests { let inbox_id = generate_inbox_id(&account_address, &nonce).unwrap(); let client = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), None, &inbox_id, @@ -2168,8 +2182,9 @@ mod tests { let path = tmp_path(); let client_a = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), None, &inbox_id, @@ -2186,8 +2201,9 @@ mod tests { drop(client_a); let client_b = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path), None, &inbox_id, @@ -2219,8 +2235,9 @@ mod tests { let key = static_enc_key().to_vec(); let client_a = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), Some(key), &inbox_id, @@ -2238,8 +2255,9 @@ mod tests { other_key[31] = 1; let result_errored = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path), Some(other_key.to_vec()), &inbox_id, @@ -2290,8 +2308,9 @@ mod tests { let path = tmp_path(); let key = static_enc_key().to_vec(); let client = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), Some(key), &inbox_id, @@ -2355,8 +2374,9 @@ mod tests { let path = tmp_path(); let key = static_enc_key().to_vec(); let client = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), Some(key), &inbox_id, @@ -2442,8 +2462,9 @@ mod tests { let path = tmp_path(); let client = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), None, // encryption_key &inbox_id, @@ -2469,8 +2490,9 @@ mod tests { let path = tmp_path(); let client_amal = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), None, &amal_inbox_id, @@ -2495,8 +2517,9 @@ mod tests { ); let client_bola = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(path.clone()), None, &bola_inbox_id, @@ -4588,8 +4611,9 @@ mod tests { // Step 2: Use wallet A to create a new client with a new inbox id derived from wallet A let wallet_a_inbox_id = generate_inbox_id(&wallet_a.get_address(), &1).unwrap(); let client_a = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &wallet_a_inbox_id, @@ -4624,8 +4648,9 @@ mod tests { let inbox_id = client_a.inbox_id(); let client_b = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &inbox_id, @@ -4686,8 +4711,9 @@ mod tests { let client_b_inbox_id = generate_inbox_id(&wallet_b.get_address(), &nonce).unwrap(); let client_b_new_result = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &client_b_inbox_id, @@ -4718,8 +4744,9 @@ mod tests { let wallet_a = generate_local_wallet(); let wallet_a_inbox_id = generate_inbox_id(&wallet_a.get_address(), &1).unwrap(); let client_a = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &wallet_a_inbox_id, @@ -4737,8 +4764,9 @@ mod tests { let wallet_b = generate_local_wallet(); let wallet_b_inbox_id = generate_inbox_id(&wallet_b.get_address(), &1).unwrap(); let client_b1 = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &wallet_b_inbox_id, @@ -4754,8 +4782,9 @@ mod tests { // Step 3: Wallet B creates a second client for inbox_id B let _client_b2 = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &wallet_b_inbox_id, @@ -4782,8 +4811,9 @@ mod tests { // Step 5: Wallet B tries to create another new client for inbox_id B, but it fails let client_b3 = create_client( - xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), - false, + connect_to_backend(xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false) + .await + .unwrap(), Some(tmp_path()), Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &wallet_b_inbox_id,