diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index a71ed555c..adf6a2b1e 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -3,8 +3,10 @@ name: CodSpeed on: push: branches: [main] + paths-ignore: ["**.md", "docs/**"] pull_request: branches: [main] + paths-ignore: ["**.md", "docs/**"] # Allows CodSpeed to trigger backtest performance analysis to generate # initial baseline data. workflow_dispatch: @@ -20,11 +22,31 @@ concurrency: env: CARGO_TERM_COLOR: never PROTOC_VERSION: "3.25.3" + # Freeze glibc malloc's adaptive thresholds: mmap/trim/arena decisions vary + # with allocation history and read as spurious instruction/memory deltas + # under the deterministic instruments (codspeed.io/docs -> reducing-variance). + MALLOC_ARENA_MAX: "1" + MALLOC_MMAP_THRESHOLD_: "131072" + MALLOC_TRIM_THRESHOLD_: "131072" + MALLOC_TOP_PAD_: "131072" jobs: benchmarks: - name: Run CodSpeed benchmarks - runs-on: ubuntu-latest + name: Run CodSpeed benchmarks (${{ matrix.shard.name }}) + runs-on: ubuntu-24.04 + strategy: + # One shard failing must not cancel the other: CodSpeed merges shards + # into a single run, and a cancelled shard leaves it incomplete. + fail-fast: false + # Shards split by package within one workflow (same OIDC auth), halving + # the serial wall time; CodSpeed merges shard results into one run + # (codspeed.io/docs -> sharded-benchmarks). + matrix: + shard: + - name: core + packages: -p wacore -p wacore-noise + - name: proto-signal + packages: -p wacore-binary -p wacore-libsignal -p wacore-appstate steps: - uses: actions/checkout@v6 with: @@ -37,36 +59,39 @@ jobs: - name: Install tools (protoc, cargo-codspeed) uses: taiki-e/install-action@v2 with: - tool: protoc@${{ env.PROTOC_VERSION }},cargo-codspeed@4.7.0 + tool: protoc@${{ env.PROTOC_VERSION }},cargo-codspeed@5.0.1 - name: Cache Rust registry uses: Swatinem/rust-cache@v2 with: - prefix-key: ${{ runner.os }}-cargo-codspeed + prefix-key: ${{ runner.os }}-cargo-codspeed-${{ matrix.shard.name }} cache-targets: "false" # simulation and memory share the same instrumented build, so one # build covers both instruments. - name: Build the benchmark targets + env: + SHARD_PACKAGES: ${{ matrix.shard.packages }} run: > cargo codspeed build -m simulation -m memory - -p wacore -p wacore-binary -p wacore-libsignal - -p wacore-appstate -p wacore-noise + $SHARD_PACKAGES # Both instruments run serially in a single invocation so each # benchmark uploads as one run carrying CPU and memory metrics. - name: Run the benchmarks uses: CodSpeedHQ/action@v4 + env: + SHARD_PACKAGES: ${{ matrix.shard.packages }} with: mode: simulation,memory - run: cargo codspeed run + run: cargo codspeed run $SHARD_PACKAGES # Integration benches drive the real async client against the bartender mock # server, so they need the service container + MOCK_SERVER_URL. Kept as a # separate job so the unit-bench job above stays fast and mock-server-free. integration-benchmarks: name: Run CodSpeed integration benchmarks - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 # These benches drive the real client (connect/reconnect handshakes) under # Valgrind, so they are slow; cap the job so a stuck run can't hang CI # indefinitely. A healthy run finishes well under this even on slow runners. @@ -97,7 +122,7 @@ jobs: - name: Install tools (protoc, cargo-codspeed) uses: taiki-e/install-action@v2 with: - tool: protoc@${{ env.PROTOC_VERSION }},cargo-codspeed@4.7.0 + tool: protoc@${{ env.PROTOC_VERSION }},cargo-codspeed@5.0.1 - name: Cache Rust registry uses: Swatinem/rust-cache@v2 diff --git a/Cargo.lock b/Cargo.lock index 8068a4bf6..9a1c47d9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -637,14 +637,14 @@ checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "codspeed" -version = "4.7.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57af92d1db7f6871b7e82c79cd87f2501db66f36b0eab924be6ea83dd6b2f3f3" +checksum = "7083f253260bcb4aaa3b4aa4c52973703dabc1a85c2f193997e2689aafa8a919" dependencies = [ "anyhow", "cc", "colored", - "getrandom 0.2.17", + "getrandom 0.4.3", "glob", "libc", "nix 0.31.3", @@ -655,9 +655,9 @@ dependencies = [ [[package]] name = "codspeed-divan-compat" -version = "4.7.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ea79fd0b1f2128cfac6308369013dba92df47baf4a4f66b57d8158224a361d" +checksum = "bc1065d507e1cbab731a7976db4cef7e47e49b87b4dbc0a925df07d343558420" dependencies = [ "clap", "codspeed", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "codspeed-divan-compat-macros" -version = "4.7.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f70e4ddd6beedefeb48f59d5f85fc21365a66e7976408c3d39f6cbbc4f03e08c" +checksum = "2fd05482a95823ffe421e8a9ba24fa22a6a30d594e2c60455cbb43a41bf2d8fa" dependencies = [ "divan-macros", "itertools", @@ -682,9 +682,9 @@ dependencies = [ [[package]] name = "codspeed-divan-compat-walltime" -version = "4.7.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490c04f6076be6eacfafb496b8b237f3efbbed93838f2689115cc6f35fcf81c9" +checksum = "d2f8eae75b8fa85357020a404899c4280d590c9fd1c47640b3ce53106c62d2ee" dependencies = [ "cfg-if", "clap", @@ -697,12 +697,11 @@ dependencies = [ [[package]] name = "colored" -version = "2.2.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4519,15 +4518,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" diff --git a/Cargo.toml b/Cargo.toml index 7f18d99b5..90181e1fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ cbc = { version = "0.2", features = ["alloc"] } chrono = { version = "0.4", default-features = false } compact_str = { version = "0.9", default-features = false } ctr = { version = "0.10", default-features = false } -divan = { package = "codspeed-divan-compat", version = "4.7.0" } +divan = { package = "codspeed-divan-compat", version = "5.0.1" } env_logger = { version = "0.11", default-features = false } event-listener = { version = "5", default-features = false } flate2 = { version = "1.1.9", default-features = false, features = ["zlib-rs"] } diff --git a/wacore/benches/send_receive_benchmark.rs b/wacore/benches/send_receive_benchmark.rs index 5ff56b59c..7bdfbf146 100644 --- a/wacore/benches/send_receive_benchmark.rs +++ b/wacore/benches/send_receive_benchmark.rs @@ -3,6 +3,11 @@ use async_trait::async_trait; use buffa::Message as ProtoMessage; use std::collections::HashMap; + +/// SipHash with fixed keys: the default RandomState seeds per process, so +/// bucket layout (and thus cache behavior) differed between benchmark runs. +type DetState = std::hash::BuildHasherDefault; +type DetHashMap = HashMap; use std::hint::black_box; use wacore::client::context::{GroupInfo, SendContextResolver}; use wacore::messages::MessageUtils; @@ -143,7 +148,7 @@ impl Runtime for BenchRuntime { struct MemIdentityStore { key_pair: IdentityKeyPair, reg_id: u32, - identities: std::sync::Arc>>, + identities: std::sync::Arc>>, } impl MemIdentityStore { @@ -151,7 +156,7 @@ impl MemIdentityStore { Self { key_pair, reg_id, - identities: std::sync::Arc::new(std::sync::Mutex::new(HashMap::new())), + identities: std::sync::Arc::new(std::sync::Mutex::new(DetHashMap::default())), } } } @@ -188,7 +193,7 @@ impl IdentityKeyStore for MemIdentityStore { } } -struct MemPreKeyStore(HashMap); +struct MemPreKeyStore(DetHashMap); #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] @@ -209,7 +214,7 @@ impl PreKeyStore for MemPreKeyStore { } } -struct MemSignedPreKeyStore(HashMap); +struct MemSignedPreKeyStore(DetHashMap); #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] @@ -233,7 +238,9 @@ impl SignedPreKeyStore for MemSignedPreKeyStore { /// Bench fixture wrapping shared session state — see `MemIdentityStore` /// for the rationale. #[derive(Clone, Default)] -struct MemSessionStore(std::sync::Arc>>); +struct MemSessionStore( + std::sync::Arc>>, +); #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] @@ -250,7 +257,7 @@ impl SessionStore for MemSessionStore { } } -struct MemSenderKeyStore(HashMap); +struct MemSenderKeyStore(DetHashMap); #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] @@ -300,8 +307,8 @@ impl User { let spk_record = SignedPreKeyRecord::new(spk_id, Timestamp::from_epoch_millis(0), &spk_pair, &spk_sig); - let mut prekeys = MemPreKeyStore(HashMap::new()); - let mut signed_prekeys = MemSignedPreKeyStore(HashMap::new()); + let mut prekeys = MemPreKeyStore(DetHashMap::default()); + let mut signed_prekeys = MemSignedPreKeyStore(DetHashMap::default()); futures::executor::block_on(async { prekeys.save_pre_key(pk_id, &pk_record).await.unwrap(); signed_prekeys @@ -324,7 +331,7 @@ impl User { prekeys, signed_prekeys, sessions: MemSessionStore::default(), - sender_keys: MemSenderKeyStore(HashMap::new()), + sender_keys: MemSenderKeyStore(DetHashMap::default()), prekey_pair: pk_pair, signed_prekey_pair: spk_pair, signed_prekey_sig: spk_sig.to_vec(), diff --git a/wacore/libsignal/benches/libsignal_benchmark.rs b/wacore/libsignal/benches/libsignal_benchmark.rs index 1b14f6d09..edde529f0 100644 --- a/wacore/libsignal/benches/libsignal_benchmark.rs +++ b/wacore/libsignal/benches/libsignal_benchmark.rs @@ -1,5 +1,22 @@ use std::collections::HashMap; +/// SipHash with fixed keys: the default RandomState seeds per process, so +/// bucket layout (and thus cache behavior) differed between benchmark runs. +type DetState = std::hash::BuildHasherDefault; +type DetHashMap = HashMap; + +/// Deterministic per-call-site RNG: entropy-seeded keys made every run measure +/// different instruction counts (vartime signature paths depend on scalar +/// bits), which CodSpeed reads as noise. A counter keeps distinct call sites +/// on distinct streams so parties never share key material. +fn bench_rng() -> rand::rngs::StdRng { + use std::sync::atomic::{AtomicU32, Ordering}; + static CTR: AtomicU32 = AtomicU32::new(0); + ::seed_from_u64( + 0xB3AC_0000 + u64::from(CTR.fetch_add(1, Ordering::Relaxed)), + ) +} + use async_trait::async_trait; use divan::black_box; @@ -20,7 +37,7 @@ use wacore_libsignal::store::sender_key_name::SenderKeyName; struct InMemoryIdentityKeyStore { identity_key_pair: IdentityKeyPair, registration_id: u32, - identities: HashMap, + identities: DetHashMap, } impl InMemoryIdentityKeyStore { @@ -28,7 +45,7 @@ impl InMemoryIdentityKeyStore { Self { identity_key_pair, registration_id, - identities: HashMap::new(), + identities: DetHashMap::default(), } } } @@ -77,13 +94,13 @@ impl IdentityKeyStore for InMemoryIdentityKeyStore { } struct InMemoryPreKeyStore { - prekeys: HashMap, + prekeys: DetHashMap, } impl InMemoryPreKeyStore { fn new() -> Self { Self { - prekeys: HashMap::new(), + prekeys: DetHashMap::default(), } } } @@ -120,13 +137,13 @@ impl PreKeyStore for InMemoryPreKeyStore { } struct InMemorySignedPreKeyStore { - signed_prekeys: HashMap, + signed_prekeys: DetHashMap, } impl InMemorySignedPreKeyStore { fn new() -> Self { Self { - signed_prekeys: HashMap::new(), + signed_prekeys: DetHashMap::default(), } } } @@ -155,13 +172,13 @@ impl SignedPreKeyStore for InMemorySignedPreKeyStore { } struct InMemorySessionStore { - sessions: HashMap, + sessions: DetHashMap, } impl InMemorySessionStore { fn new() -> Self { Self { - sessions: HashMap::new(), + sessions: DetHashMap::default(), } } } @@ -194,13 +211,13 @@ impl SessionStore for InMemorySessionStore { } struct InMemorySenderKeyStore { - sender_keys: HashMap, + sender_keys: DetHashMap, } impl InMemorySenderKeyStore { fn new() -> Self { Self { - sender_keys: HashMap::new(), + sender_keys: DetHashMap::default(), } } } @@ -241,10 +258,15 @@ struct User { impl User { fn new(name: &str, device_id: u32) -> Self { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let identity_key_pair = IdentityKeyPair::generate(&mut rng); - let registration_id = rand::random::() & 0x3FFF; + // Same deterministic stream: the id is varint-encoded into prekey + // bundles, so an entropy draw here still shifted payload sizes. + let registration_id = { + use rand::RngExt as _; + rng.random::() & 0x3FFF + }; let prekey_id: PreKeyId = 1.into(); let prekey_pair = KeyPair::generate(&mut rng); @@ -321,7 +343,7 @@ fn setup_dm_session() -> (User, User) { let (mut alice, bob) = setup_dm_users(); let bob_bundle = bob.get_prekey_bundle(); - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); futures::executor::block_on(async { process_prekey_bundle( @@ -374,7 +396,7 @@ fn setup_established_dm_session() -> (User, User) { let ct_msg = CiphertextMessage::PreKeySignalMessage( wacore_libsignal::protocol::PreKeySignalMessage::try_from(ct.serialize()).unwrap(), ); - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); message_decrypt( &ct_msg, &alice.address, @@ -404,7 +426,7 @@ fn setup_group_with_distribution() -> (User, User, SenderKeyName) { let mut bob = User::new("bob", 1); futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let skdm = create_sender_key_distribution_message( &sender_key_name, &mut alice.sender_key_store, @@ -434,7 +456,7 @@ fn bench_dm_session_establishment(bencher: divan::Bencher) { bencher.with_inputs(setup_dm_users).bench_refs(|data| { let (alice, bob) = data; let bob_bundle = bob.get_prekey_bundle(); - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); futures::executor::block_on(async { process_prekey_bundle( @@ -480,7 +502,7 @@ fn bench_dm_decrypt_first_message(bencher: divan::Bencher) { .with_inputs(setup_dm_with_first_message) .bench_refs(|data| { let (alice, bob, ciphertext_bytes) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let plaintext = futures::executor::block_on(async { let ciphertext = CiphertextMessage::PreKeySignalMessage( @@ -539,7 +561,7 @@ fn setup_dm_with_inorder_subsequent_message() -> (User, User, Vec) { let (mut alice, mut bob) = setup_established_dm_session(); futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); // Bob replies and Alice decrypts it, clearing Alice's pending prekey so // her subsequent messages are plain SignalMessages. @@ -616,7 +638,7 @@ fn bench_dm_decrypt_subsequent_message(bencher: divan::Bencher) { .with_inputs(setup_dm_with_inorder_subsequent_message) .bench_refs(|data| { let (alice, bob, ciphertext_bytes) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let plaintext = futures::executor::block_on(async { let ciphertext = CiphertextMessage::SignalMessage( @@ -647,7 +669,7 @@ fn bench_dm_decrypt_subsequent_message(bencher: divan::Bencher) { fn bench_group_create_distribution_message(bencher: divan::Bencher) { bencher.with_inputs(setup_group_sender).bench_refs(|data| { let (alice, sender_key_name) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let skdm = futures::executor::block_on(async { create_sender_key_distribution_message( @@ -670,7 +692,7 @@ fn bench_group_encrypt_message(bencher: divan::Bencher) { .bench_refs(|data| { let (alice, _bob, sender_key_name) = data; let plaintext = b"Hello group! This is a group message from Alice."; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let ciphertext = futures::executor::block_on(async { group_encrypt( @@ -691,7 +713,7 @@ fn setup_group_with_encrypted_message() -> (User, User, SenderKeyName, Vec) let (mut alice, bob, sender_key_name) = setup_group_with_distribution(); let ciphertext = futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let skm = group_encrypt( &mut alice.sender_key_store, &sender_key_name, @@ -738,7 +760,7 @@ fn bench_full_dm_conversation(bencher: divan::Bencher) { .with_inputs(setup_conversation_data) .bench_refs(|data| { let (alice, bob) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); futures::executor::block_on(async { let bob_bundle = bob.get_prekey_bundle(); @@ -836,7 +858,7 @@ fn bench_full_dm_conversation(bencher: divan::Bencher) { // Signature-specific benchmarks to measure the XEdDSA optimization fn setup_keypair_with_message() -> (KeyPair, [u8; 64]) { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let keypair = KeyPair::generate(&mut rng); let message = [0x42u8; 64]; // Fixed message for consistent benchmarking (keypair, message) @@ -850,7 +872,7 @@ fn bench_signature_creation(bencher: divan::Bencher) { .with_inputs(setup_keypair_with_message) .bench_refs(|data| { let (keypair, message) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); // Sign multiple times to amortize any setup overhead for _ in 0..10 { @@ -869,7 +891,7 @@ fn bench_signature_verification(bencher: divan::Bencher) { .with_inputs(setup_keypair_with_message) .bench_refs(|data| { let (keypair, message) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let signature = keypair .calculate_signature(&message[..], &mut rng) .expect("signature"); @@ -887,7 +909,7 @@ fn bench_signature_verification(bencher: divan::Bencher) { // Benchmark key generation (shows the added cost of caching) #[divan::bench] fn bench_key_generation() { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); for _ in 0..10 { let keypair = KeyPair::generate(&mut rng); black_box(keypair); @@ -899,7 +921,7 @@ fn bench_key_generation() { fn setup_with_archived_sessions() -> (User, User, Vec>) { let mut alice = User::new("alice", 1); let mut bob = User::new("bob", 1); - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); // Store ciphertexts encrypted with each session version let mut old_ciphertexts = Vec::new(); @@ -1026,7 +1048,7 @@ fn bench_decrypt_with_previous_session(bencher: divan::Bencher) { .with_inputs(setup_with_archived_sessions) .bench_refs(|data| { let (alice, bob, ciphertexts) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); // Try to decrypt an old message (encrypted with a previous session) // This forces the decryption to iterate through previous sessions @@ -1062,7 +1084,7 @@ fn setup_out_of_order_messages() -> (User, User, Vec>) { let mut messages = Vec::new(); futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); // Alice sends initial PreKey message to Bob let msg = message_encrypt( @@ -1142,7 +1164,7 @@ fn bench_out_of_order_decryption(bencher: divan::Bencher) { .with_inputs(setup_out_of_order_messages) .bench_refs(|data| { let (alice, bob, messages) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); futures::executor::block_on(async { // Decrypt messages in reverse order (worst case for message key storage) @@ -1175,7 +1197,7 @@ fn bench_out_of_order_decryption(bencher: divan::Bencher) { fn setup_promote_matching_session() -> (User, User, Vec) { let mut alice = User::new("alice", 1); let mut bob = User::new("bob", 1); - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let prekey_message = futures::executor::block_on(async { // Create initial session @@ -1293,7 +1315,7 @@ fn bench_promote_matching_session(bencher: divan::Bencher) { .with_inputs(setup_promote_matching_session) .bench_refs(|data| { let (alice, bob, prekey_message) = data; - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); futures::executor::block_on(async { // Process multiple PreKey messages to exercise promote_matching_session @@ -1336,7 +1358,7 @@ fn create_test_session_state( version: u8, base_key: &wacore_libsignal::protocol::PublicKey, ) -> SessionState { - let mut csprng = rand::make_rng::(); + let mut csprng = bench_rng(); let identity_keypair = KeyPair::generate(&mut csprng); let their_identity = IdentityKey::new(identity_keypair.public_key); let our_identity = IdentityKey::new(KeyPair::generate(&mut csprng).public_key); @@ -1355,7 +1377,7 @@ fn create_test_session_state( /// Setup for message key eviction benchmark. /// Creates a session with a receiver chain pre-filled near capacity. fn setup_message_key_eviction() -> (SessionState, wacore_libsignal::protocol::PublicKey) { - let mut csprng = rand::make_rng::(); + let mut csprng = bench_rng(); let base_key = KeyPair::generate(&mut csprng).public_key; let mut state = create_test_session_state(3, &base_key); @@ -1424,7 +1446,7 @@ fn setup_group_out_of_order_worst_case() -> (User, SenderKeyName, Vec) { ); let worst_case_ct = futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let mut ciphertexts: Vec> = Vec::with_capacity((N + 1) as usize); for i in 0..=N { let skm = group_encrypt( @@ -1495,7 +1517,7 @@ fn setup_group_in_order_decrypt_with_backlog() -> (User, SenderKeyName, Vec) ); let in_order_ct = futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); let mut ciphertexts: Vec> = Vec::with_capacity((N + 2) as usize); for i in 0..=(N + 1) { let skm = group_encrypt( @@ -1560,7 +1582,7 @@ fn setup_skdm_ingest() -> ( alice.address.name().to_string(), ); let skdm = futures::executor::block_on(async { - let mut rng = rand::make_rng::(); + let mut rng = bench_rng(); create_sender_key_distribution_message( &sender_key_name, &mut alice.sender_key_store,