From cf10919469f192919b708ee65a2caaf42f896d78 Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Sat, 30 Nov 2024 12:17:57 -0500 Subject: [PATCH] common crate for wasm shims --- .github/workflows/test-webassembly.yml | 2 +- Cargo.lock | 47 +++--- Cargo.toml | 7 +- bindings_ffi/Cargo.toml | 1 + bindings_ffi/src/mls.rs | 14 +- bindings_node/Cargo.toml | 1 + bindings_node/src/inbox_id.rs | 2 +- bindings_wasm/Cargo.toml | 1 + bindings_wasm/src/inbox_id.rs | 2 +- common/Cargo.toml | 35 +++++ common/src/lib.rs | 35 +++++ common/src/macros.rs | 24 +++ {xmtp_mls => common}/src/retry.rs | 21 +-- common/src/test.rs | 124 +++++++++++++++ common/src/test/macros.rs | 49 ++++++ .../utils => common/src}/test/traced_test.rs | 39 ++++- common/src/time.rs | 76 ++++++++++ dev/wasm | 12 -- examples/cli/Cargo.toml | 1 + examples/cli/cli-client.rs | 2 +- mls_validation_service/Cargo.toml | 1 + mls_validation_service/src/handlers.rs | 5 +- xmtp_api_http/src/util.rs | 3 +- xmtp_id/Cargo.toml | 8 +- xmtp_id/src/associations/builder.rs | 3 +- xmtp_id/src/associations/member.rs | 7 +- xmtp_id/src/associations/mod.rs | 131 ++++++++-------- xmtp_id/src/associations/serialization.rs | 16 +- xmtp_id/src/associations/signature.rs | 5 +- xmtp_id/src/associations/state.rs | 6 +- xmtp_id/src/associations/test_utils.rs | 23 --- xmtp_id/src/associations/unverified.rs | 7 +- .../src/associations/verified_signature.rs | 10 +- xmtp_id/src/utils/mod.rs | 11 -- xmtp_mls/Cargo.toml | 8 +- xmtp_mls/benches/crypto.rs | 1 - xmtp_mls/src/api/identity.rs | 13 +- xmtp_mls/src/api/mls.rs | 3 +- xmtp_mls/src/api/mod.rs | 6 +- xmtp_mls/src/builder.rs | 17 +-- xmtp_mls/src/client.rs | 5 +- xmtp_mls/src/codecs/group_updated.rs | 7 +- xmtp_mls/src/codecs/membership_change.rs | 7 +- xmtp_mls/src/groups/device_sync.rs | 20 +-- .../src/groups/device_sync/consent_sync.rs | 16 +- .../src/groups/device_sync/message_sync.rs | 28 ++-- xmtp_mls/src/groups/group_permissions.rs | 24 +-- xmtp_mls/src/groups/intents.rs | 2 +- xmtp_mls/src/groups/mls_sync.rs | 11 +- xmtp_mls/src/groups/mod.rs | 12 +- xmtp_mls/src/groups/scoped_client.rs | 2 +- xmtp_mls/src/groups/subscriptions.rs | 30 +--- xmtp_mls/src/groups/validated_commit.rs | 3 +- xmtp_mls/src/hpke.rs | 3 +- xmtp_mls/src/identity.rs | 5 +- xmtp_mls/src/identity_updates.rs | 16 +- xmtp_mls/src/intents.rs | 2 +- xmtp_mls/src/lib.rs | 142 +----------------- xmtp_mls/src/storage/encrypted_store/group.rs | 13 +- .../storage/encrypted_store/group_intent.rs | 46 +++--- .../storage/encrypted_store/group_message.rs | 11 +- .../src/storage/encrypted_store/identity.rs | 7 +- .../encrypted_store/identity_update.rs | 14 +- .../encrypted_store/key_package_history.rs | 14 +- xmtp_mls/src/storage/encrypted_store/mod.rs | 41 +++-- .../encrypted_store/sqlcipher_connection.rs | 3 +- xmtp_mls/src/storage/errors.rs | 42 +++--- xmtp_mls/src/storage/sql_key_store.rs | 4 +- xmtp_mls/src/subscriptions.rs | 73 ++++----- xmtp_mls/src/types.rs | 2 - xmtp_mls/src/utils/mod.rs | 45 ------ xmtp_mls/src/utils/test/mod.rs | 64 ++------ xmtp_proto/Cargo.toml | 12 +- xmtp_proto/src/api_client.rs | 6 - xmtp_proto/src/error.rs | 7 + 75 files changed, 810 insertions(+), 708 deletions(-) create mode 100644 common/Cargo.toml create mode 100644 common/src/lib.rs create mode 100644 common/src/macros.rs rename {xmtp_mls => common}/src/retry.rs (94%) create mode 100644 common/src/test.rs create mode 100644 common/src/test/macros.rs rename {xmtp_mls/src/utils => common/src}/test/traced_test.rs (72%) create mode 100644 common/src/time.rs delete mode 100755 dev/wasm delete mode 100644 xmtp_mls/src/types.rs diff --git a/.github/workflows/test-webassembly.yml b/.github/workflows/test-webassembly.yml index c77c0a7c1..62f3ee969 100644 --- a/.github/workflows/test-webassembly.yml +++ b/.github/workflows/test-webassembly.yml @@ -35,7 +35,7 @@ jobs: - name: Start Docker containers run: dev/up - name: Build WebAssembly Packages - run: cargo build --tests --release --target wasm32-unknown-unknown -p xmtp_id -p xmtp_mls -p xmtp_api_http -p xmtp_cryptography + run: cargo build --tests --release --target wasm32-unknown-unknown -p xmtp_id -p xmtp_mls -p xmtp_api_http -p xmtp_cryptography -p xmtp_common - name: test with chrome run: | cargo test --release --target wasm32-unknown-unknown -p xmtp_mls -p xmtp_id -p xmtp_api_http -p xmtp_cryptography -- \ diff --git a/Cargo.lock b/Cargo.lock index 084c38557..04a6f822f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,6 +461,7 @@ dependencies = [ "tracing", "tracing-subscriber", "xmtp_api_grpc", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_mls", @@ -485,6 +486,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-bindgen-test", "xmtp_api_http", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_mls", @@ -3508,6 +3510,7 @@ dependencies = [ "tracing-subscriber", "vergen", "warp", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_mls", @@ -6814,21 +6817,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.74" @@ -7278,12 +7266,33 @@ dependencies = [ "valuable", "valuable-serde", "xmtp_api_grpc", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_mls", "xmtp_proto", ] +[[package]] +name = "xmtp_common" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "futures", + "getrandom", + "gloo-timers 0.3.0", + "parking_lot 0.12.3", + "rand", + "thiserror 2.0.3", + "tokio", + "tracing", + "tracing-subscriber", + "tracing-wasm", + "wasm-bindgen-test", + "web-time", + "xmtp_cryptography", +] + [[package]] name = "xmtp_cryptography" version = "0.1.0" @@ -7338,7 +7347,8 @@ dependencies = [ "tracing", "url", "wasm-bindgen-test", - "wasm-timer", + "web-time", + "xmtp_common", "xmtp_cryptography", "xmtp_proto", "xmtp_v2", @@ -7398,10 +7408,11 @@ dependencies = [ "trait-variant", "wasm-bindgen-futures", "wasm-bindgen-test", - "wasm-timer", "web-sys", + "web-time", "xmtp_api_grpc", "xmtp_api_http", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_proto", @@ -7424,6 +7435,7 @@ dependencies = [ "tonic", "tracing", "wasm-bindgen-test", + "xmtp_common", ] [[package]] @@ -7471,6 +7483,7 @@ dependencies = [ "uniffi", "uuid 1.11.0", "xmtp_api_grpc", + "xmtp_common", "xmtp_cryptography", "xmtp_id", "xmtp_mls", diff --git a/Cargo.toml b/Cargo.toml index 0c2025a8e..c43f7bc11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,8 @@ members = [ "bindings_node", "bindings_ffi", "xtask", - "xmtp_debug" -] + "xmtp_debug", + "common"] # Make the feature resolver explicit. # See https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html#details @@ -29,8 +29,8 @@ license = "MIT" anyhow = "1.0" async-stream = "0.3" async-trait = "0.1.77" +web-time = "1.1" chrono = "0.4.38" -wasm-timer = "0.2" ctor = "0.2" ed25519 = "2.2.3" ed25519-dalek = { version = "2.1.1", features = ["zeroize"] } @@ -98,6 +98,7 @@ xmtp_api_grpc = { path = "xmtp_api_grpc" } xmtp_id = { path = "xmtp_id" } xmtp_mls = { path = "xmtp_mls" } xmtp_proto = { path = "xmtp_proto" } +xmtp_common = { path = "common" } [profile.dev] # Disabling debug info speeds up builds a bunch, diff --git a/bindings_ffi/Cargo.toml b/bindings_ffi/Cargo.toml index 938ab78b8..7e44b3498 100644 --- a/bindings_ffi/Cargo.toml +++ b/bindings_ffi/Cargo.toml @@ -22,6 +22,7 @@ xmtp_mls = { path = "../xmtp_mls" } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } xmtp_user_preferences = { path = "../xmtp_user_preferences" } xmtp_v2 = { path = "../xmtp_v2" } +xmtp_common.workspace = true [target.'cfg(target_os = "android")'.dependencies] paranoid-android = "0.2" diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index e899374bf..3c84a7187 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -4,6 +4,7 @@ use crate::{FfiSubscribeError, GenericError}; use std::{collections::HashMap, convert::TryInto, sync::Arc}; use tokio::sync::Mutex; use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient; +use xmtp_common::retry::Retry; use xmtp_id::associations::verify_signed_with_public_context; use xmtp_id::scw_verifier::RemoteSignatureVerifier; use xmtp_id::{ @@ -36,7 +37,6 @@ use xmtp_mls::{ GroupMetadataOptions, MlsGroup, PreconfiguredPolicies, UpdateAdminListType, }, identity::IdentityStrategy, - retry::Retry, storage::{ consent_record::{ConsentState, ConsentType, StoredConsentRecord}, group::GroupQueryArgs, @@ -1802,9 +1802,7 @@ mod tests { FfiPermissionPolicySet, FfiPermissionUpdateType, FfiSubscribeError, }; use ethers::utils::hex; - use rand::distributions::{Alphanumeric, DistString}; use std::{ - env, sync::{ atomic::{AtomicU32, Ordering}, Arc, Mutex, @@ -1812,6 +1810,7 @@ mod tests { time::{Duration, Instant}, }; use tokio::{sync::Notify, time::error::Elapsed}; + use xmtp_common::tmp_path; use xmtp_cryptography::{signature::RecoverableSignature, utils::rng}; use xmtp_id::associations::{ generate_inbox_id, @@ -1928,15 +1927,6 @@ mod tests { } } - pub fn rand_string() -> String { - Alphanumeric.sample_string(&mut rand::thread_rng(), 24) - } - - pub fn tmp_path() -> String { - let db_name = rand_string(); - format!("{}/{}.db3", env::temp_dir().to_str().unwrap(), db_name) - } - fn static_enc_key() -> EncryptionKey { [2u8; 32] } diff --git a/bindings_node/Cargo.toml b/bindings_node/Cargo.toml index aa1038961..81729585c 100644 --- a/bindings_node/Cargo.toml +++ b/bindings_node/Cargo.toml @@ -30,6 +30,7 @@ xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id = { path = "../xmtp_id" } xmtp_mls = { path = "../xmtp_mls" } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } +xmtp_common.workspace = true [build-dependencies] napi-build = "2.0.1" diff --git a/bindings_node/src/inbox_id.rs b/bindings_node/src/inbox_id.rs index b9a4d34a9..5b91cb9ea 100644 --- a/bindings_node/src/inbox_id.rs +++ b/bindings_node/src/inbox_id.rs @@ -4,10 +4,10 @@ use napi::bindgen_prelude::Uint8Array; use napi_derive::napi; use std::sync::Arc; use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient; +use xmtp_common::retry::Retry; use xmtp_id::associations::generate_inbox_id as xmtp_id_generate_inbox_id; use xmtp_id::associations::MemberIdentifier; use xmtp_mls::api::ApiClientWrapper; -use xmtp_mls::retry::Retry; #[napi] pub async fn get_inbox_id_for_address( diff --git a/bindings_wasm/Cargo.toml b/bindings_wasm/Cargo.toml index 65f79084b..20e988091 100644 --- a/bindings_wasm/Cargo.toml +++ b/bindings_wasm/Cargo.toml @@ -19,6 +19,7 @@ xmtp_api_http = { path = "../xmtp_api_http" } xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id = { path = "../xmtp_id" } xmtp_mls = { path = "../xmtp_mls", features = ["test-utils", "http-api"] } +xmtp_common.workspace = true xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } tracing-web = "0.1" tracing.workspace = true diff --git a/bindings_wasm/src/inbox_id.rs b/bindings_wasm/src/inbox_id.rs index 1aec357c4..d0b046f3d 100644 --- a/bindings_wasm/src/inbox_id.rs +++ b/bindings_wasm/src/inbox_id.rs @@ -1,8 +1,8 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsError}; use xmtp_api_http::XmtpHttpApiClient; +use xmtp_common::retry::Retry; use xmtp_id::associations::generate_inbox_id as xmtp_id_generate_inbox_id; use xmtp_mls::api::ApiClientWrapper; -use xmtp_mls::retry::Retry; #[wasm_bindgen(js_name = getInboxIdForAddress)] pub async fn get_inbox_id_for_address( diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 000000000..5a1f774f8 --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "xmtp_common" +edition = "2021" +version.workspace = true +license.workspace = true + +[dependencies] +web-time.workspace = true +tracing.workspace = true +tokio = { workspace = true, features = ["time"] } +rand = "0.8" +futures.workspace = true +xmtp_cryptography.workspace = true + +parking_lot = { workspace = true, optional = true } +tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "ansi", "json"], optional = true } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { workspace = true, features = ["js"] } +gloo-timers = { workspace = true, features = ["futures"] } +tracing-wasm = { version = "0.2", optional = true } +console_error_panic_hook = { version = "0.1", optional = true } + +[dev-dependencies] +thiserror.workspace = true + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +tokio = { workspace = true, features = ["time", "macros", "rt", "sync"]} +wasm-bindgen-test.workspace = true + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +tokio = { workspace = true, features = ["time", "macros", "rt-multi-thread", "sync"]} + +[features] +test-utils = ["dep:parking_lot", "dep:tracing-subscriber", "dep:tracing-wasm", "dep:console_error_panic_hook"] diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 000000000..bc6664738 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,35 @@ +//! Common types shared among all XMTP Crates + +mod macros; + +#[cfg(feature = "test-utils")] +mod test; +#[cfg(feature = "test-utils")] +pub use test::*; + +pub mod retry; +pub use retry::*; + +/// Global Marker trait for WebAssembly +#[cfg(target_arch = "wasm32")] +pub trait Wasm {} +#[cfg(target_arch = "wasm32")] +impl Wasm for T {} + +pub mod time; + +use rand::{ + distributions::{Alphanumeric, DistString}, + RngCore, +}; +use xmtp_cryptography::utils as crypto_utils; + +pub fn rand_string() -> String { + Alphanumeric.sample_string(&mut crypto_utils::rng(), N) +} + +pub fn rand_array() -> [u8; N] { + let mut buffer = [0u8; N]; + crypto_utils::rng().fill_bytes(&mut buffer); + buffer +} diff --git a/common/src/macros.rs b/common/src/macros.rs new file mode 100644 index 000000000..9ebf42790 --- /dev/null +++ b/common/src/macros.rs @@ -0,0 +1,24 @@ +/// Turn the `Result` into an `Option`, logging the error with `tracing::error` and +/// returning `None` if the value matches on Result::Err(). +/// Optionally pass a message as the second argument. +#[macro_export] +macro_rules! optify { + ( $e: expr ) => { + match $e { + Ok(v) => Some(v), + Err(e) => { + tracing::error!("{}", e); + None + } + } + }; + ( $e: expr, $msg: tt ) => { + match $e { + Ok(v) => Some(v), + Err(e) => { + tracing::error!("{}: {:?}", $msg, e); + None + } + } + }; +} diff --git a/xmtp_mls/src/retry.rs b/common/src/retry.rs similarity index 94% rename from xmtp_mls/src/retry.rs rename to common/src/retry.rs index 6e5aca993..3088d1dc6 100644 --- a/xmtp_mls/src/retry.rs +++ b/common/src/retry.rs @@ -18,9 +18,11 @@ use rand::Rng; +pub struct NotSpecialized; + /// Specifies which errors are retryable. /// All Errors are not retryable by-default. -pub trait RetryableError: std::error::Error { +pub trait RetryableError: std::error::Error { fn is_retryable(&self) -> bool; } @@ -76,7 +78,7 @@ pub struct RetryBuilder { /// /// # Example /// ``` -/// use xmtp_mls::retry::RetryBuilder; +/// use xmtp_common::retry::RetryBuilder; /// /// RetryBuilder::default() /// .retries(5) @@ -121,7 +123,7 @@ impl Retry { /// Retry but for an async context /// ``` -/// use xmtp_mls::{retry_async, retry::{RetryableError, Retry}}; +/// use xmtp_common::{retry_async, retry::{RetryableError, Retry}}; /// use thiserror::Error; /// use tokio::sync::mpsc; /// @@ -183,7 +185,7 @@ macro_rules! retry_async { e.to_string() ); attempts += 1; - $crate::sleep($retry.duration(attempts)).await; + $crate::time::sleep($retry.duration(attempts)).await; } else { tracing::info!("error is not retryable. {:?}:{}", e, e); break Err(e); @@ -207,13 +209,6 @@ macro_rules! retryable { }}; } -// network errors should generally be retryable, unless there's a bug in our code -impl RetryableError for xmtp_proto::Error { - fn is_retryable(&self) -> bool { - true - } -} - #[cfg(test)] pub(crate) mod tests { #[cfg(target_arch = "wasm32")] @@ -313,7 +308,7 @@ pub(crate) mod tests { return Ok(()); } // do some work - crate::sleep(core::time::Duration::from_nanos(100)).await; + crate::time::sleep(core::time::Duration::from_nanos(100)).await; Err(SomeError::ARetryableError) } @@ -339,7 +334,7 @@ pub(crate) mod tests { } *data += 1; // do some work - crate::sleep(core::time::Duration::from_nanos(100)).await; + crate::time::sleep(core::time::Duration::from_nanos(100)).await; Err(SomeError::ARetryableError) } diff --git a/common/src/test.rs b/common/src/test.rs new file mode 100644 index 000000000..b5d2cd593 --- /dev/null +++ b/common/src/test.rs @@ -0,0 +1,124 @@ +//! Common Test Utilites +use rand::{ + distributions::{Alphanumeric, DistString}, + seq::IteratorRandom, + Rng, +}; +use std::sync::OnceLock; +use xmtp_cryptography::utils as crypto_utils; + +#[cfg(not(target_arch = "wasm32"))] +pub mod traced_test; +#[cfg(not(target_arch = "wasm32"))] +pub use traced_test::TestWriter; + +mod macros; + +static INIT: OnceLock<()> = OnceLock::new(); + +/// A simple test logger that defaults to the INFO level +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +pub fn logger() { + use tracing_subscriber::{ + fmt::{self, format}, + layer::SubscriberExt, + util::SubscriberInitExt, + EnvFilter, Layer, + }; + + INIT.get_or_init(|| { + let structured = std::env::var("STRUCTURED"); + let is_structured = matches!(structured, Ok(s) if s == "true" || s == "1"); + + let filter = || { + EnvFilter::builder() + .with_default_directive(tracing::metadata::LevelFilter::INFO.into()) + .from_env_lossy() + }; + + tracing_subscriber::registry() + // structured JSON logger only if STRUCTURED=true + .with(is_structured.then(|| { + tracing_subscriber::fmt::layer() + .json() + .flatten_event(true) + .with_level(true) + .with_filter(filter()) + })) + // default logger + .with((!is_structured).then(|| { + fmt::layer() + .compact() + .fmt_fields({ + format::debug_fn(move |writer, field, value| { + if field.name() == "message" { + write!(writer, "{:?}", value)?; + } + Ok(()) + }) + }) + .with_filter(filter()) + })) + .init(); + }); +} + +/// A simple test logger that defaults to the INFO level +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +pub fn logger() { + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::util::SubscriberInitExt; + use tracing_subscriber::EnvFilter; + + INIT.get_or_init(|| { + let filter = EnvFilter::builder() + .with_default_directive(tracing::metadata::LevelFilter::DEBUG.into()) + .from_env_lossy(); + + tracing_subscriber::registry() + .with(tracing_wasm::WASMLayer::default()) + .with(filter) + .init(); + + console_error_panic_hook::set_once(); + }); +} + +pub fn rand_hexstring() -> String { + let mut rng = crypto_utils::rng(); + let hex_chars = "0123456789abcdef"; + let v: String = (0..40) + .map(|_| hex_chars.chars().choose(&mut rng).unwrap()) + .collect(); + + format!("0x{}", v) +} + +pub fn rand_account_address() -> String { + Alphanumeric.sample_string(&mut crypto_utils::rng(), 42) +} + +pub fn rand_vec() -> Vec { + crate::rand_array::().to_vec() +} + +pub fn rand_u64() -> u64 { + crypto_utils::rng().gen() +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn tmp_path() -> String { + let db_name = crate::rand_string::<24>(); + format!("{}/{}.db3", std::env::temp_dir().to_str().unwrap(), db_name) +} + +#[cfg(target_arch = "wasm32")] +pub fn tmp_path() -> String { + let db_name = crate::rand_string::<24>(); + format!("{}/{}.db3", "test_db", db_name) +} + +pub fn rand_time() -> i64 { + let mut rng = rand::thread_rng(); + rng.gen_range(0..1_000_000_000) +} diff --git a/common/src/test/macros.rs b/common/src/test/macros.rs new file mode 100644 index 000000000..e07087d78 --- /dev/null +++ b/common/src/test/macros.rs @@ -0,0 +1,49 @@ +/// wrapper over assert!(matches!()) for Errors +/// assert_err!(fun(), StorageError::Explosion) +/// +/// or the message variant, +/// assert_err!(fun(), StorageError::Explosion, "the storage did not explode"); +#[macro_export] +macro_rules! assert_err { + ( $x:expr , $y:pat $(,)? ) => { + assert!(matches!($x, Err($y))) + }; + + ( $x:expr, $y:pat $(,)?, $($msg:tt)+) => {{ + assert!(matches!($x, Err($y)), $($msg)+) + }} + } + +/// wrapper over assert! macros for Ok's +/// +/// Make sure something is Ok(_) without caring about return value. +/// assert_ok!(fun()); +/// +/// Against an expected value, e.g Ok(true) +/// assert_ok!(fun(), true); +/// +/// or the message variant, +/// assert_ok!(fun(), Ok(_), "the storage is not ok"); +#[macro_export] +macro_rules! assert_ok { + + ( $e:expr ) => { + assert_ok!($e,) + }; + + ( $e:expr, ) => {{ + use std::result::Result::*; + match $e { + Ok(v) => v, + Err(e) => panic!("assertion failed: Err({:?})", e), + } + }}; + + ( $x:expr , $y:expr $(,)? ) => { + assert_eq!($x, Ok($y.into())); + }; + + ( $x:expr, $y:expr $(,)?, $($msg:tt)+) => {{ + assert_eq!($x, Ok($y.into()), $($msg)+); + }} + } diff --git a/xmtp_mls/src/utils/test/traced_test.rs b/common/src/test/traced_test.rs similarity index 72% rename from xmtp_mls/src/utils/test/traced_test.rs rename to common/src/test/traced_test.rs index fea217199..eb208d220 100644 --- a/xmtp_mls/src/utils/test/traced_test.rs +++ b/common/src/test/traced_test.rs @@ -1,3 +1,4 @@ +/// Tests that can assert on tracing logs in a tokio threaded context use std::{io, sync::Arc}; use parking_lot::Mutex; @@ -58,8 +59,9 @@ impl fmt::MakeWriter<'_> for TestWriter { self.clone() } } - +/* /// Only works with current-thread +#[inline] pub fn traced_test(f: impl Fn() -> Fut) where Fut: futures::Future, @@ -88,6 +90,39 @@ where buf.clear(); }); } +*/ + +#[macro_export] +macro_rules! traced_test { + ( $f:expr ) => {{ + use tracing_subscriber::fmt; + use $crate::traced_test::TestWriter; + + $crate::traced_test::LOG_BUFFER.with(|buf| { + let rt = tokio::runtime::Builder::new_current_thread() + .thread_name("tracing-test") + .enable_time() + .enable_io() + .build() + .unwrap(); + buf.clear(); + + let subscriber = fmt::Subscriber::builder() + .with_env_filter(format!("{}=debug", env!("CARGO_PKG_NAME"))) + .with_writer(buf.clone()) + .with_level(true) + .with_ansi(false) + .finish(); + + let dispatch = tracing::Dispatch::new(subscriber); + tracing::dispatcher::with_default(&dispatch, || { + rt.block_on($f); + }); + + buf.clear(); + }); + }}; +} /// macro that can assert logs in tests. /// Note: tests that use this must be used in `traced_test` function @@ -95,7 +130,7 @@ where #[macro_export] macro_rules! assert_logged { ( $search:expr , $occurrences:expr ) => { - $crate::utils::test::traced_test::LOG_BUFFER.with(|buf| { + $crate::traced_test::LOG_BUFFER.with(|buf| { let lines = { buf.flush(); buf.as_string() diff --git a/common/src/time.rs b/common/src/time.rs new file mode 100644 index 000000000..56649ce3b --- /dev/null +++ b/common/src/time.rs @@ -0,0 +1,76 @@ +//! Time primitives for native and WebAssembly + +use std::fmt; + +#[derive(Debug)] +pub struct Expired; + +impl std::error::Error for Expired { + fn description(&self) -> &str { + "Timer duration expired" + } +} + +#[cfg(not(target_arch = "wasm32"))] +impl From for Expired { + fn from(_: tokio::time::error::Elapsed) -> Expired { + Expired + } +} + +impl fmt::Display for Expired { + fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result { + write!(f, "timer duration expired") + } +} + +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +pub use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +pub use web_time::{Duration, Instant, SystemTime, UNIX_EPOCH}; + +pub fn now_ns() -> i64 { + let now = SystemTime::now(); + + now.duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_nanos() as i64 +} + +#[cfg(target_arch = "wasm32")] +pub async fn timeout(duration: Duration, future: F) -> Result +where + F: std::future::IntoFuture, +{ + use futures::future::Either::*; + let timeout = gloo_timers::future::TimeoutFuture::new(duration.as_millis() as u32); + let future = future.into_future(); + futures::pin_mut!(future); + match futures::future::select(timeout, future).await { + Left(_) => Err(Expired), + Right((value, _)) => Ok(value), + } +} + +#[cfg(not(target_arch = "wasm32"))] +pub async fn timeout(duration: Duration, future: F) -> Result +where + F: std::future::IntoFuture, +{ + tokio::time::timeout(duration, future) + .await + .map_err(Into::into) +} + +// WASM Shims +#[cfg(target_arch = "wasm32")] +#[doc(hidden)] +pub async fn sleep(duration: Duration) { + gloo_timers::future::TimeoutFuture::new(duration.as_millis() as u32).await; +} + +#[cfg(not(target_arch = "wasm32"))] +#[doc(hidden)] +pub async fn sleep(duration: Duration) { + tokio::time::sleep(duration).await +} diff --git a/dev/wasm b/dev/wasm deleted file mode 100755 index 717bdf8b4..000000000 --- a/dev/wasm +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -eou pipefail - -if [[ "${OSTYPE}" == "darwin"* ]]; then - if ! wasm-pack --version &>/dev/null; then cargo install wasm-pack; fi -fi - -pushd bindings_wasm/ > /dev/null - -wasm-pack build --target nodejs --out-dir pkg # pkg is the default - -popd > /dev/null diff --git a/examples/cli/Cargo.toml b/examples/cli/Cargo.toml index 9d837d9a1..e7aee9674 100644 --- a/examples/cli/Cargo.toml +++ b/examples/cli/Cargo.toml @@ -42,3 +42,4 @@ xmtp_cryptography = { path = "../../xmtp_cryptography" } xmtp_id = { path = "../../xmtp_id" } xmtp_mls = { path = "../../xmtp_mls" } xmtp_proto = { path = "../../xmtp_proto", features = ["proto_full"] } +xmtp_common.workspace = true diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index df7fa4c42..f50a80b25 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -32,6 +32,7 @@ use tracing_subscriber::{ use valuable::Valuable; use xmtp_api_grpc::grpc_api_helper::Client as ClientV3; use xmtp_api_grpc::replication_client::ClientV4; +use xmtp_common::time::now_ns; use xmtp_cryptography::{ signature::{RecoverableSignature, SignatureError}, utils::rng, @@ -54,7 +55,6 @@ use xmtp_mls::{ group_message::StoredGroupMessage, EncryptedMessageStore, EncryptionKey, StorageError, StorageOption, }, - utils::time::now_ns, InboxOwner, }; use xmtp_proto::xmtp::mls::message_contents::DeviceSyncKind; diff --git a/mls_validation_service/Cargo.toml b/mls_validation_service/Cargo.toml index fd6e37edd..e5aa6dbb7 100644 --- a/mls_validation_service/Cargo.toml +++ b/mls_validation_service/Cargo.toml @@ -36,6 +36,7 @@ ethers.workspace = true rand = { workspace = true } xmtp_id = { workspace = true, features = ["test-utils"] } xmtp_mls = { workspace = true, features = ["test-utils"] } +xmtp_common = { workspace = true, features = ["test-utils"]} [features] test-utils = ["xmtp_id/test-utils"] diff --git a/mls_validation_service/src/handlers.rs b/mls_validation_service/src/handlers.rs index ef96904dd..abf159685 100644 --- a/mls_validation_service/src/handlers.rs +++ b/mls_validation_service/src/handlers.rs @@ -328,11 +328,12 @@ mod tests { prelude::{tls_codec::Serialize, Credential as OpenMlsCredential, CredentialWithKey}, }; use openmls_rust_crypto::OpenMlsRustCrypto; + use xmtp_common::{rand_string, rand_u64}; use xmtp_cryptography::XmtpInstallationCredential; use xmtp_id::{ associations::{ generate_inbox_id, - test_utils::{rand_string, rand_u64, MockSmartContractSignatureVerifier}, + test_utils::MockSmartContractSignatureVerifier, unverified::{UnverifiedAction, UnverifiedIdentityUpdate}, }, is_smart_contract, @@ -399,7 +400,7 @@ mod tests { #[tokio::test] #[should_panic] async fn test_get_association_state() { - let account_address = rand_string(); + let account_address = rand_string::<24>(); let nonce = rand_u64(); let inbox_id = generate_inbox_id(&account_address, &nonce).unwrap(); let update = UnverifiedIdentityUpdate::new_test( diff --git a/xmtp_api_http/src/util.rs b/xmtp_api_http/src/util.rs index 55e4ff3fa..ab151c9f4 100644 --- a/xmtp_api_http/src/util.rs +++ b/xmtp_api_http/src/util.rs @@ -83,7 +83,7 @@ pub fn create_grpc_stream_inner< .send() .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - + tracing::debug!("Got Request, getting byte stream"); let mut remaining = vec![]; for await bytes in request.bytes_stream() { let bytes = bytes @@ -92,6 +92,7 @@ pub fn create_grpc_stream_inner< let de = Deserializer::from_slice(bytes); let mut stream = de.into_iter::>(); 'messages: loop { + tracing::debug!("Waiting on next response ..."); let response = stream.next(); let res = match response { Some(Ok(GrpcResponse::Ok(response))) => Ok(response), diff --git a/xmtp_id/Cargo.toml b/xmtp_id/Cargo.toml index 3488b23d3..2b6d44c91 100644 --- a/xmtp_id/Cargo.toml +++ b/xmtp_id/Cargo.toml @@ -27,8 +27,9 @@ tokio = { workspace = true, features = ["macros"] } tracing.workspace = true xmtp_cryptography.workspace = true xmtp_proto = { workspace = true, features = ["proto_full"] } -wasm-timer.workspace = true +web-time.workspace = true ethers = { workspace = true, features = ["rustls"] } +xmtp_common.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] openmls = { workspace = true, features = ["js"] } @@ -40,10 +41,11 @@ openmls.workspace = true [dev-dependencies] xmtp_v2 = { path = "../xmtp_v2" } ed25519-dalek = { workspace = true, features = ["digest", "rand_core"] } +xmtp_common = { workspace = true, features = ["test-utils"] } +wasm-bindgen-test.workspace = true [target.'cfg(target_arch = "wasm32")'.dev-dependencies] -wasm-bindgen-test.workspace = true gloo-timers.workspace = true [features] -test-utils = [] +test-utils = ["xmtp_common/test-utils"] diff --git a/xmtp_id/src/associations/builder.rs b/xmtp_id/src/associations/builder.rs index 43c0d166a..5426cd8b7 100644 --- a/xmtp_id/src/associations/builder.rs +++ b/xmtp_id/src/associations/builder.rs @@ -4,8 +4,9 @@ use std::collections::HashMap; -use crate::{scw_verifier::SmartContractSignatureVerifier, utils::now_ns}; +use crate::scw_verifier::SmartContractSignatureVerifier; use thiserror::Error; +use xmtp_common::time::now_ns; use super::{ unsigned_actions::{ diff --git a/xmtp_id/src/associations/member.rs b/xmtp_id/src/associations/member.rs index 40b162e73..f23e19101 100644 --- a/xmtp_id/src/associations/member.rs +++ b/xmtp_id/src/associations/member.rs @@ -165,15 +165,12 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::associations::test_utils; - use super::*; - - use test_utils::rand_string; + use xmtp_common::rand_hexstring; impl Default for MemberIdentifier { fn default() -> Self { - MemberIdentifier::Address(rand_string()) + MemberIdentifier::Address(rand_hexstring()) } } diff --git a/xmtp_id/src/associations/mod.rs b/xmtp_id/src/associations/mod.rs index 7cd29ba17..ca6e6e7d3 100644 --- a/xmtp_id/src/associations/mod.rs +++ b/xmtp_id/src/associations/mod.rs @@ -42,11 +42,11 @@ pub fn get_state>( #[cfg(any(test, feature = "test-utils"))] pub mod test_defaults { use self::{ - test_utils::{rand_string, rand_u64, rand_vec}, unverified::{UnverifiedAction, UnverifiedIdentityUpdate}, verified_signature::VerifiedSignature, }; use super::*; + use xmtp_common::{rand_hexstring, rand_u64, rand_vec}; impl IdentityUpdate { pub fn new_test(actions: Vec, inbox_id: String) -> Self { @@ -62,19 +62,19 @@ pub mod test_defaults { impl Default for AddAssociation { fn default() -> Self { - let existing_member = rand_string(); - let new_member = rand_vec(); + let existing_member = rand_hexstring(); + let new_member = rand_vec::<32>(); Self { existing_member_signature: VerifiedSignature::new( existing_member.into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), new_member_signature: VerifiedSignature::new( new_member.clone().into(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), new_member_identifier: new_member.into(), @@ -85,14 +85,14 @@ pub mod test_defaults { // Default will create an inbox with a ERC-191 signature impl Default for CreateInbox { fn default() -> Self { - let signer = rand_string(); + let signer = rand_hexstring(); Self { nonce: rand_u64(), account_address: signer.clone(), initial_address_signature: VerifiedSignature::new( signer.into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), } @@ -101,15 +101,15 @@ pub mod test_defaults { impl Default for RevokeAssociation { fn default() -> Self { - let signer = rand_string(); + let signer = rand_hexstring(); Self { recovery_address_signature: VerifiedSignature::new( signer.into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), - revoked_member: rand_string().into(), + revoked_member: rand_hexstring().into(), } } } @@ -119,10 +119,11 @@ pub mod test_defaults { pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use wasm_bindgen_test::wasm_bindgen_test; - use self::test_utils::{rand_string, rand_vec}; use super::*; use crate::associations::verified_signature::VerifiedSignature; + use xmtp_common::{rand_hexstring, rand_vec}; pub fn new_test_inbox() -> AssociationState { let create_request = CreateInbox::default(); @@ -144,7 +145,7 @@ pub(crate) mod tests { existing_member_signature: VerifiedSignature::new( initial_wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), ..Default::default() @@ -157,7 +158,7 @@ pub(crate) mod tests { .unwrap() } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_create_inbox() { let create_request = CreateInbox::default(); let inbox_id = @@ -172,11 +173,11 @@ pub(crate) mod tests { assert!(existing_entity.identifier.eq(&account_address.into())); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn create_and_add_separately() { let initial_state = new_test_inbox(); let inbox_id = initial_state.inbox_id().to_string(); - let new_installation_identifier: MemberIdentifier = rand_vec().into(); + let new_installation_identifier: MemberIdentifier = rand_vec::<32>().into(); let first_member: MemberIdentifier = initial_state.recovery_address().clone().into(); let update = Action::AddAssociation(AddAssociation { @@ -184,13 +185,13 @@ pub(crate) mod tests { new_member_signature: VerifiedSignature::new( new_installation_identifier.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), existing_member_signature: VerifiedSignature::new( first_member.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -206,24 +207,24 @@ pub(crate) mod tests { assert_eq!(new_member.added_by_entity, Some(first_member)); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn create_and_add_together() { let create_action = CreateInbox::default(); let account_address = create_action.account_address.clone(); let inbox_id = generate_inbox_id(&account_address, &create_action.nonce).unwrap(); - let new_member_identifier: MemberIdentifier = rand_vec().into(); + let new_member_identifier: MemberIdentifier = rand_vec::<32>().into(); let add_action = AddAssociation { existing_member_signature: VerifiedSignature::new( account_address.clone().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), // Add an installation ID new_member_signature: VerifiedSignature::new( new_member_identifier.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), new_member_identifier: new_member_identifier.clone(), @@ -243,9 +244,9 @@ pub(crate) mod tests { ); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn create_from_legacy_key() { - let member_identifier: MemberIdentifier = rand_string().into(); + let member_identifier: MemberIdentifier = rand_hexstring().into(); let create_action = CreateInbox { nonce: 0, account_address: member_identifier.to_string(), @@ -282,7 +283,7 @@ pub(crate) mod tests { assert!(matches!(update_result, Err(AssociationError::Replay))); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn add_wallet_from_installation_key() { let initial_state = new_test_inbox_with_installation(); let inbox_id = initial_state.inbox_id().to_string(); @@ -293,19 +294,19 @@ pub(crate) mod tests { .unwrap() .identifier; - let new_wallet_address: MemberIdentifier = rand_string().into(); + let new_wallet_address: MemberIdentifier = rand_hexstring().into(); let add_association = Action::AddAssociation(AddAssociation { new_member_identifier: new_wallet_address.clone(), new_member_signature: VerifiedSignature::new( new_wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), existing_member_signature: VerifiedSignature::new( installation_id.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -318,13 +319,13 @@ pub(crate) mod tests { assert_eq!(new_state.members().len(), 3); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn reject_invalid_signature_on_create() { // Creates a signature with the wrong signer let bad_signature = VerifiedSignature::new( - rand_string().into(), + rand_hexstring().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ); let action = CreateInbox { @@ -334,7 +335,7 @@ pub(crate) mod tests { let state_result = get_state(vec![IdentityUpdate::new_test( vec![Action::CreateInbox(action)], - rand_string(), + rand_hexstring(), )]); assert!(state_result.is_err()); @@ -344,15 +345,15 @@ pub(crate) mod tests { )); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn reject_invalid_signature_on_update() { let initial_state = new_test_inbox(); let inbox_id = initial_state.inbox_id().to_string(); // Signature is from a random address let bad_signature = VerifiedSignature::new( - rand_string().into(), + rand_hexstring().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ); @@ -376,7 +377,7 @@ pub(crate) mod tests { existing_member_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), ..Default::default() @@ -392,7 +393,7 @@ pub(crate) mod tests { )); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn reject_if_signer_not_existing_member() { let create_inbox = CreateInbox::default(); let inbox_id = @@ -402,9 +403,9 @@ pub(crate) mod tests { let update = Action::AddAssociation(AddAssociation { // Existing member signature is coming from a random wallet existing_member_signature: VerifiedSignature::new( - rand_string().into(), + rand_hexstring().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), ..Default::default() @@ -420,26 +421,26 @@ pub(crate) mod tests { )); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn reject_if_installation_adding_installation() { let existing_state = new_test_inbox_with_installation(); let inbox_id = existing_state.inbox_id().to_string(); let existing_installations = existing_state.members_by_kind(MemberKind::Installation); let existing_installation = existing_installations.first().unwrap(); - let new_installation_id: MemberIdentifier = rand_vec().into(); + let new_installation_id: MemberIdentifier = rand_vec::<32>().into(); let update = Action::AddAssociation(AddAssociation { existing_member_signature: VerifiedSignature::new( existing_installation.identifier.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), new_member_identifier: new_installation_id.clone(), new_member_signature: VerifiedSignature::new( new_installation_id.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -457,7 +458,7 @@ pub(crate) mod tests { )); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn revoke() { let initial_state = new_test_inbox_with_installation(); let inbox_id = initial_state.inbox_id().to_string(); @@ -471,7 +472,7 @@ pub(crate) mod tests { recovery_address_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), revoked_member: installation_id.clone(), @@ -485,7 +486,7 @@ pub(crate) mod tests { assert!(new_state.get(&installation_id).is_none()); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn revoke_children() { let initial_state = new_test_inbox_with_installation(); let inbox_id = initial_state.inbox_id().to_string(); @@ -500,7 +501,7 @@ pub(crate) mod tests { existing_member_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), ..Default::default() @@ -517,7 +518,7 @@ pub(crate) mod tests { recovery_address_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), revoked_member: wallet_address.clone(), @@ -532,7 +533,7 @@ pub(crate) mod tests { assert_eq!(new_state.members().len(), 0); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn revoke_and_re_add() { let initial_state = new_test_inbox(); let wallet_address = initial_state @@ -544,19 +545,19 @@ pub(crate) mod tests { let inbox_id = initial_state.inbox_id().to_string(); - let second_wallet_address: MemberIdentifier = rand_string().into(); + let second_wallet_address: MemberIdentifier = rand_hexstring().into(); let add_second_wallet = Action::AddAssociation(AddAssociation { new_member_identifier: second_wallet_address.clone(), new_member_signature: VerifiedSignature::new( second_wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), existing_member_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -565,7 +566,7 @@ pub(crate) mod tests { recovery_address_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), revoked_member: second_wallet_address.clone(), @@ -586,13 +587,13 @@ pub(crate) mod tests { new_member_signature: VerifiedSignature::new( second_wallet_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), existing_member_signature: VerifiedSignature::new( wallet_address, SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -605,19 +606,19 @@ pub(crate) mod tests { assert_eq!(state_after_re_add.members().len(), 2); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn change_recovery_address() { let initial_state = new_test_inbox_with_installation(); let inbox_id = initial_state.inbox_id().to_string(); let initial_recovery_address: MemberIdentifier = initial_state.recovery_address().clone().into(); - let new_recovery_address = rand_string(); + let new_recovery_address = rand_hexstring(); let update_recovery = Action::ChangeRecoveryAddress(ChangeRecoveryAddress { new_recovery_address: new_recovery_address.clone(), recovery_address_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), }); @@ -633,7 +634,7 @@ pub(crate) mod tests { recovery_address_signature: VerifiedSignature::new( initial_recovery_address.clone(), SignatureKind::Erc191, - rand_vec(), + rand_vec::<32>(), None, ), revoked_member: initial_recovery_address.clone(), @@ -650,14 +651,14 @@ pub(crate) mod tests { )); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn scw_signature_binding() { let initial_chain_id: u64 = 1; - let signer = rand_string(); + let signer = rand_hexstring(); let initial_address_signature = VerifiedSignature::new( signer.clone().into(), SignatureKind::Erc1271, - rand_vec(), + rand_vec::<32>(), Some(initial_chain_id), ); let action = CreateInbox { @@ -675,13 +676,13 @@ pub(crate) mod tests { let inbox_id = initial_state.inbox_id(); let new_chain_id: u64 = 2; - let new_member: MemberIdentifier = rand_vec().into(); + let new_member: MemberIdentifier = rand_vec::<32>().into(); // A signature from the same account address but on a different chain ID let existing_member_sig = VerifiedSignature::new( signer.clone().into(), SignatureKind::Erc1271, - rand_vec(), + rand_vec::<32>(), Some(new_chain_id), ); @@ -691,7 +692,7 @@ pub(crate) mod tests { new_member_signature: VerifiedSignature::new( new_member.clone(), SignatureKind::InstallationKey, - rand_vec(), + rand_vec::<32>(), None, ), new_member_identifier: new_member.clone(), @@ -702,7 +703,7 @@ pub(crate) mod tests { }), Action::ChangeRecoveryAddress(ChangeRecoveryAddress { recovery_address_signature: existing_member_sig.clone(), - new_recovery_address: rand_string(), + new_recovery_address: rand_hexstring(), }), ]; diff --git a/xmtp_id/src/associations/serialization.rs b/xmtp_id/src/associations/serialization.rs index fd53a28e9..60807f158 100644 --- a/xmtp_id/src/associations/serialization.rs +++ b/xmtp_id/src/associations/serialization.rs @@ -579,21 +579,19 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::associations::{ - hashes::generate_inbox_id, - test_utils::{rand_string, rand_u64, rand_vec}, - }; + use crate::associations::hashes::generate_inbox_id; + use xmtp_common::{rand_hexstring, rand_u64, rand_vec}; use super::*; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn test_round_trip_unverified() { - let account_address = rand_string(); + let account_address = rand_hexstring(); let nonce = rand_u64(); let inbox_id = generate_inbox_id(&account_address, &nonce).unwrap(); let client_timestamp_ns = rand_u64(); - let signature_bytes = rand_vec(); + let signature_bytes = rand_vec::<32>(); let identity_update = UnverifiedIdentityUpdate::new( inbox_id, @@ -614,7 +612,7 @@ pub(crate) mod tests { 4, 5, 6, ]), unsigned_action: UnsignedAddAssociation { - new_member_identifier: rand_string().into(), + new_member_identifier: rand_hexstring().into(), }, }), UnverifiedAction::ChangeRecoveryAddress(UnverifiedChangeRecoveryAddress { @@ -622,7 +620,7 @@ pub(crate) mod tests { 7, 8, 9, ]), unsigned_action: UnsignedChangeRecoveryAddress { - new_recovery_address: rand_string(), + new_recovery_address: rand_hexstring(), }, }), UnverifiedAction::RevokeAssociation(UnverifiedRevokeAssociation { @@ -630,7 +628,7 @@ pub(crate) mod tests { 10, 11, 12, ]), unsigned_action: UnsignedRevokeAssociation { - revoked_member: rand_string().into(), + revoked_member: rand_hexstring().into(), }, }), ], diff --git a/xmtp_id/src/associations/signature.rs b/xmtp_id/src/associations/signature.rs index 863e0044e..90eb98a4d 100644 --- a/xmtp_id/src/associations/signature.rs +++ b/xmtp_id/src/associations/signature.rs @@ -296,8 +296,9 @@ mod tests { use ethers::core::k256::{ecdsa::Signature as K256Signature, elliptic_curve::scalar::IsHigh}; use ethers::signers::{LocalWallet, Signer}; use rand::thread_rng; + use wasm_bindgen_test::wasm_bindgen_test; - #[tokio::test] + #[wasm_bindgen_test(unsupported = tokio::test)] async fn test_to_lower_s() { // Create a test wallet let wallet = LocalWallet::new(&mut thread_rng()); @@ -334,7 +335,7 @@ mod tests { assert!(!is_high, "Normalized signature should have low-s value"); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_invalid_signature() { // Test with invalid signature bytes let invalid_sig = vec![0u8; 65]; diff --git a/xmtp_id/src/associations/state.rs b/xmtp_id/src/associations/state.rs index a9339be88..d26569e1b 100644 --- a/xmtp_id/src/associations/state.rs +++ b/xmtp_id/src/associations/state.rs @@ -204,14 +204,14 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::associations::test_utils::rand_string; + use xmtp_common::rand_hexstring; use super::*; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn can_add_remove() { - let starting_state = AssociationState::new(rand_string(), 0, None).unwrap(); + let starting_state = AssociationState::new(rand_hexstring(), 0, None).unwrap(); let new_entity = Member::default(); let with_add = starting_state.add(new_entity.clone()); assert!(with_add.get(&new_entity.identifier).is_some()); @@ -221,7 +221,7 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn can_diff() { - let starting_state = AssociationState::new(rand_string(), 0, None).unwrap(); + let starting_state = AssociationState::new(rand_hexstring(), 0, None).unwrap(); let entity_1 = Member::default(); let entity_2 = Member::default(); let entity_3 = Member::default(); diff --git a/xmtp_id/src/associations/test_utils.rs b/xmtp_id/src/associations/test_utils.rs index 4ab83734d..2f0db1704 100644 --- a/xmtp_id/src/associations/test_utils.rs +++ b/xmtp_id/src/associations/test_utils.rs @@ -11,32 +11,9 @@ use ethers::{ signers::{LocalWallet, Signer}, types::Bytes, }; -use rand::Rng; use xmtp_cryptography::basic_credential::XmtpInstallationCredential; use xmtp_cryptography::CredentialSign; -pub fn rand_string() -> String { - let hex_chars = "0123456789abcdef"; - let v: String = (0..40) - .map(|_| { - let idx = rand::thread_rng().gen_range(0..hex_chars.len()); - hex_chars.chars().nth(idx).unwrap() - }) - .collect(); - - format!("0x{}", v) -} - -pub fn rand_u64() -> u64 { - rand::thread_rng().gen() -} - -pub fn rand_vec() -> Vec { - let mut buf = [0u8; 32]; - rand::thread_rng().fill(&mut buf[..]); - buf.to_vec() -} - #[derive(Debug, Clone)] pub struct MockSmartContractSignatureVerifier { is_valid_signature: bool, diff --git a/xmtp_id/src/associations/unverified.rs b/xmtp_id/src/associations/unverified.rs index a1ac2c849..64f198e0e 100644 --- a/xmtp_id/src/associations/unverified.rs +++ b/xmtp_id/src/associations/unverified.rs @@ -409,9 +409,8 @@ mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::associations::{ - generate_inbox_id, test_utils::rand_string, unsigned_actions::UnsignedCreateInbox, - }; + use crate::associations::{generate_inbox_id, unsigned_actions::UnsignedCreateInbox}; + use xmtp_common::rand_hexstring; use super::{ UnverifiedAction, UnverifiedCreateInbox, UnverifiedIdentityUpdate, @@ -421,7 +420,7 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn create_identity_update() { - let account_address = rand_string(); + let account_address = rand_hexstring(); let nonce = 1; let update = UnverifiedIdentityUpdate { inbox_id: generate_inbox_id(account_address.as_str(), &nonce).unwrap(), diff --git a/xmtp_id/src/associations/verified_signature.rs b/xmtp_id/src/associations/verified_signature.rs index 3b30dc6e0..255fc3972 100644 --- a/xmtp_id/src/associations/verified_signature.rs +++ b/xmtp_id/src/associations/verified_signature.rs @@ -175,15 +175,15 @@ mod tests { use super::*; use crate::{ associations::{ - sign_with_legacy_key, - test_utils::{rand_string, MockSmartContractSignatureVerifier}, - verified_signature::VerifiedSignature, - InstallationKeyContext, MemberIdentifier, SignatureKind, + sign_with_legacy_key, test_utils::MockSmartContractSignatureVerifier, + verified_signature::VerifiedSignature, InstallationKeyContext, MemberIdentifier, + SignatureKind, }, InboxOwner, }; use ethers::signers::{LocalWallet, Signer}; use prost::Message; + use xmtp_common::rand_hexstring; use xmtp_cryptography::{CredentialSign, XmtpInstallationCredential}; use xmtp_proto::xmtp::message_contents::{ signature::Union as SignatureUnion, signed_private_key, @@ -367,7 +367,7 @@ mod tests { async fn test_smart_contract_wallet() { let mock_verifier = MockSmartContractSignatureVerifier::new(true); let chain_id: u64 = 24; - let account_address = rand_string(); + let account_address = rand_hexstring(); let account_id = AccountId::new(format!("eip155:{chain_id}"), account_address.clone()); let signature_text = "test_smart_contract_wallet_signature"; let signature_bytes = &[1, 2, 3]; diff --git a/xmtp_id/src/utils/mod.rs b/xmtp_id/src/utils/mod.rs index 0acaf32ef..ec59e09c8 100644 --- a/xmtp_id/src/utils/mod.rs +++ b/xmtp_id/src/utils/mod.rs @@ -1,13 +1,2 @@ -use wasm_timer::{SystemTime, UNIX_EPOCH}; #[cfg(any(test, feature = "test-utils"))] pub mod test; - -pub const NS_IN_SEC: i64 = 1_000_000_000; - -pub fn now_ns() -> i64 { - let now = SystemTime::now(); - - now.duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_nanos() as i64 -} diff --git a/xmtp_mls/Cargo.toml b/xmtp_mls/Cargo.toml index e900fcf95..e890b4496 100644 --- a/xmtp_mls/Cargo.toml +++ b/xmtp_mls/Cargo.toml @@ -38,7 +38,8 @@ test-utils = [ "xmtp_proto/test-utils", "xmtp_api_http/test-utils", "xmtp_api_grpc/test-utils", - "dep:const_format" + "dep:const_format", + "xmtp_common/test-utils" ] update-schema = ["toml"] @@ -65,8 +66,9 @@ tokio-stream = { version = "0.1", default-features = false, features = [ ] } tracing.workspace = true trait-variant.workspace = true -wasm-timer.workspace = true +web-time.workspace = true zeroize.workspace = true +xmtp_common.workspace = true # XMTP/Local xmtp_cryptography = { workspace = true } @@ -142,6 +144,8 @@ openmls_basic_credential.workspace = true xmtp_id = { path = "../xmtp_id", features = ["test-utils"] } xmtp_proto = { workspace = true, features = ["test-utils"] } const_format.workspace = true +xmtp_common = { workspace = true, features = ["test-utils"]} +wasm-bindgen-test.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] ctor.workspace = true diff --git a/xmtp_mls/benches/crypto.rs b/xmtp_mls/benches/crypto.rs index 17306e01b..c4f338ba7 100644 --- a/xmtp_mls/benches/crypto.rs +++ b/xmtp_mls/benches/crypto.rs @@ -46,7 +46,6 @@ fn bench_encrypt_welcome(c: &mut Criterion) { let keypair = crypto .derive_hpke_keypair(CIPHERSUITE.hpke_config(), ikm.as_slice()) .unwrap(); - let mut payload = vec![0; size]; OsRng.fill_bytes(payload.as_mut_slice()); (payload, keypair.public) diff --git a/xmtp_mls/src/api/identity.rs b/xmtp_mls/src/api/identity.rs index 02e6be91c..f2ef21a75 100644 --- a/xmtp_mls/src/api/identity.rs +++ b/xmtp_mls/src/api/identity.rs @@ -151,8 +151,9 @@ pub(crate) mod tests { use super::super::test_utils::*; use super::GetIdentityUpdatesV2Filter; - use crate::{api::ApiClientWrapper, retry::Retry}; - use xmtp_id::associations::{test_utils::rand_string, unverified::UnverifiedIdentityUpdate}; + use crate::api::ApiClientWrapper; + use xmtp_common::{rand_hexstring, Retry}; + use xmtp_id::associations::unverified::UnverifiedIdentityUpdate; use xmtp_proto::xmtp::identity::api::v1::{ get_identity_updates_response::{ IdentityUpdateLog, Response as GetIdentityUpdatesResponseItem, @@ -173,7 +174,7 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn publish_identity_update() { let mut mock_api = MockApiClient::new(); - let inbox_id = rand_string(); + let inbox_id = rand_hexstring(); let identity_update = create_identity_update(inbox_id.clone()); mock_api @@ -191,7 +192,7 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn get_identity_update_v2() { let mut mock_api = MockApiClient::new(); - let inbox_id = rand_string(); + let inbox_id = rand_hexstring(); let inbox_id_clone = inbox_id.clone(); let inbox_id_clone_2 = inbox_id.clone(); mock_api @@ -238,10 +239,10 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn get_inbox_ids() { let mut mock_api = MockApiClient::new(); - let inbox_id = rand_string(); + let inbox_id = rand_hexstring(); let inbox_id_clone = inbox_id.clone(); let inbox_id_clone_2 = inbox_id.clone(); - let address = rand_string(); + let address = rand_hexstring(); let address_clone = address.clone(); let address_clone_2 = address.clone(); diff --git a/xmtp_mls/src/api/mls.rs b/xmtp_mls/src/api/mls.rs index 4000467e6..5b50595c7 100644 --- a/xmtp_mls/src/api/mls.rs +++ b/xmtp_mls/src/api/mls.rs @@ -1,7 +1,8 @@ use std::collections::HashMap; use super::ApiClientWrapper; -use crate::{retry_async, XmtpApi}; +use crate::XmtpApi; +use xmtp_common::retry_async; use xmtp_proto::api_client::XmtpMlsStreams; use xmtp_proto::xmtp::mls::api::v1::{ group_message_input::{Version as GroupMessageInputVersion, V1 as GroupMessageInputV1}, diff --git a/xmtp_mls/src/api/mod.rs b/xmtp_mls/src/api/mod.rs index c9255e01f..ddfaa2564 100644 --- a/xmtp_mls/src/api/mod.rs +++ b/xmtp_mls/src/api/mod.rs @@ -5,11 +5,9 @@ pub mod test_utils; use std::sync::Arc; -use crate::{ - retry::{Retry, RetryableError}, - XmtpApi, -}; +use crate::XmtpApi; use thiserror::Error; +use xmtp_common::{Retry, RetryableError}; use xmtp_id::{associations::DeserializationError as AssociationDeserializationError, InboxId}; use xmtp_proto::Error as ApiError; diff --git a/xmtp_mls/src/builder.rs b/xmtp_mls/src/builder.rs index 450b84666..e72b1cf25 100644 --- a/xmtp_mls/src/builder.rs +++ b/xmtp_mls/src/builder.rs @@ -11,10 +11,10 @@ use crate::{ client::Client, identity::{Identity, IdentityStrategy}, identity_updates::load_identity_updates, - retry::Retry, storage::EncryptedMessageStore, StorageError, XmtpApi, }; +use xmtp_common::Retry; #[derive(Error, Debug)] pub enum ClientBuilderError { @@ -222,24 +222,22 @@ pub(crate) mod tests { use crate::api::ApiClientWrapper; use crate::builder::ClientBuilderError; use crate::identity::IdentityError; - use crate::retry::Retry; use crate::utils::test::TestClient; use crate::XmtpApi; - use crate::{ - api::test_utils::*, identity::Identity, storage::identity::StoredIdentity, - utils::test::rand_vec, Store, - }; + use crate::{api::test_utils::*, identity::Identity, storage::identity::StoredIdentity, Store}; + use xmtp_common::{rand_vec, tmp_path, Retry}; use openmls::credentials::{Credential, CredentialType}; use prost::Message; + use xmtp_common::rand_u64; use xmtp_cryptography::utils::{generate_local_wallet, rng}; use xmtp_cryptography::XmtpInstallationCredential; + use xmtp_id::associations::generate_inbox_id; use xmtp_id::associations::test_utils::MockSmartContractSignatureVerifier; use xmtp_id::associations::unverified::{ UnverifiedRecoverableEcdsaSignature, UnverifiedSignature, }; use xmtp_id::associations::ValidatedLegacySignedPublicKey; - use xmtp_id::associations::{generate_inbox_id, test_utils::rand_u64}; use xmtp_id::scw_verifier::SmartContractSignatureVerifier; use xmtp_proto::api_client::XmtpTestClient; use xmtp_proto::xmtp::identity::api::v1::{ @@ -255,7 +253,6 @@ pub(crate) mod tests { use super::{ClientBuilder, IdentityStrategy}; use crate::{ storage::{EncryptedMessageStore, StorageOption}, - utils::test::tmp_path, Client, InboxOwner, }; @@ -619,7 +616,7 @@ pub(crate) mod tests { let stored: StoredIdentity = (&Identity { inbox_id: inbox_id.clone(), installation_keys: XmtpInstallationCredential::new(), - credential: Credential::new(CredentialType::Basic, rand_vec()), + credential: Credential::new(CredentialType::Basic, rand_vec::<24>()), signature_request: None, is_ready: AtomicBool::new(true), }) @@ -656,7 +653,7 @@ pub(crate) mod tests { let stored: StoredIdentity = (&Identity { inbox_id: stored_inbox_id.clone(), installation_keys: Default::default(), - credential: Credential::new(CredentialType::Basic, rand_vec()), + credential: Credential::new(CredentialType::Basic, rand_vec::<24>()), signature_request: None, is_ready: AtomicBool::new(true), }) diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index 8efd0da2d..5b71fe50a 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -38,8 +38,6 @@ use crate::{ identity_updates::{load_identity_updates, IdentityUpdateError}, intents::Intents, mutex_registry::MutexRegistry, - retry::Retry, - retry_async, retryable, storage::wallet_addresses::WalletEntry, storage::{ consent_record::{ConsentState, ConsentType, StoredConsentRecord}, @@ -54,6 +52,7 @@ use crate::{ xmtp_openmls_provider::XmtpOpenMlsProvider, Fetch, Store, XmtpApi, }; +use xmtp_common::{retry_async, retryable, Retry}; /// Enum representing the network the Client is connected to #[derive(Clone, Copy, Default, Debug)] @@ -109,7 +108,7 @@ impl From for ClientError { } } -impl crate::retry::RetryableError for ClientError { +impl xmtp_common::RetryableError for ClientError { fn is_retryable(&self) -> bool { match self { ClientError::Group(group_error) => retryable!(group_error), diff --git a/xmtp_mls/src/codecs/group_updated.rs b/xmtp_mls/src/codecs/group_updated.rs index 09ebea595..cf1b7cc87 100644 --- a/xmtp_mls/src/codecs/group_updated.rs +++ b/xmtp_mls/src/codecs/group_updated.rs @@ -50,20 +50,19 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use xmtp_common::rand_string; use xmtp_proto::xmtp::mls::message_contents::{group_updated::Inbox, GroupUpdated}; - use crate::utils::test::rand_string; - use super::*; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn test_encode_decode() { let new_member = Inbox { - inbox_id: rand_string(), + inbox_id: rand_string::<24>(), }; let data = GroupUpdated { - initiated_by_inbox_id: rand_string(), + initiated_by_inbox_id: rand_string::<24>(), added_inboxes: vec![new_member.clone()], removed_inboxes: vec![], metadata_field_changes: vec![], diff --git a/xmtp_mls/src/codecs/membership_change.rs b/xmtp_mls/src/codecs/membership_change.rs index e64f50df6..eb389ad96 100644 --- a/xmtp_mls/src/codecs/membership_change.rs +++ b/xmtp_mls/src/codecs/membership_change.rs @@ -52,18 +52,17 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use xmtp_common::{rand_string, rand_vec}; use xmtp_proto::xmtp::mls::message_contents::MembershipChange; - use crate::utils::test::{rand_string, rand_vec}; - use super::*; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), test)] fn test_encode_decode() { let new_member = MembershipChange { - installation_ids: vec![rand_vec()], - account_address: rand_string(), + installation_ids: vec![rand_vec::<24>()], + account_address: rand_string::<24>(), initiated_by_account_address: "".to_string(), }; let data = GroupMembershipChanges { diff --git a/xmtp_mls/src/groups/device_sync.rs b/xmtp_mls/src/groups/device_sync.rs index 8f887f81c..88b3605f1 100644 --- a/xmtp_mls/src/groups/device_sync.rs +++ b/xmtp_mls/src/groups/device_sync.rs @@ -1,11 +1,9 @@ use super::{GroupError, MlsGroup}; use crate::configuration::NS_IN_HOUR; -use crate::retry::{RetryBuilder, RetryableError}; use crate::storage::group::{ConversationType, GroupQueryArgs}; use crate::storage::group_message::MsgQueryArgs; use crate::storage::DbConnection; use crate::subscriptions::{LocalEvents, StreamMessages, SubscribeError, SyncMessage}; -use crate::utils::time::now_ns; use crate::xmtp_openmls_provider::XmtpOpenMlsProvider; use crate::{ client::ClientError, @@ -15,23 +13,20 @@ use crate::{ group_message::{GroupMessageKind, StoredGroupMessage}, StorageError, }, - Client, + Client, Store, }; -use crate::{retry_async, Store}; use aes_gcm::aead::generic_array::GenericArray; use aes_gcm::{ aead::{Aead, KeyInit}, Aes256Gcm, }; use futures::{pin_mut, Stream, StreamExt}; -use rand::{ - distributions::{Alphanumeric, DistString}, - Rng, RngCore, -}; +use rand::{Rng, RngCore}; use serde::{Deserialize, Serialize}; -use std::time::Duration; use thiserror::Error; use tracing::{instrument, warn}; +use xmtp_common::time::{now_ns, Duration}; +use xmtp_common::{retry_async, RetryBuilder, RetryableError}; use xmtp_cryptography::utils as crypto_utils; use xmtp_id::scw_verifier::SmartContractSignatureVerifier; use xmtp_proto::api_client::trait_impls::XmtpApi; @@ -787,14 +782,11 @@ impl TryFrom for DeviceSyncKeyType { } pub(super) fn new_request_id() -> String { - Alphanumeric.sample_string(&mut rand::thread_rng(), ENC_KEY_SIZE) + xmtp_common::rand_string::() } pub(super) fn generate_nonce() -> [u8; NONCE_SIZE] { - let mut nonce = [0u8; NONCE_SIZE]; - let mut rng = crypto_utils::rng(); - rng.fill_bytes(&mut nonce); - nonce + xmtp_common::rand_array::() } pub(super) fn new_pin() -> String { diff --git a/xmtp_mls/src/groups/device_sync/consent_sync.rs b/xmtp_mls/src/groups/device_sync/consent_sync.rs index 82142f863..1d78a0892 100644 --- a/xmtp_mls/src/groups/device_sync/consent_sync.rs +++ b/xmtp_mls/src/groups/device_sync/consent_sync.rs @@ -67,25 +67,31 @@ where } } -#[cfg(all(not(target_arch = "wasm32"), test))] +#[cfg(test)] pub(crate) mod tests { + #[cfg(target_arch = "wasm32")] + wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use wasm_bindgen_test::wasm_bindgen_test; + const HISTORY_SERVER_HOST: &str = "localhost"; const HISTORY_SERVER_PORT: u16 = 5558; - use std::time::{Duration, Instant}; + use xmtp_common::{ + assert_ok, + time::{Duration, Instant}, + }; use super::*; use crate::{ - assert_ok, builder::ClientBuilder, - groups::scoped_client::LocalScopedGroupClient, + groups::scoped_client::ScopedGroupClient, storage::consent_record::{ConsentState, ConsentType}, utils::test::wait_for_min_intents, }; use xmtp_cryptography::utils::generate_local_wallet; use xmtp_id::InboxOwner; - #[tokio::test(flavor = "multi_thread", worker_threads = 1)] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 1))] async fn test_consent_sync() { let history_sync_url = format!("http://{}:{}", HISTORY_SERVER_HOST, HISTORY_SERVER_PORT); diff --git a/xmtp_mls/src/groups/device_sync/message_sync.rs b/xmtp_mls/src/groups/device_sync/message_sync.rs index c2e4976a7..61f8fba05 100644 --- a/xmtp_mls/src/groups/device_sync/message_sync.rs +++ b/xmtp_mls/src/groups/device_sync/message_sync.rs @@ -42,21 +42,27 @@ where } } -#[cfg(all(not(target_arch = "wasm32"), test))] +#[cfg(test)] pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use wasm_bindgen_test::wasm_bindgen_test; use super::*; + use crate::{ - assert_ok, builder::ClientBuilder, groups::GroupMetadataOptions, - utils::test::wait_for_min_intents, utils::test::HISTORY_SYNC_URL, + builder::ClientBuilder, + groups::GroupMetadataOptions, + utils::test::{wait_for_min_intents, HISTORY_SYNC_URL}, + }; + use xmtp_common::{ + assert_ok, + time::{Duration, Instant}, }; - use std::time::{Duration, Instant}; use xmtp_cryptography::utils::generate_local_wallet; use xmtp_id::InboxOwner; - #[tokio::test(flavor = "multi_thread", worker_threads = 1)] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 1))] async fn test_message_history_sync() { let wallet = generate_local_wallet(); let amal_a = ClientBuilder::new_test_client_with_history(&wallet, HISTORY_SYNC_URL).await; @@ -148,7 +154,7 @@ pub(crate) mod tests { } } - #[tokio::test(flavor = "multi_thread", worker_threads = 1)] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 1))] async fn test_prepare_groups_to_sync() { let wallet = generate_local_wallet(); let amal_a = ClientBuilder::new_test_client(&wallet).await; @@ -165,7 +171,7 @@ pub(crate) mod tests { assert_eq!(result.len(), 2); } - #[tokio::test] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 1))] async fn test_externals_cant_join_sync_group() { let wallet = generate_local_wallet(); let amal = ClientBuilder::new_test_client_with_history(&wallet, HISTORY_SYNC_URL).await; @@ -206,20 +212,20 @@ pub(crate) mod tests { assert!(result.is_err()); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_new_pin() { let pin = new_pin(); assert!(pin.chars().all(|c| c.is_numeric())); assert_eq!(pin.len(), 4); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_new_request_id() { let request_id = new_request_id(); assert_eq!(request_id.len(), ENC_KEY_SIZE); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_new_key() { let sig_key = DeviceSyncKeyType::new_aes_256_gcm_key(); let enc_key = DeviceSyncKeyType::new_aes_256_gcm_key(); @@ -229,7 +235,7 @@ pub(crate) mod tests { assert_ne!(sig_key, enc_key); } - #[test] + #[wasm_bindgen_test(unsupported = test)] fn test_generate_nonce() { let nonce_1 = generate_nonce(); let nonce_2 = generate_nonce(); diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 62aedf158..1a1b04594 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -1275,19 +1275,17 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::{ - groups::{ - group_metadata::DmMembers, group_mutable_metadata::MetadataField, - validated_commit::MutableMetadataChanges, - }, - utils::test::{rand_string, rand_vec}, + use crate::groups::{ + group_metadata::DmMembers, group_mutable_metadata::MetadataField, + validated_commit::MutableMetadataChanges, }; + use xmtp_common::{rand_string, rand_vec}; use super::*; fn build_change(inbox_id: Option, is_admin: bool, is_super_admin: bool) -> Inbox { Inbox { - inbox_id: inbox_id.unwrap_or(rand_string()), + inbox_id: inbox_id.unwrap_or(rand_string::<24>()), is_creator: is_super_admin, is_super_admin, is_admin, @@ -1302,8 +1300,8 @@ pub(crate) mod tests { is_super_admin: bool, ) -> CommitParticipant { CommitParticipant { - inbox_id: inbox_id.unwrap_or(rand_string()), - installation_id: installation_id.unwrap_or_else(rand_vec), + inbox_id: inbox_id.unwrap_or(rand_string::<24>()), + installation_id: installation_id.unwrap_or_else(rand_vec::<24>), is_creator: is_super_admin, is_admin, is_super_admin, @@ -1344,7 +1342,13 @@ pub(crate) mod tests { let field_changes = metadata_fields_changed .unwrap_or_default() .into_iter() - .map(|field| MetadataFieldChange::new(field, Some(rand_string()), Some(rand_string()))) + .map(|field| { + MetadataFieldChange::new( + field, + Some(rand_string::<24>()), + Some(rand_string::<24>()), + ) + }) .collect(); let dm_members = if let Some(dm_target_inbox_id) = dm_target_inbox_id { diff --git a/xmtp_mls/src/groups/intents.rs b/xmtp_mls/src/groups/intents.rs index 80f5eb167..883bce431 100644 --- a/xmtp_mls/src/groups/intents.rs +++ b/xmtp_mls/src/groups/intents.rs @@ -93,7 +93,7 @@ impl MlsGroup { fn maybe_insert_key_update_intent(&self, conn: &DbConnection) -> Result<(), GroupError> { let last_rotated_at_ns = conn.get_rotated_at_ns(self.group_id.clone())?; - let now_ns = crate::utils::time::now_ns(); + let now_ns = xmtp_common::time::now_ns(); let elapsed_ns = now_ns - last_rotated_at_ns; if elapsed_ns > GROUP_KEY_ROTATION_INTERVAL_NS { self.queue_intent_with_conn(conn, IntentKind::KeyUpdate, vec![])?; diff --git a/xmtp_mls/src/groups/mls_sync.rs b/xmtp_mls/src/groups/mls_sync.rs index a47ec3f9a..193cfe6aa 100644 --- a/xmtp_mls/src/groups/mls_sync.rs +++ b/xmtp_mls/src/groups/mls_sync.rs @@ -14,13 +14,12 @@ use crate::{ GRPC_DATA_LIMIT, MAX_GROUP_SIZE, MAX_INTENT_PUBLISH_ATTEMPTS, MAX_PAST_EPOCHS, SYNC_UPDATE_INSTALLATIONS_INTERVAL_NS, }, + groups::device_sync::DeviceSyncContent, groups::{intents::UpdateMetadataIntentData, validated_commit::ValidatedCommit}, hpke::{encrypt_welcome, HpkeError}, identity::{parse_credential, IdentityError}, identity_updates::load_identity_updates, intents::ProcessIntentError, - retry::{Retry, RetryableError}, - retry_async, storage::{ db_connection::DbConnection, group_intent::{IntentKind, IntentState, StoredGroupIntent, ID}, @@ -30,11 +29,11 @@ use crate::{ sql_key_store, }, subscriptions::LocalEvents, + subscriptions::SyncMessage, utils::{hash::sha256, id::calculate_message_id}, xmtp_openmls_provider::XmtpOpenMlsProvider, Delete, Fetch, StoreOrIgnore, }; -use crate::{groups::device_sync::DeviceSyncContent, subscriptions::SyncMessage}; use futures::future::try_join_all; use openmls::{ credentials::BasicCredential, @@ -58,6 +57,8 @@ use std::{ mem::{discriminant, Discriminant}, }; use thiserror::Error; +use tracing::debug; +use xmtp_common::{retry_async, Retry, RetryableError}; use xmtp_id::{InboxId, InboxIdRef}; use xmtp_proto::xmtp::mls::{ api::v1::{ @@ -124,7 +125,7 @@ pub enum GroupMessageProcessingError { AssociationDeserialization(#[from] xmtp_id::associations::DeserializationError), } -impl crate::retry::RetryableError for GroupMessageProcessingError { +impl RetryableError for GroupMessageProcessingError { fn is_retryable(&self) -> bool { match self { Self::Diesel(err) => err.is_retryable(), @@ -1178,7 +1179,7 @@ where None => SYNC_UPDATE_INSTALLATIONS_INTERVAL_NS, }; - let now_ns = crate::utils::time::now_ns(); + let now_ns = xmtp_common::time::now_ns(); let last_ns = provider .conn_ref() .get_installations_time_checked(self.group_id.clone())?; diff --git a/xmtp_mls/src/groups/mod.rs b/xmtp_mls/src/groups/mod.rs index 8060040df..f0bddb452 100644 --- a/xmtp_mls/src/groups/mod.rs +++ b/xmtp_mls/src/groups/mod.rs @@ -58,6 +58,7 @@ use self::{ validated_commit::CommitValidationError, }; use std::{collections::HashSet, sync::Arc}; +use xmtp_common::time::now_ns; use xmtp_cryptography::signature::{sanitize_evm_addresses, AddressValidationError}; use xmtp_id::{InboxId, InboxIdRef}; use xmtp_proto::xmtp::mls::{ @@ -83,7 +84,6 @@ use crate::{ identity::{parse_credential, IdentityError}, identity_updates::{load_identity_updates, InstallationDiffError}, intents::ProcessIntentError, - retry::RetryableError, storage::{ consent_record::{ConsentState, ConsentType, StoredConsentRecord}, db_connection::DbConnection, @@ -93,10 +93,11 @@ use crate::{ sql_key_store, }, subscriptions::{LocalEventError, LocalEvents}, - utils::{id::calculate_message_id, time::now_ns}, + utils::id::calculate_message_id, xmtp_openmls_provider::XmtpOpenMlsProvider, Store, }; +use xmtp_common::retry::RetryableError; #[derive(Debug, Error)] pub enum GroupError { @@ -1590,12 +1591,12 @@ pub(crate) mod tests { use openmls::prelude::Member; use prost::Message; use std::sync::Arc; + use xmtp_common::assert_err; use xmtp_cryptography::utils::generate_local_wallet; use xmtp_proto::xmtp::mls::api::v1::group_message::Version; use xmtp_proto::xmtp::mls::message_contents::EncodedContent; use crate::{ - assert_err, builder::ClientBuilder, codecs::{group_updated::GroupUpdatedCodec, ContentCodec}, groups::{ @@ -1913,8 +1914,9 @@ pub(crate) mod tests { #[cfg(not(target_arch = "wasm32"))] fn test_create_from_welcome_validation() { use crate::groups::{build_group_membership_extension, group_membership::GroupMembership}; - use crate::{assert_logged, utils::test::traced_test}; - traced_test(|| async { + use xmtp_common::assert_logged; + xmtp_common::traced_test!(async { + tracing::info!("TEST"); let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; diff --git a/xmtp_mls/src/groups/scoped_client.rs b/xmtp_mls/src/groups/scoped_client.rs index 808fee0e0..af76a67b2 100644 --- a/xmtp_mls/src/groups/scoped_client.rs +++ b/xmtp_mls/src/groups/scoped_client.rs @@ -17,7 +17,7 @@ use xmtp_id::{ }; use xmtp_proto::{api_client::trait_impls::XmtpApi, xmtp::mls::api::v1::GroupMessage}; -#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(ScopedGroupClient: Send ))] +#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(ScopedGroupClient: Send))] #[cfg(not(target_arch = "wasm32"))] #[allow(unused)] pub trait LocalScopedGroupClient: Send + Sync + Sized { diff --git a/xmtp_mls/src/groups/subscriptions.rs b/xmtp_mls/src/groups/subscriptions.rs index 2caf9bec9..a66a4e8e3 100644 --- a/xmtp_mls/src/groups/subscriptions.rs +++ b/xmtp_mls/src/groups/subscriptions.rs @@ -14,8 +14,8 @@ use crate::storage::refresh_state::EntityKind; use crate::storage::StorageError; use crate::subscriptions::MessagesStreamInfo; use crate::subscriptions::SubscribeError; -use crate::{retry::Retry, retry_async}; use prost::Message; +use xmtp_common::{retry_async, Retry}; use xmtp_proto::xmtp::mls::api::v1::GroupMessage; impl MlsGroup { @@ -259,6 +259,8 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use wasm_bindgen_test::wasm_bindgen_test; + use super::*; use tokio_stream::wrappers::UnboundedReceiverStream; use xmtp_cryptography::utils::generate_local_wallet; @@ -269,11 +271,7 @@ pub(crate) mod tests { }; use futures::StreamExt; - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 1) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_decode_group_message_bytes() { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -307,11 +305,7 @@ pub(crate) mod tests { } } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_subscribe_messages() { let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; let bola = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); @@ -364,11 +358,7 @@ pub(crate) mod tests { assert_eq!(second_val.decrypted_message_bytes, "goodbye".as_bytes()); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_subscribe_multiple() { let amal = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let group = Arc::new( @@ -406,11 +396,7 @@ pub(crate) mod tests { } } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 5) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_subscribe_membership_changes() { let amal = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -438,7 +424,7 @@ pub(crate) mod tests { // just to make sure stream is started let _ = start_rx.await; // Adding in a sleep, since the HTTP API client may acknowledge requests before they are ready - crate::sleep(core::time::Duration::from_millis(100)).await; + xmtp_common::time::sleep(core::time::Duration::from_millis(100)).await; amal_group .add_members_by_inbox_id(&[bola.inbox_id()]) diff --git a/xmtp_mls/src/groups/validated_commit.rs b/xmtp_mls/src/groups/validated_commit.rs index 45cb5cc75..f13557236 100644 --- a/xmtp_mls/src/groups/validated_commit.rs +++ b/xmtp_mls/src/groups/validated_commit.rs @@ -24,10 +24,9 @@ use xmtp_proto::xmtp::{ use crate::{ configuration::GROUP_MEMBERSHIP_EXTENSION_ID, identity_updates::{InstallationDiff, InstallationDiffError}, - retry::RetryableError, - retryable, storage::db_connection::DbConnection, }; +use xmtp_common::{retry::RetryableError, retryable}; use super::{ group_membership::{GroupMembership, MembershipDiff}, diff --git a/xmtp_mls/src/hpke.rs b/xmtp_mls/src/hpke.rs index 19906a351..cf664043a 100644 --- a/xmtp_mls/src/hpke.rs +++ b/xmtp_mls/src/hpke.rs @@ -1,7 +1,5 @@ use crate::{ configuration::{CIPHERSUITE, WELCOME_HPKE_LABEL}, - retry::RetryableError, - retryable, storage::sql_key_store::{SqlKeyStoreError, KEY_PACKAGE_REFERENCES}, xmtp_openmls_provider::XmtpOpenMlsProvider, }; @@ -17,6 +15,7 @@ use openmls_rust_crypto::RustCrypto; use openmls_traits::OpenMlsProvider; use openmls_traits::{storage::StorageProvider, types::HpkeCiphertext}; use thiserror::Error; +use xmtp_common::{retryable, RetryableError}; #[derive(Debug, Error)] pub enum HpkeError { diff --git a/xmtp_mls/src/identity.rs b/xmtp_mls/src/identity.rs index 0b73a784d..c02626729 100644 --- a/xmtp_mls/src/identity.rs +++ b/xmtp_mls/src/identity.rs @@ -1,7 +1,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use crate::configuration::GROUP_PERMISSIONS_EXTENSION_ID; -use crate::retry::RetryableError; use crate::storage::db_connection::DbConnection; use crate::storage::identity::StoredIdentity; use crate::storage::sql_key_store::{SqlKeyStore, SqlKeyStoreError, KEY_PACKAGE_REFERENCES}; @@ -11,9 +10,8 @@ use crate::{ configuration::{CIPHERSUITE, GROUP_MEMBERSHIP_EXTENSION_ID, MUTABLE_METADATA_EXTENSION_ID}, storage::StorageError, xmtp_openmls_provider::XmtpOpenMlsProvider, - XmtpApi, + Fetch, Store, XmtpApi, }; -use crate::{retryable, Fetch, Store}; use openmls::prelude::hash_ref::HashReference; use openmls::{ credentials::{errors::BasicCredentialError, BasicCredential, CredentialWithKey}, @@ -31,6 +29,7 @@ use prost::Message; use thiserror::Error; use tracing::debug; use tracing::info; +use xmtp_common::{retryable, RetryableError}; use xmtp_cryptography::{CredentialSign, XmtpInstallationCredential}; use xmtp_id::associations::unverified::UnverifiedSignature; use xmtp_id::associations::{AssociationError, InstallationKeyContext, PublicContext}; diff --git a/xmtp_mls/src/identity_updates.rs b/xmtp_mls/src/identity_updates.rs index e4a6cef10..822c00bac 100644 --- a/xmtp_mls/src/identity_updates.rs +++ b/xmtp_mls/src/identity_updates.rs @@ -1,11 +1,8 @@ -use crate::{ - retry::{Retry, RetryableError}, - retry_async, retryable, - storage::association_state::StoredAssociationState, -}; +use crate::storage::association_state::StoredAssociationState; use futures::future::try_join_all; use std::collections::{HashMap, HashSet}; use thiserror::Error; +use xmtp_common::{retry_async, retryable, Retry, RetryableError}; use xmtp_cryptography::CredentialSign; use xmtp_id::{ associations::{ @@ -593,9 +590,10 @@ pub(crate) mod tests { builder::ClientBuilder, groups::group_membership::GroupMembership, storage::{db_connection::DbConnection, identity_update::StoredIdentityUpdate}, - utils::test::{rand_vec, FullXmtpClient}, + utils::test::FullXmtpClient, Client, XmtpApi, }; + use xmtp_common::rand_vec; use super::{is_member_of_association_state, load_identity_updates}; @@ -620,7 +618,7 @@ pub(crate) mod tests { fn insert_identity_update(conn: &DbConnection, inbox_id: &str, sequence_id: i64) { let identity_update = - StoredIdentityUpdate::new(inbox_id.to_string(), sequence_id, 0, rand_vec()); + StoredIdentityUpdate::new(inbox_id.to_string(), sequence_id, 0, rand_vec::<24>()); conn.insert_or_ignore_identity_updates(&[identity_update]) .expect("insert should succeed"); @@ -730,8 +728,8 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg(not(target_arch = "wasm32"))] fn cache_association_state() { - use crate::{assert_logged, utils::test::traced_test}; - traced_test(|| async { + use xmtp_common::assert_logged; + xmtp_common::traced_test!(async { let wallet = generate_local_wallet(); let wallet_2 = generate_local_wallet(); let wallet_address = wallet.get_address(); diff --git a/xmtp_mls/src/intents.rs b/xmtp_mls/src/intents.rs index 7f54daa6d..90156af9a 100644 --- a/xmtp_mls/src/intents.rs +++ b/xmtp_mls/src/intents.rs @@ -10,12 +10,12 @@ use crate::{ client::XmtpMlsLocalContext, - retry::RetryableError, storage::{refresh_state::EntityKind, EncryptedMessageStore}, xmtp_openmls_provider::XmtpOpenMlsProvider, }; use std::{future::Future, sync::Arc}; use thiserror::Error; +use xmtp_common::RetryableError; #[derive(Debug, Error)] pub enum ProcessIntentError { diff --git a/xmtp_mls/src/lib.rs b/xmtp_mls/src/lib.rs index fb21ba10b..83d744f13 100644 --- a/xmtp_mls/src/lib.rs +++ b/xmtp_mls/src/lib.rs @@ -12,11 +12,9 @@ pub mod identity; pub mod identity_updates; mod intents; mod mutex_registry; -pub mod retry; pub mod storage; mod stream_handles; pub mod subscriptions; -pub mod types; pub mod utils; pub mod verified_key_package_v2; mod xmtp_openmls_provider; @@ -28,15 +26,6 @@ pub use xmtp_openmls_provider::XmtpOpenMlsProvider; pub use xmtp_id::InboxOwner; pub use xmtp_proto::api_client::trait_impls::*; -#[macro_use] -extern crate tracing; - -/// Global Marker trait for WebAssembly -#[cfg(target_arch = "wasm32")] -pub trait Wasm {} -#[cfg(target_arch = "wasm32")] -impl Wasm for T {} - /// Inserts a model to the underlying data store, erroring if it already exists pub trait Store { fn store(&self, into: &StorageConnection) -> Result<(), StorageError>; @@ -79,138 +68,17 @@ pub use stream_handles::{ spawn, AbortHandle, GenericStreamHandle, StreamHandle, StreamHandleError, }; -#[cfg(target_arch = "wasm32")] -#[doc(hidden)] -pub async fn sleep(duration: core::time::Duration) { - gloo_timers::future::TimeoutFuture::new(duration.as_millis() as u32).await; -} - -#[cfg(not(target_arch = "wasm32"))] -#[doc(hidden)] -pub async fn sleep(duration: core::time::Duration) { - tokio::time::sleep(duration).await -} - -/// Turn the `Result` into an `Option`, logging the error with `tracing::error` and -/// returning `None` if the value matches on Result::Err(). -/// Optionally pass a message as the second argument. -#[macro_export] -macro_rules! optify { - ( $e: expr ) => { - match $e { - Ok(v) => Some(v), - Err(e) => { - tracing::error!("{}", e); - None - } - } - }; - ( $e: expr, $msg: tt ) => { - match $e { - Ok(v) => Some(v), - Err(e) => { - tracing::error!("{}: {:?}", $msg, e); - None - } - } - }; -} - #[cfg(test)] pub(crate) mod tests { // Execute once before any tests are run #[cfg_attr(not(target_arch = "wasm32"), ctor::ctor)] #[cfg(not(target_arch = "wasm32"))] fn _setup() { - use tracing_subscriber::{ - fmt::{self, format}, - layer::SubscriberExt, - util::SubscriberInitExt, - EnvFilter, Layer, - }; - - let structured = std::env::var("STRUCTURED"); - let is_structured = matches!(structured, Ok(s) if s == "true" || s == "1"); - - let filter = || { - EnvFilter::builder() - .with_default_directive(tracing::metadata::LevelFilter::INFO.into()) - .from_env_lossy() - }; - - tracing_subscriber::registry() - // structured JSON logger - .with(is_structured.then(|| { - tracing_subscriber::fmt::layer() - .json() - .flatten_event(true) - .with_level(true) - .with_filter(filter()) - })) - // default logger - .with((!is_structured).then(|| { - fmt::layer() - .compact() - .fmt_fields({ - format::debug_fn(move |writer, field, value| { - if field.name() == "message" { - write!(writer, "{:?}", value)?; - } - Ok(()) - }) - }) - .with_filter(filter()) - })) - .init(); + xmtp_common::logger() } +} - /// wrapper over assert!(matches!()) for Errors - /// assert_err!(fun(), StorageError::Explosion) - /// - /// or the message variant, - /// assert_err!(fun(), StorageError::Explosion, "the storage did not explode"); - #[macro_export] - macro_rules! assert_err { - ( $x:expr , $y:pat $(,)? ) => { - assert!(matches!($x, Err($y))) - }; - - ( $x:expr, $y:pat $(,)?, $($msg:tt)+) => {{ - assert!(matches!($x, Err($y)), $($msg)+) - }} - } - - /// wrapper over assert! macros for Ok's - /// - /// Make sure something is Ok(_) without caring about return value. - /// assert_ok!(fun()); - /// - /// Against an expected value, e.g Ok(true) - /// assert_ok!(fun(), true); - /// - /// or the message variant, - /// assert_ok!(fun(), Ok(_), "the storage is not ok"); - #[macro_export] - macro_rules! assert_ok { - - ( $e:expr ) => { - assert_ok!($e,) - }; - - ( $e:expr, ) => {{ - use std::result::Result::*; - match $e { - Ok(v) => v, - Err(e) => panic!("assertion failed: Err({:?})", e), - } - }}; - - ( $x:expr , $y:expr $(,)? ) => { - assert_eq!($x, Ok($y.into())); - }; - - ( $x:expr, $y:expr $(,)?, $($msg:tt)+) => {{ - assert_eq!($x, Ok($y.into()), $($msg)+); - }} - } +pub mod types { + pub type Address = String; + pub type InstallationId = String; } diff --git a/xmtp_mls/src/storage/encrypted_store/group.rs b/xmtp_mls/src/storage/encrypted_store/group.rs index 1bd426db7..ee1ae2d00 100644 --- a/xmtp_mls/src/storage/encrypted_store/group.rs +++ b/xmtp_mls/src/storage/encrypted_store/group.rs @@ -375,7 +375,7 @@ impl DbConnection { /// Updates the 'last time checked' we checked for new installations. pub fn update_rotated_at_ns(&self, group_id: Vec) -> Result<(), StorageError> { self.raw_query(|conn| { - let now = crate::utils::time::now_ns(); + let now = xmtp_common::time::now_ns(); diesel::update(dsl::groups.find(&group_id)) .set(dsl::rotated_at_ns.eq(now)) .execute(conn) @@ -403,7 +403,7 @@ impl DbConnection { /// Updates the 'last time checked' we checked for new installations. pub fn update_installations_time_checked(&self, group_id: Vec) -> Result<(), StorageError> { self.raw_query(|conn| { - let now = crate::utils::time::now_ns(); + let now = xmtp_common::time::now_ns(); diesel::update(dsl::groups.find(&group_id)) .set(dsl::installations_last_checked.eq(now)) .execute(conn) @@ -535,18 +535,17 @@ pub(crate) mod tests { use super::*; use crate::{ - assert_ok, storage::{ consent_record::{ConsentType, StoredConsentRecord}, encrypted_store::{schema::groups::dsl::groups, tests::with_connection}, }, - utils::{test::rand_vec, time::now_ns}, Fetch, Store, }; + use xmtp_common::{assert_ok, rand_vec, time::now_ns}; /// Generate a test group pub fn generate_group(state: Option) -> StoredGroup { - let id = rand_vec(); + let id = rand_vec::<24>(); let created_at_ns = now_ns(); let membership_state = state.unwrap_or(GroupMembershipState::Allowed); StoredGroup::new( @@ -573,7 +572,7 @@ pub(crate) mod tests { /// Generate a test dm group pub fn generate_dm(state: Option) -> StoredGroup { - let id = rand_vec(); + let id = rand_vec::<24>(); let created_at_ns = now_ns(); let membership_state = state.unwrap_or(GroupMembershipState::Allowed); let dm_inbox_id = Some("placeholder_inbox_id".to_string()); @@ -761,7 +760,7 @@ pub(crate) mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_new_sync_group() { with_connection(|conn| { - let id = rand_vec(); + let id = rand_vec::<24>(); let created_at_ns = now_ns(); let membership_state = GroupMembershipState::Allowed; diff --git a/xmtp_mls/src/storage/encrypted_store/group_intent.rs b/xmtp_mls/src/storage/encrypted_store/group_intent.rs index a45a818c3..2cc872a3c 100644 --- a/xmtp_mls/src/storage/encrypted_store/group_intent.rs +++ b/xmtp_mls/src/storage/encrypted_store/group_intent.rs @@ -400,9 +400,9 @@ pub(crate) mod tests { group::{GroupMembershipState, StoredGroup}, tests::with_connection, }, - utils::test::rand_vec, Fetch, Store, }; + use xmtp_common::rand_vec; fn insert_group(conn: &DbConnection, group_id: Vec) { let group = StoredGroup::new( @@ -445,8 +445,8 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_store_and_fetch() { - let group_id = rand_vec(); - let data = rand_vec(); + let group_id = rand_vec::<24>(); + let data = rand_vec::<24>(); let kind = IntentKind::UpdateGroupMembership; let state = IntentState::ToPublish; @@ -479,25 +479,25 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_query() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); let test_intents: Vec = vec![ NewGroupIntent::new_test( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), IntentState::ToPublish, ), NewGroupIntent::new_test( IntentKind::KeyUpdate, group_id.clone(), - rand_vec(), + rand_vec::<24>(), IntentState::Published, ), NewGroupIntent::new_test( IntentKind::KeyUpdate, group_id.clone(), - rand_vec(), + rand_vec::<24>(), IntentState::Committed, ), ]; @@ -559,7 +559,7 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn find_by_payload_hash() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); with_connection(|conn| { insert_group(conn, group_id.clone()); @@ -568,7 +568,7 @@ pub(crate) mod tests { NewGroupIntent::new( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), ) .store(conn) .unwrap(); @@ -577,8 +577,8 @@ pub(crate) mod tests { let intent = find_first_intent(conn, group_id.clone()); // Set the payload hash - let payload_hash = rand_vec(); - let post_commit_data = rand_vec(); + let payload_hash = rand_vec::<24>(); + let post_commit_data = rand_vec::<24>(); conn.set_group_intent_published( intent.id, payload_hash.clone(), @@ -602,7 +602,7 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_happy_path_state_transitions() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); with_connection(|conn| { insert_group(conn, group_id.clone()); @@ -611,7 +611,7 @@ pub(crate) mod tests { NewGroupIntent::new( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), ) .store(conn) .unwrap(); @@ -619,8 +619,8 @@ pub(crate) mod tests { let mut intent = find_first_intent(conn, group_id.clone()); // Set to published - let payload_hash = rand_vec(); - let post_commit_data = rand_vec(); + let payload_hash = rand_vec::<24>(); + let post_commit_data = rand_vec::<24>(); conn.set_group_intent_published( intent.id, payload_hash.clone(), @@ -648,7 +648,7 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_republish_state_transition() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); with_connection(|conn| { insert_group(conn, group_id.clone()); @@ -657,7 +657,7 @@ pub(crate) mod tests { NewGroupIntent::new( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), ) .store(conn) .unwrap(); @@ -665,8 +665,8 @@ pub(crate) mod tests { let mut intent = find_first_intent(conn, group_id.clone()); // Set to published - let payload_hash = rand_vec(); - let post_commit_data = rand_vec(); + let payload_hash = rand_vec::<24>(); + let post_commit_data = rand_vec::<24>(); conn.set_group_intent_published( intent.id, payload_hash.clone(), @@ -693,7 +693,7 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_invalid_state_transition() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); with_connection(|conn| { insert_group(conn, group_id.clone()); @@ -702,7 +702,7 @@ pub(crate) mod tests { NewGroupIntent::new( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), ) .store(conn) .unwrap(); @@ -729,13 +729,13 @@ pub(crate) mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_increment_publish_attempts() { - let group_id = rand_vec(); + let group_id = rand_vec::<24>(); with_connection(|conn| { insert_group(conn, group_id.clone()); NewGroupIntent::new( IntentKind::UpdateGroupMembership, group_id.clone(), - rand_vec(), + rand_vec::<24>(), ) .store(conn) .unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/group_message.rs b/xmtp_mls/src/storage/encrypted_store/group_message.rs index 7976a030c..b273e615d 100644 --- a/xmtp_mls/src/storage/encrypted_store/group_message.rs +++ b/xmtp_mls/src/storage/encrypted_store/group_message.rs @@ -284,11 +284,10 @@ pub(crate) mod tests { use super::*; use crate::{ - assert_err, assert_ok, storage::encrypted_store::{group::tests::generate_group, tests::with_connection}, - utils::test::{rand_time, rand_vec}, Store, }; + use xmtp_common::{assert_err, assert_ok, rand_time, rand_vec}; fn generate_message( kind: Option, @@ -296,11 +295,11 @@ pub(crate) mod tests { sent_at_ns: Option, ) -> StoredGroupMessage { StoredGroupMessage { - id: rand_vec(), - group_id: group_id.map(<[u8]>::to_vec).unwrap_or(rand_vec()), - decrypted_message_bytes: rand_vec(), + id: rand_vec::<24>(), + group_id: group_id.map(<[u8]>::to_vec).unwrap_or(rand_vec::<24>()), + decrypted_message_bytes: rand_vec::<24>(), sent_at_ns: sent_at_ns.unwrap_or(rand_time()), - sender_installation_id: rand_vec(), + sender_installation_id: rand_vec::<24>(), sender_inbox_id: "0x0".to_string(), kind: kind.unwrap_or(GroupMessageKind::Application), delivery_status: DeliveryStatus::Unpublished, diff --git a/xmtp_mls/src/storage/encrypted_store/identity.rs b/xmtp_mls/src/storage/encrypted_store/identity.rs index 4051036c5..f6f973b8f 100644 --- a/xmtp_mls/src/storage/encrypted_store/identity.rs +++ b/xmtp_mls/src/storage/encrypted_store/identity.rs @@ -71,7 +71,8 @@ pub(crate) mod tests { super::{EncryptedMessageStore, StorageOption}, StoredIdentity, }; - use crate::{utils::test::rand_vec, Store}; + use crate::Store; + use xmtp_common::rand_vec; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] @@ -84,12 +85,12 @@ pub(crate) mod tests { .unwrap(); let conn = &store.conn().unwrap(); - StoredIdentity::new("".to_string(), rand_vec(), rand_vec()) + StoredIdentity::new("".to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn) .unwrap(); let duplicate_insertion = - StoredIdentity::new("".to_string(), rand_vec(), rand_vec()).store(conn); + StoredIdentity::new("".to_string(), rand_vec::<24>(), rand_vec::<24>()).store(conn); assert!(duplicate_insertion.is_err()); } } diff --git a/xmtp_mls/src/storage/encrypted_store/identity_update.rs b/xmtp_mls/src/storage/encrypted_store/identity_update.rs index 74eb878d3..1c5c6b564 100644 --- a/xmtp_mls/src/storage/encrypted_store/identity_update.rs +++ b/xmtp_mls/src/storage/encrypted_store/identity_update.rs @@ -134,16 +134,18 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); - use crate::{ - storage::encrypted_store::tests::with_connection, - utils::test::{rand_time, rand_vec}, - Store, - }; + use crate::{storage::encrypted_store::tests::with_connection, Store}; + use xmtp_common::{rand_time, rand_vec}; use super::*; fn build_update(inbox_id: &str, sequence_id: i64) -> StoredIdentityUpdate { - StoredIdentityUpdate::new(inbox_id.to_string(), sequence_id, rand_time(), rand_vec()) + StoredIdentityUpdate::new( + inbox_id.to_string(), + sequence_id, + rand_time(), + rand_vec::<24>(), + ) } #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] diff --git a/xmtp_mls/src/storage/encrypted_store/key_package_history.rs b/xmtp_mls/src/storage/encrypted_store/key_package_history.rs index 7947abb0a..9e43243c0 100644 --- a/xmtp_mls/src/storage/encrypted_store/key_package_history.rs +++ b/xmtp_mls/src/storage/encrypted_store/key_package_history.rs @@ -1,7 +1,8 @@ use diesel::prelude::*; use super::{db_connection::DbConnection, schema::key_package_history, StorageError}; -use crate::{impl_store_or_ignore, utils::time::now_ns, StoreOrIgnore}; +use crate::{impl_store_or_ignore, StoreOrIgnore}; +use xmtp_common::time::now_ns; #[derive(Insertable, Debug, Clone)] #[diesel(table_name = key_package_history)] @@ -78,7 +79,8 @@ impl DbConnection { #[cfg(test)] mod tests { - use crate::{storage::encrypted_store::tests::with_connection, utils::test::rand_vec}; + use crate::storage::encrypted_store::tests::with_connection; + use xmtp_common::rand_vec; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); @@ -86,7 +88,7 @@ mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_store_key_package_history_entry() { with_connection(|conn| { - let hash_ref = rand_vec(); + let hash_ref = rand_vec::<24>(); let new_entry = conn .store_key_package_history_entry(hash_ref.clone()) .unwrap(); @@ -100,9 +102,9 @@ mod tests { #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn test_store_multiple() { with_connection(|conn| { - let hash_ref1 = rand_vec(); - let hash_ref2 = rand_vec(); - let hash_ref3 = rand_vec(); + let hash_ref1 = rand_vec::<24>(); + let hash_ref2 = rand_vec::<24>(); + let hash_ref3 = rand_vec::<24>(); conn.store_key_package_history_entry(hash_ref1.clone()) .unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/mod.rs b/xmtp_mls/src/storage/encrypted_store/mod.rs index bc72fa7cc..b2c045492 100644 --- a/xmtp_mls/src/storage/encrypted_store/mod.rs +++ b/xmtp_mls/src/storage/encrypted_store/mod.rs @@ -458,6 +458,7 @@ where pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker); + use wasm_bindgen_test::wasm_bindgen_test; use super::*; use crate::{ @@ -465,9 +466,9 @@ pub(crate) mod tests { group::{GroupMembershipState, StoredGroup}, identity::StoredIdentity, }, - utils::test::{rand_vec, tmp_path}, Fetch, Store, StreamHandle as _, }; + use xmtp_common::{rand_vec, tmp_path}; /// Test harness that loads an Ephemeral store. pub async fn with_connection(fun: F) -> R @@ -496,8 +497,7 @@ pub(crate) mod tests { } } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] + #[wasm_bindgen_test(unsupported = tokio::test)] async fn ephemeral_store() { let store = EncryptedMessageStore::new( StorageOption::Ephemeral, @@ -508,7 +508,7 @@ pub(crate) mod tests { let conn = &store.conn().unwrap(); let inbox_id = "inbox_id"; - StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) + StoredIdentity::new(inbox_id.to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn) .unwrap(); @@ -516,8 +516,7 @@ pub(crate) mod tests { assert_eq!(fetched_identity.inbox_id, inbox_id); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] + #[wasm_bindgen_test(unsupported = tokio::test)] async fn persistent_store() { let db_path = tmp_path(); { @@ -530,7 +529,7 @@ pub(crate) mod tests { let conn = &store.conn().unwrap(); let inbox_id = "inbox_id"; - StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) + StoredIdentity::new(inbox_id.to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn) .unwrap(); @@ -539,10 +538,8 @@ pub(crate) mod tests { } EncryptedMessageStore::remove_db_files(db_path) } - - // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] #[cfg(not(target_arch = "wasm32"))] + #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] async fn releases_db_lock() { let db_path = tmp_path(); { @@ -555,7 +552,7 @@ pub(crate) mod tests { let conn = &store.conn().unwrap(); let inbox_id = "inbox_id"; - StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) + StoredIdentity::new(inbox_id.to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn) .unwrap(); @@ -574,8 +571,7 @@ pub(crate) mod tests { EncryptedMessageStore::remove_db_files(db_path) } - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] - #[cfg(not(target_arch = "wasm32"))] + #[wasm_bindgen_test(unsupported = tokio::test)] async fn mismatched_encryption_key() { let mut enc_key = [1u8; 32]; @@ -587,9 +583,13 @@ pub(crate) mod tests { .await .unwrap(); - StoredIdentity::new("dummy_address".to_string(), rand_vec(), rand_vec()) - .store(&store.conn().unwrap()) - .unwrap(); + StoredIdentity::new( + "dummy_address".to_string(), + rand_vec::<24>(), + rand_vec::<24>(), + ) + .store(&store.conn().unwrap()) + .unwrap(); } // Drop it enc_key[3] = 145; // Alter the enc_key @@ -604,8 +604,7 @@ pub(crate) mod tests { EncryptedMessageStore::remove_db_files(db_path) } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] + #[wasm_bindgen_test(unsupported = tokio::test)] async fn encrypted_db_with_multiple_connections() { let db_path = tmp_path(); { @@ -618,7 +617,7 @@ pub(crate) mod tests { let conn1 = &store.conn().unwrap(); let inbox_id = "inbox_id"; - StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) + StoredIdentity::new(inbox_id.to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn1) .unwrap(); @@ -656,7 +655,7 @@ pub(crate) mod tests { let handle = std::thread::spawn(move || { store_pointer.transaction(|provider| { let conn1 = provider.conn_ref(); - StoredIdentity::new("correct".to_string(), rand_vec(), rand_vec()) + StoredIdentity::new("correct".to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn1) .unwrap(); // wait for second transaction to start @@ -722,7 +721,7 @@ pub(crate) mod tests { store_pointer .transaction_async(|provider| async move { let conn1 = provider.conn_ref(); - StoredIdentity::new("crab".to_string(), rand_vec(), rand_vec()) + StoredIdentity::new("crab".to_string(), rand_vec::<24>(), rand_vec::<24>()) .store(conn1) .unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs b/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs index 25dfb379f..fe9350b26 100644 --- a/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs +++ b/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs @@ -304,9 +304,10 @@ fn pragma_plaintext_header() -> impl Display { #[cfg(test)] mod tests { - use crate::{storage::EncryptedMessageStore, utils::test::tmp_path}; + use crate::storage::EncryptedMessageStore; use diesel_migrations::MigrationHarness; use std::fs::File; + use xmtp_common::tmp_path; use super::*; const SQLITE3_PLAINTEXT_HEADER: &str = "SQLite format 3\0"; diff --git a/xmtp_mls/src/storage/errors.rs b/xmtp_mls/src/storage/errors.rs index f109b0248..de25850ab 100644 --- a/xmtp_mls/src/storage/errors.rs +++ b/xmtp_mls/src/storage/errors.rs @@ -3,9 +3,11 @@ use std::sync::PoisonError; use diesel::result::DatabaseErrorKind; use thiserror::Error; -use crate::{groups::intents::IntentError, retry::RetryableError, retryable}; - use super::sql_key_store; +use crate::groups::intents::IntentError; +use xmtp_common::{retryable, RetryableError}; + +pub struct Mls; #[derive(Debug, Error)] pub enum StorageError { @@ -66,7 +68,7 @@ impl From> for StorageError { } } -impl RetryableError for diesel::result::Error { +impl RetryableError for diesel::result::Error { fn is_retryable(&self) -> bool { use diesel::result::Error::*; use DatabaseErrorKind::*; @@ -101,7 +103,7 @@ impl RetryableError for StorageError { } // OpenMLS KeyStore errors -impl RetryableError for openmls::group::AddMembersError { +impl RetryableError for openmls::group::AddMembersError { fn is_retryable(&self) -> bool { match self { Self::CreateCommitError(commit) => retryable!(commit), @@ -112,7 +114,7 @@ impl RetryableError for openmls::group::AddMembersError { +impl RetryableError for openmls::group::CreateCommitError { fn is_retryable(&self) -> bool { match self { Self::KeyStoreError(storage) => retryable!(storage), @@ -122,7 +124,9 @@ impl RetryableError for openmls::group::CreateCommitError { +impl RetryableError + for openmls::treesync::LeafNodeUpdateError +{ fn is_retryable(&self) -> bool { match self { Self::Storage(storage) => retryable!(storage), @@ -131,13 +135,13 @@ impl RetryableError for openmls::treesync::LeafNodeUpdateError for openmls::key_packages::errors::KeyPackageNewError { fn is_retryable(&self) -> bool { matches!(self, Self::StorageError) } } -impl RetryableError for openmls::group::RemoveMembersError { +impl RetryableError for openmls::group::RemoveMembersError { fn is_retryable(&self) -> bool { match self { Self::CreateCommitError(commit) => retryable!(commit), @@ -148,7 +152,7 @@ impl RetryableError for openmls::group::RemoveMembersError { +impl RetryableError for openmls::group::NewGroupError { fn is_retryable(&self) -> bool { match self { Self::StorageError(storage) => retryable!(storage), @@ -157,7 +161,7 @@ impl RetryableError for openmls::group::NewGroupError for openmls::group::UpdateGroupMembershipError { fn is_retryable(&self) -> bool { @@ -170,13 +174,13 @@ impl RetryableError } } -impl RetryableError for openmls::prelude::MlsGroupStateError { +impl RetryableError for openmls::prelude::MlsGroupStateError { fn is_retryable(&self) -> bool { false } } -impl RetryableError +impl RetryableError for openmls::prelude::CreateGroupContextExtProposalError { fn is_retryable(&self) -> bool { @@ -188,7 +192,7 @@ impl RetryableError } } -impl RetryableError for openmls::group::SelfUpdateError { +impl RetryableError for openmls::group::SelfUpdateError { fn is_retryable(&self) -> bool { match self { Self::CreateCommitError(commit) => retryable!(commit), @@ -199,7 +203,7 @@ impl RetryableError for openmls::group::SelfUpdateError for openmls::prelude::CreationFromExternalError { fn is_retryable(&self) -> bool { @@ -210,7 +214,7 @@ impl RetryableError } } -impl RetryableError for openmls::prelude::WelcomeError { +impl RetryableError for openmls::prelude::WelcomeError { fn is_retryable(&self) -> bool { match self { Self::PublicGroupError(creation_err) => retryable!(creation_err), @@ -220,7 +224,7 @@ impl RetryableError for openmls::prelude::WelcomeError { +impl RetryableError for openmls::group::MergeCommitError { fn is_retryable(&self) -> bool { match self { Self::StorageError(storage) => retryable!(storage), @@ -229,7 +233,9 @@ impl RetryableError for openmls::group::MergeCommitError { +impl RetryableError + for openmls::group::MergePendingCommitError +{ fn is_retryable(&self) -> bool { match self { Self::MlsGroupStateError(err) => retryable!(err), @@ -238,7 +244,7 @@ impl RetryableError for openmls::group::MergePendingCommitError for openmls::prelude::ProcessMessageError { fn is_retryable(&self) -> bool { match self { Self::GroupStateError(err) => retryable!(err), diff --git a/xmtp_mls/src/storage/sql_key_store.rs b/xmtp_mls/src/storage/sql_key_store.rs index ae9d2d797..1ad7aa674 100644 --- a/xmtp_mls/src/storage/sql_key_store.rs +++ b/xmtp_mls/src/storage/sql_key_store.rs @@ -1,4 +1,4 @@ -use crate::{retry::RetryableError, retryable}; +use xmtp_common::{retryable, RetryableError}; use super::encrypted_store::db_connection::DbConnectionPrivate; use bincode; @@ -1041,9 +1041,9 @@ pub(crate) mod tests { use crate::{ configuration::CIPHERSUITE, storage::{sql_key_store::SqlKeyStoreError, EncryptedMessageStore, StorageOption}, - utils::test::tmp_path, xmtp_openmls_provider::XmtpOpenMlsProvider, }; + use xmtp_common::tmp_path; #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] #[cfg_attr(not(target_arch = "wasm32"), tokio::test)] diff --git a/xmtp_mls/src/subscriptions.rs b/xmtp_mls/src/subscriptions.rs index 67606dae8..bac20877d 100644 --- a/xmtp_mls/src/subscriptions.rs +++ b/xmtp_mls/src/subscriptions.rs @@ -13,8 +13,6 @@ use xmtp_proto::{api_client::XmtpMlsStreams, xmtp::mls::api::v1::WelcomeMessage} use crate::{ client::{extract_welcome_message, ClientError}, groups::{mls_sync::GroupMessageProcessingError, subscriptions, GroupError, MlsGroup}, - retry::{Retry, RetryableError}, - retry_async, retryable, storage::{ consent_record::StoredConsentRecord, group::{ConversationType, GroupQueryArgs, StoredGroup}, @@ -24,6 +22,7 @@ use crate::{ Client, XmtpApi, }; use thiserror::Error; +use xmtp_common::{retry_async, retryable, Retry, RetryableError}; #[derive(Debug, Error)] pub enum LocalEventError { @@ -108,7 +107,7 @@ where #[instrument(level = "trace", skip_all)] fn stream_sync_messages(self) -> impl Stream, SubscribeError>> { BroadcastStream::new(self).filter_map(|event| async { - crate::optify!(event, "Missed message due to event queue lag") + xmtp_common::optify!(event, "Missed message due to event queue lag") .and_then(LocalEvents::sync_filter) .map(Result::Ok) }) @@ -118,7 +117,7 @@ where self, ) -> impl Stream, SubscribeError>> { BroadcastStream::new(self).filter_map(|event| async { - crate::optify!(event, "Missed message due to event queue lag") + xmtp_common::optify!(event, "Missed message due to event queue lag") .and_then(LocalEvents::consent_filter) .map(Result::Ok) }) @@ -276,7 +275,7 @@ where self.local_events.subscribe(), ) .filter_map(|event| async { - crate::optify!(event, "Missed messages due to event queue lag") + xmtp_common::optify!(event, "Missed messages due to event queue lag") .and_then(LocalEvents::group_filter) .map(Result::Ok) }); @@ -510,10 +509,10 @@ pub(crate) mod tests { atomic::{AtomicU64, Ordering}, Arc, }; + use wasm_bindgen_test::wasm_bindgen_test; use xmtp_cryptography::utils::generate_local_wallet; - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test(flavor = "current_thread"))] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_stream_welcomes() { let alice = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bob = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); @@ -548,12 +547,9 @@ pub(crate) mod tests { assert_eq!(bob_received_groups.group_id, group_id); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_stream_messages() { + xmtp_common::logger(); let alice = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bob = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -561,7 +557,6 @@ pub(crate) mod tests { .create_group(None, GroupMetadataOptions::default()) .unwrap(); - // let mut bob_stream = bob.stream_conversations().await.unwrap()warning: unused implementer of `futures::Future` that must be used; alice_group .add_members_by_inbox_id(&[bob.inbox_id()]) .await @@ -572,10 +567,10 @@ pub(crate) mod tests { .unwrap(); let bob_group = bob_group.first().unwrap(); - let notify = Delivery::new(None); - let notify_ptr = notify.clone(); - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - crate::spawn(None, async move { + // let notify = Delivery::new(None); + // let notify_ptr = notify.clone(); + // let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + /*crate::spawn(None, async move { let stream = alice_group.stream().await.unwrap(); futures::pin_mut!(stream); while let Some(item) = stream.next().await { @@ -583,26 +578,25 @@ pub(crate) mod tests { notify_ptr.notify_one(); } }); - let mut stream = tokio_stream::wrappers::UnboundedReceiverStream::new(rx); - + */ + // let mut stream = tokio_stream::wrappers::UnboundedReceiverStream::new(rx); + let stream = alice_group.stream().await.unwrap(); + futures::pin_mut!(stream); bob_group.send_message(b"hello").await.unwrap(); - notify.wait_for_delivery().await.unwrap(); + tracing::debug!("Bob Sent Message!, waiting for delivery"); + // notify.wait_for_delivery().await.unwrap(); let message = stream.next().await.unwrap().unwrap(); assert_eq!(message.decrypted_message_bytes, b"hello"); bob_group.send_message(b"hello2").await.unwrap(); - notify.wait_for_delivery().await.unwrap(); + // notify.wait_for_delivery().await.unwrap(); let message = stream.next().await.unwrap().unwrap(); assert_eq!(message.decrypted_message_bytes, b"hello2"); // assert_eq!(bob_received_groups.group_id, alice_bob_group.group_id); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_stream_all_messages_unchanging_group_list() { let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -623,7 +617,7 @@ pub(crate) mod tests { .add_members_by_inbox_id(&[caro.inbox_id()]) .await .unwrap(); - crate::sleep(core::time::Duration::from_millis(100)).await; + xmtp_common::time::sleep(core::time::Duration::from_millis(100)).await; let messages: Arc>> = Arc::new(Mutex::new(Vec::new())); let messages_clone = messages.clone(); @@ -659,11 +653,7 @@ pub(crate) mod tests { assert_eq!(messages[3].decrypted_message_bytes, b"fourth"); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread", worker_threads = 10))] async fn test_stream_all_messages_changing_group_list() { let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -751,18 +741,14 @@ pub(crate) mod tests { .send_message("should not show up".as_bytes()) .await .unwrap(); - crate::sleep(core::time::Duration::from_millis(100)).await; + xmtp_common::time::sleep(core::time::Duration::from_millis(100)).await; let messages = messages.lock(); assert_eq!(messages.len(), 5); } #[ignore] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr( - not(target_arch = "wasm32"), - tokio::test(flavor = "multi_thread", worker_threads = 10) - )] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread"))] async fn test_stream_all_messages_does_not_lose_messages() { let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let caro = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); @@ -795,7 +781,7 @@ pub(crate) mod tests { crate::spawn(None, async move { for _ in 0..50 { alix_group_pointer.send_message(b"spam").await.unwrap(); - crate::sleep(core::time::Duration::from_micros(200)).await; + xmtp_common::time::sleep(core::time::Duration::from_micros(200)).await; } }); @@ -827,8 +813,7 @@ pub(crate) mod tests { } } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test(flavor = "multi_thread"))] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread"))] async fn test_self_group_creation() { let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bo = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); @@ -889,8 +874,7 @@ pub(crate) mod tests { closer.end(); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test(flavor = "multi_thread"))] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread"))] async fn test_dm_streaming() { let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bo = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); @@ -1023,8 +1007,7 @@ pub(crate) mod tests { closer.end(); } - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] - #[cfg_attr(not(target_arch = "wasm32"), tokio::test(flavor = "multi_thread"))] + #[wasm_bindgen_test(unsupported = tokio::test(flavor = "multi_thread"))] async fn test_dm_stream_all_messages() { let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); let bo = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); diff --git a/xmtp_mls/src/types.rs b/xmtp_mls/src/types.rs deleted file mode 100644 index 0a73a89b1..000000000 --- a/xmtp_mls/src/types.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub type Address = String; -pub type InstallationId = String; diff --git a/xmtp_mls/src/utils/mod.rs b/xmtp_mls/src/utils/mod.rs index 19872e390..0bf5da123 100644 --- a/xmtp_mls/src/utils/mod.rs +++ b/xmtp_mls/src/utils/mod.rs @@ -7,20 +7,6 @@ pub mod hash { pub use xmtp_cryptography::hash::sha256_bytes as sha256; } -pub mod time { - use wasm_timer::{SystemTime, UNIX_EPOCH}; - - pub const NS_IN_SEC: i64 = 1_000_000_000; - - pub fn now_ns() -> i64 { - let now = SystemTime::now(); - - now.duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_nanos() as i64 - } -} - pub mod id { /// Relies on a client-created idempotency_key (which could be a timestamp) pub fn calculate_message_id( @@ -42,34 +28,3 @@ pub mod id { hex::encode(group_id) } } - -#[cfg(any( - all(target_arch = "wasm32", feature = "test-utils"), - all(test, target_arch = "wasm32") -))] -pub mod wasm { - use tokio::sync::OnceCell; - static INIT: OnceCell<()> = OnceCell::const_new(); - - /// can be used to debug wasm tests - /// normal tracing logs are output to the browser console - pub async fn init() { - use web_sys::console; - - INIT.get_or_init(|| async { - console::log_1(&"INIT".into()); - let config = tracing_wasm::WASMLayerConfigBuilder::default() - .set_console_config(tracing_wasm::ConsoleConfig::ReportWithoutConsoleColor) - .build(); - tracing_wasm::set_as_global_default_with_config(config); - console_error_panic_hook::set_once(); - diesel_wasm_sqlite::init_sqlite().await; - }) - .await; - } -} - -#[cfg(not(target_arch = "wasm32"))] -pub mod wasm { - pub async fn init() {} -} diff --git a/xmtp_mls/src/utils/test/mod.rs b/xmtp_mls/src/utils/test/mod.rs index aded954b2..04b735b62 100755 --- a/xmtp_mls/src/utils/test/mod.rs +++ b/xmtp_mls/src/utils/test/mod.rs @@ -1,19 +1,7 @@ #![allow(clippy::unwrap_used)] -use crate::storage::DbConnection; -use crate::{ - builder::ClientBuilder, - identity::IdentityStrategy, - storage::{EncryptedMessageStore, StorageOption}, - types::Address, - Client, InboxOwner, XmtpApi, -}; -use rand::{ - distributions::{Alphanumeric, DistString}, - Rng, RngCore, -}; use std::sync::Arc; -use tokio::{sync::Notify, time::error::Elapsed}; +use tokio::sync::Notify; use xmtp_id::{ associations::{ generate_inbox_id, @@ -24,10 +12,12 @@ use xmtp_id::{ }; use xmtp_proto::api_client::XmtpTestClient; -#[cfg(not(target_arch = "wasm32"))] -pub mod traced_test; -#[cfg(not(target_arch = "wasm32"))] -pub use traced_test::traced_test; +use crate::{ + builder::ClientBuilder, + identity::IdentityStrategy, + storage::{DbConnection, EncryptedMessageStore, StorageOption}, + Client, InboxOwner, XmtpApi, +}; pub type FullXmtpClient = Client; @@ -45,40 +35,9 @@ use xmtp_api_http::XmtpHttpApiClient; #[cfg(any(feature = "http-api", target_arch = "wasm32"))] pub type TestClient = XmtpHttpApiClient; -pub fn rand_string() -> String { - Alphanumeric.sample_string(&mut rand::thread_rng(), 24) -} - -pub fn rand_account_address() -> Address { - Alphanumeric.sample_string(&mut rand::thread_rng(), 42) -} - -pub fn rand_vec() -> Vec { - rand::thread_rng().gen::<[u8; 24]>().to_vec() -} - -#[cfg(not(target_arch = "wasm32"))] -pub fn tmp_path() -> String { - let db_name = rand_string(); - format!("{}/{}.db3", std::env::temp_dir().to_str().unwrap(), db_name) -} - -#[cfg(target_arch = "wasm32")] -pub fn tmp_path() -> String { - let db_name = rand_string(); - format!("{}/{}.db3", "test_db", db_name) -} - -pub fn rand_time() -> i64 { - let mut rng = rand::thread_rng(); - rng.gen_range(0..1_000_000_000) -} - impl EncryptedMessageStore { pub fn generate_enc_key() -> [u8; 32] { - let mut key = [0u8; 32]; - xmtp_cryptography::utils::rng().fill_bytes(&mut key[..]); - key + xmtp_common::rand_array::<32>() } #[cfg(not(target_arch = "wasm32"))] @@ -97,8 +56,7 @@ impl EncryptedMessageStore { impl ClientBuilder { pub async fn temp_store(self) -> Self { - let tmpdb = tmp_path(); - tracing::info!("Opening Database at [{}]", tmpdb); + let tmpdb = xmtp_common::tmp_path(); self.store( EncryptedMessageStore::new( StorageOption::Persistent(tmpdb), @@ -258,8 +216,8 @@ impl Delivery { } } - pub async fn wait_for_delivery(&self) -> Result<(), Elapsed> { - tokio::time::timeout(self.timeout, async { self.notify.notified().await }).await + pub async fn wait_for_delivery(&self) -> Result<(), xmtp_common::time::Expired> { + xmtp_common::time::timeout(self.timeout, async { self.notify.notified().await }).await } pub fn notify_one(&self) { diff --git a/xmtp_proto/Cargo.toml b/xmtp_proto/Cargo.toml index c376941a1..f24eef4d2 100644 --- a/xmtp_proto/Cargo.toml +++ b/xmtp_proto/Cargo.toml @@ -6,7 +6,6 @@ license.workspace = true [dependencies] futures = { workspace = true } -openmls = { workspace = true, optional = true } pbjson-types.workspace = true pbjson.workspace = true prost = { workspace = true, features = ["prost-derive"] } @@ -15,17 +14,22 @@ async-trait = "0.1" hex.workspace = true openmls_rust_crypto = { workspace = true, optional = true } tracing.workspace = true +xmtp_common.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -tonic = { workspace = true } +tonic = { workspace = true, features = ["codegen", "server", "channel", "prost"] } +openmls = { workspace = true } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +openmls = { workspace = true, features = ["js"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test.workspace = true [features] -convert = ["openmls", "openmls_rust_crypto", "proto_full"] +convert = ["openmls_rust_crypto", "proto_full"] default = [] -test-utils = [] +test-utils = ["xmtp_common/test-utils"] # @@protoc_deletion_point(features) # This section is automatically generated by protoc-gen-prost-crate. diff --git a/xmtp_proto/src/api_client.rs b/xmtp_proto/src/api_client.rs index 03afb8df3..75cd72fbb 100644 --- a/xmtp_proto/src/api_client.rs +++ b/xmtp_proto/src/api_client.rs @@ -128,12 +128,6 @@ where } } -/// Global Marker trait for WebAssembly -#[cfg(target_arch = "wasm32")] -pub trait Wasm {} -#[cfg(target_arch = "wasm32")] -impl Wasm for T {} - // Wasm futures don't have `Send` or `Sync` bounds. #[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))] diff --git a/xmtp_proto/src/error.rs b/xmtp_proto/src/error.rs index d8109b9b8..8a574c785 100644 --- a/xmtp_proto/src/error.rs +++ b/xmtp_proto/src/error.rs @@ -35,6 +35,13 @@ pub struct Error { source: Option, } +// network errors should generally be retryable, unless there's a bug in our code +impl xmtp_common::RetryableError for Error { + fn is_retryable(&self) -> bool { + true + } +} + impl Error { pub fn new(kind: ErrorKind) -> Self { Self { kind, source: None }