From 12ba705528006ae6867232bb63c57dc096f0db78 Mon Sep 17 00:00:00 2001 From: Mykhailo Kremniov Date: Wed, 11 Mar 2026 14:50:43 +0200 Subject: [PATCH] Make peer manager use the provided rng instead of creating a new one. --- Cargo.lock | 1 + p2p/benches/benches.rs | 17 +- p2p/src/lib.rs | 3 + .../peer_manager/addr_list_response_cache.rs | 18 +- p2p/src/peer_manager/dns_seed.rs | 9 +- p2p/src/peer_manager/mod.rs | 163 ++++-- p2p/src/peer_manager/peerdb/mod.rs | 49 +- p2p/src/peer_manager/peerdb/salt.rs | 8 +- p2p/src/peer_manager/peerdb/storage_load.rs | 7 +- p2p/src/peer_manager/peerdb/tests.rs | 66 ++- .../tests/addr_list_response_caching.rs | 22 +- p2p/src/peer_manager/tests/addresses.rs | 8 + p2p/src/peer_manager/tests/ban.rs | 7 + p2p/src/peer_manager/tests/connections.rs | 499 +++++++++++++----- p2p/src/peer_manager/tests/discouragement.rs | 7 + p2p/src/peer_manager/tests/eviction.rs | 4 +- p2p/src/peer_manager/tests/mod.rs | 15 +- p2p/src/peer_manager/tests/peer_types.rs | 19 +- p2p/src/peer_manager/tests/ping.rs | 26 +- p2p/src/peer_manager/tests/whitelist.rs | 90 +++- p2p/src/tests/bad_time_diff.rs | 81 ++- p2p/src/tests/correct_handshake.rs | 81 ++- p2p/src/tests/disable_networking.rs | 24 +- .../disconnect_on_will_disconnect_msg.rs | 55 +- p2p/src/tests/helpers/mod.rs | 3 +- p2p/src/tests/helpers/test_node.rs | 3 + p2p/src/tests/incorrect_handshake.rs | 128 +++-- p2p/src/tests/min_peer_software_version.rs | 34 +- p2p/src/tests/misbehavior.rs | 49 +- p2p/src/tests/peer_discovery_on_stale_tip.rs | 18 +- p2p/src/tests/same_handshake_nonce.rs | 49 +- p2p/src/tests/unsupported_message.rs | 6 +- p2p/src/tests/unsupported_version.rs | 113 ++-- randomness/Cargo.toml | 3 + randomness/src/lib.rs | 72 +++ 35 files changed, 1264 insertions(+), 493 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4bf69a765..373a69948e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6988,6 +6988,7 @@ name = "randomness" version = "1.2.1" dependencies = [ "rand 0.8.5", + "static_assertions", ] [[package]] diff --git a/p2p/benches/benches.rs b/p2p/benches/benches.rs index 29bdc9ab22..9445bbb0d8 100644 --- a/p2p/benches/benches.rs +++ b/p2p/benches/benches.rs @@ -31,8 +31,14 @@ pub fn peer_db(c: &mut Criterion) { let db_store = peerdb_inmemory_store(); let chain_config = create_unit_test_config(); let p2p_config = Arc::new(test_p2p_config()); - let mut peerdb = - PeerDb::<_>::new(&chain_config, p2p_config, Default::default(), db_store).unwrap(); + let mut peerdb = PeerDb::<_>::new( + &chain_config, + p2p_config, + Default::default(), + db_store, + &mut rng, + ) + .unwrap(); for _ in 0..100000 { peerdb.peer_discovered(TestAddressMaker::new_random_address(&mut rng).into()); @@ -54,7 +60,12 @@ pub fn peer_db(c: &mut Criterion) { c.bench_function("PeerDb", |b| { b.iter(|| { - peerdb.select_non_reserved_outbound_addresses(&outbound_addr_groups, &|_| true, 11) + peerdb.select_non_reserved_outbound_addresses( + &outbound_addr_groups, + &|_| true, + 11, + &mut rng, + ) }) }); } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 47c16941d4..2216246b82 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -57,6 +57,7 @@ use networking::transport::{ TcpTransportSocket, }; use peer_manager::peerdb::storage::PeerDbStorage; +use randomness::make_true_rng; use types::socket_address::SocketAddress; use crate::{ @@ -155,6 +156,8 @@ where peer_mgr_event_receiver, time_getter.clone(), peerdb_storage, + // Note: a "true" rng is not really needed here, but `make_pseudo_rng`'s result is not `Send`. + make_true_rng(), )?; let shutdown_ = Arc::clone(&shutdown); let peer_manager_task = tokio_spawn_in_current_tracing_span( diff --git a/p2p/src/peer_manager/addr_list_response_cache.rs b/p2p/src/peer_manager/addr_list_response_cache.rs index ea5cc84160..6210b04506 100644 --- a/p2p/src/peer_manager/addr_list_response_cache.rs +++ b/p2p/src/peer_manager/addr_list_response_cache.rs @@ -20,7 +20,7 @@ use std::{ }; use common::primitives::time::Time; -use randomness::{make_pseudo_rng, Rng}; +use randomness::Rng; use super::{peer_context::PeerContext, peerdb::salt::Salt}; @@ -50,7 +50,13 @@ impl AddrListResponseCache { } } - pub fn get_or_create(&mut self, peer_ctx: &PeerContext, now: Time, create: F) -> &Addresses + pub fn get_or_create( + &mut self, + peer_ctx: &PeerContext, + now: Time, + create: F, + rng: &mut impl Rng, + ) -> &Addresses where F: FnOnce() -> Addresses, { @@ -61,13 +67,13 @@ impl AddrListResponseCache { let cache_entry = match self.cache.entry(id) { Entry::Vacant(entry) => entry.insert(CacheEntry { addresses: create(), - expiration_time: Self::new_expiration_time_from_now(now), + expiration_time: Self::new_expiration_time_from_now(now, rng), }), Entry::Occupied(mut entry) => { if entry.get().expiration_time <= now { *entry.get_mut() = CacheEntry { addresses: create(), - expiration_time: Self::new_expiration_time_from_now(now), + expiration_time: Self::new_expiration_time_from_now(now, rng), }; } entry.into_mut() @@ -101,10 +107,10 @@ impl AddrListResponseCache { hasher.finish() } - fn new_expiration_time_from_now(now: Time) -> Time { + fn new_expiration_time_from_now(now: Time, rng: &mut impl Rng) -> Time { let min_secs = EXPIRATION_INTERVAL_MIN.as_secs(); let max_secs = EXPIRATION_INTERVAL_MAX.as_secs(); - let secs = make_pseudo_rng().gen_range(min_secs..=max_secs); + let secs = rng.gen_range(min_secs..=max_secs); (now + Duration::from_secs(secs)).expect("Unexpected time overflow") } } diff --git a/p2p/src/peer_manager/dns_seed.rs b/p2p/src/peer_manager/dns_seed.rs index 3c1cddfb80..fa95132f70 100644 --- a/p2p/src/peer_manager/dns_seed.rs +++ b/p2p/src/peer_manager/dns_seed.rs @@ -16,16 +16,17 @@ use std::sync::Arc; use async_trait::async_trait; + use common::chain::ChainConfig; use logging::log; use p2p_types::{peer_address::PeerAddress, socket_address::SocketAddress}; -use randomness::{make_pseudo_rng, seq::IteratorRandom}; +use randomness::{seq::IteratorRandom, RngCore}; use crate::config::P2pConfig; #[async_trait] pub trait DnsSeed: Send + Sync { - async fn obtain_addresses(&self) -> Vec; + async fn obtain_addresses(&self, rng: &mut (dyn RngCore + Send)) -> Vec; } pub struct DefaultDnsSeed { @@ -47,7 +48,7 @@ const MAX_DNS_RECORDS: usize = 10; #[async_trait] impl DnsSeed for DefaultDnsSeed { - async fn obtain_addresses(&self) -> Vec { + async fn obtain_addresses(&self, rng: &mut (dyn RngCore + Send)) -> Vec { let dns_seeds = self.chain_config.dns_seeds(); if dns_seeds.is_empty() { @@ -73,7 +74,7 @@ impl DnsSeed for DefaultDnsSeed { ) }) // Randomize selection because records can be sorted by type (A and AAAA) - .choose_multiple(&mut make_pseudo_rng(), MAX_DNS_RECORDS) + .choose_multiple(rng, MAX_DNS_RECORDS) .into_iter() .for_each(|addr| { addresses.push(addr); diff --git a/p2p/src/peer_manager/mod.rs b/p2p/src/peer_manager/mod.rs index 78adfc7354..ee7223e73e 100644 --- a/p2p/src/peer_manager/mod.rs +++ b/p2p/src/peer_manager/mod.rs @@ -27,6 +27,7 @@ pub mod peers_eviction; use std::{ collections::{BTreeMap, BTreeSet, HashMap}, net::IpAddr, + ops::DerefMut as _, sync::Arc, time::Duration, }; @@ -43,7 +44,7 @@ use common::{ use logging::log; use networking::types::ConnectionDirection; use p2p_types::{bannable_address::BannableAddress, socket_address::SocketAddress, IsGlobalIp}; -use randomness::{make_pseudo_rng, seq::IteratorRandom, Rng}; +use randomness::{seq::IteratorRandom, BoxedRngMutexWrapper, Rng, RngCore}; use utils::{bloom_filters::rolling_bloom_filter::RollingBloomFilter, ensure, set_flag::SetFlag}; use utils_networking::IpOrSocketAddress; @@ -205,6 +206,9 @@ where /// substitute it with a mock implementation. dns_seed: Box, + /// An RNG used to generate various delays when dealing with peers. + rng: std::sync::Mutex>, + /// The time when PeerManager was initialized. init_time: Time, /// Last time when a new tip was added to the chainstate. @@ -233,6 +237,7 @@ where T::ConnectivityHandle: ConnectivityService, S: PeerDbStorage, { + #[allow(clippy::too_many_arguments)] pub fn new( networking_enabled: bool, chain_config: Arc, @@ -241,6 +246,7 @@ where peer_mgr_event_receiver: mpsc::UnboundedReceiver, time_getter: TimeGetter, peerdb_storage: S, + rng: impl RngCore + Send + 'static, ) -> crate::Result { Self::new_generic( networking_enabled, @@ -252,6 +258,7 @@ where peerdb_storage, None, Box::new(DefaultDnsSeed::new(chain_config, p2p_config)), + rng, ) } @@ -266,21 +273,24 @@ where peerdb_storage: S, observer: Option>, dns_seed: Box, + mut rng: impl RngCore + Send + 'static, ) -> crate::Result { - let mut rng = make_pseudo_rng(); let peerdb = peerdb::PeerDb::new( &chain_config, Arc::clone(&p2p_config), time_getter.clone(), peerdb_storage, + &mut rng, )?; let salt = peerdb.salt(); let now = time_getter.get_time(); let next_feeler_connection_time = - Self::choose_next_feeler_connection_time(&p2p_config, now); + Self::choose_next_feeler_connection_time(&p2p_config, now, &mut rng); assert!(!p2p_config.outbound_connection_timeout.is_zero()); assert!(!p2p_config.ping_timeout.is_zero()); + let peer_eviction_random_state = peers_eviction::RandomState::new(&mut rng); + Ok(PeerManager { networking_enabled, chain_config, @@ -293,10 +303,11 @@ where peers: BTreeMap::new(), peerdb, subscribed_to_peer_addresses: BTreeSet::new(), - peer_eviction_random_state: peers_eviction::RandomState::new(&mut rng), + peer_eviction_random_state, addr_list_response_cache: AddrListResponseCache::new(salt), observer, dns_seed, + rng: std::sync::Mutex::new(Box::new(rng)), init_time: now, last_chainstate_tip_block_time: None, last_heartbeat_time: None, @@ -306,11 +317,21 @@ where }) } - fn choose_next_feeler_connection_time(p2p_config: &P2pConfig, now: Time) -> Time { + fn lock_rng( + rng: &std::sync::Mutex>, + ) -> std::sync::MutexGuard<'_, Box> { + rng.lock().expect("poisoned mutex") + } + + fn choose_next_feeler_connection_time( + p2p_config: &P2pConfig, + now: Time, + rng: &mut impl RngCore, + ) -> Time { let delay = p2p_config .peer_manager_config .feeler_connections_interval - .mul_f64(utils::exp_rand::exponential_rand(&mut make_pseudo_rng())); + .mul_f64(utils::exp_rand::exponential_rand(rng)); (now + delay).expect("Unexpected time overflow") } @@ -375,8 +396,10 @@ where // Send only one address because of the rate limiter (see `ADDR_RATE_INITIAL_SIZE`). // Select a random address to give all addresses a chance to be discovered by the network. - let chosen_discovered_address = - discovered_own_addresses.iter().choose(&mut make_pseudo_rng()).cloned(); + let chosen_discovered_address = discovered_own_addresses + .iter() + .choose(Self::lock_rng(&self.rng).deref_mut()) + .cloned(); log::debug!( "Own addresses discovered for peer {peer_id}: {:?}, chosen address: {:?}", @@ -401,7 +424,7 @@ where address: address.as_peer_address(), }), ); - peer.announced_addresses.insert(&address, &mut make_pseudo_rng()); + peer.announced_addresses.insert(&address, Self::lock_rng(&self.rng).deref_mut()); } } @@ -430,7 +453,7 @@ where .peers .values_mut() .filter(|peer| peer.discovered_own_address.is_some()) - .choose(&mut make_pseudo_rng()) + .choose(Self::lock_rng(&self.rng).deref_mut()) { Self::send_own_address_to_peer(&mut self.peer_connectivity_handle, peer); } @@ -932,11 +955,13 @@ where /// It's called when a new inbound connection is received, but the connection limit has been reached. /// Returns true if a random peer has been disconnected. fn try_evict_random_inbound_connection(&mut self) -> bool { - if let Some(peer_id) = peers_eviction::select_for_eviction_inbound( + let peer_id_opt = peers_eviction::select_for_eviction_inbound( self.eviction_candidates(PeerRole::Inbound), &self.p2p_config.peer_manager_config, - &mut make_pseudo_rng(), - ) { + Self::lock_rng(&self.rng).deref_mut(), + ); + + if let Some(peer_id) = peer_id_opt { log::info!("Inbound peer {peer_id} is selected for eviction"); self.disconnect( peer_id, @@ -952,12 +977,14 @@ where /// If there are too many outbound block relay peers, find and disconnect the "worst" one. fn evict_block_relay_peer(&mut self) { - if let Some(peer_id) = peers_eviction::select_for_eviction_block_relay( + let peer_id_opt = peers_eviction::select_for_eviction_block_relay( self.eviction_candidates(PeerRole::OutboundBlockRelay), &self.p2p_config.peer_manager_config, self.time_getter.get_time(), - &mut make_pseudo_rng(), - ) { + Self::lock_rng(&self.rng).deref_mut(), + ); + + if let Some(peer_id) = peer_id_opt { log::info!("Block relay peer {peer_id} is selected for eviction"); self.disconnect( peer_id, @@ -970,12 +997,14 @@ where /// If there are too many outbound full relay peers, find and disconnect the "worst" one. fn evict_full_relay_peer(&mut self) { - if let Some(peer_id) = peers_eviction::select_for_eviction_full_relay( + let peer_id_opt = peers_eviction::select_for_eviction_full_relay( self.eviction_candidates(PeerRole::OutboundFullRelay), &self.p2p_config.peer_manager_config, self.time_getter.get_time(), - &mut make_pseudo_rng(), - ) { + Self::lock_rng(&self.rng).deref_mut(), + ); + + if let Some(peer_id) = peer_id_opt { log::info!("Full relay peer {peer_id} is selected for eviction"); self.disconnect( peer_id, @@ -1062,7 +1091,7 @@ where let announced_addresses = RollingBloomFilter::new( PEER_ADDRESSES_ROLLING_BLOOM_FILTER_SIZE, PEER_ADDRESSES_ROLLING_BLOOM_FPP, - &mut make_pseudo_rng(), + Self::lock_rng(&self.rng).deref_mut(), ); let discovered_own_address = self.discover_own_address( @@ -1098,7 +1127,8 @@ where assert!(old_value.is_none()); if peer_role.is_outbound() { - self.peerdb.outbound_peer_connected(peer_address); + self.peerdb + .outbound_peer_connected(peer_address, Self::lock_rng(&self.rng).deref_mut()); } if peer_role == PeerRole::OutboundBlockRelay { @@ -1194,7 +1224,8 @@ where } if peer_role.is_outbound() { - self.peerdb.report_outbound_failure(peer_address); + self.peerdb + .report_outbound_failure(peer_address, Self::lock_rng(&self.rng).deref_mut()); } } else if peer_role == PeerRole::Feeler { self.disconnect( @@ -1219,7 +1250,8 @@ where /// Inform the [`crate::peer_manager::peerdb::PeerDb`] about the address failure so it knows to /// update its own records. fn handle_outbound_error(&mut self, address: SocketAddress, error: P2pError) { - self.peerdb.report_outbound_failure(address); + self.peerdb + .report_outbound_failure(address, Self::lock_rng(&self.rng).deref_mut()); let PendingConnect { outbound_connect_type, @@ -1252,7 +1284,10 @@ where ); if peer.peer_role.is_outbound() { - self.peerdb.outbound_peer_disconnected(peer.peer_address); + self.peerdb.outbound_peer_disconnected( + peer.peer_address, + Self::lock_rng(&self.rng).deref_mut(), + ); } if let Some(PendingDisconnect { @@ -1293,7 +1328,10 @@ where /// Fill PeerDb with addresses from the DNS seed servers async fn query_dns_seed(&mut self) { - let addresses = self.dns_seed.obtain_addresses().await; + // Note: can't pass the result of `Self::lock_rng(&self.rng).deref_mut()` to `obtain_addresses`, + // like it's done in other places, because it's an async function and `MutexGuard` is not `Send`. + let addresses = + self.dns_seed.obtain_addresses(&mut BoxedRngMutexWrapper::new(&self.rng)).await; let mut new_addr_count = 0; for addr in &addresses { @@ -1410,6 +1448,7 @@ where ) }, needed_outbound_full_relay_conn_count, + Self::lock_rng(&self.rng).deref_mut(), ); log::debug!( @@ -1450,6 +1489,7 @@ where ) }, needed_outbound_block_relay_conn_count, + Self::lock_rng(&self.rng).deref_mut(), ); log::debug!( @@ -1493,12 +1533,16 @@ where && cur_feeler_conn_count == 0 && now >= self.next_feeler_connection_time { - if let Some(address) = - self.peerdb.select_non_reserved_outbound_address_from_new_addr_table() - { + let address_opt = self.peerdb.select_non_reserved_outbound_address_from_new_addr_table( + Self::lock_rng(&self.rng).deref_mut(), + ); + if let Some(address) = address_opt { self.connect(address, OutboundConnectType::Feeler); - self.next_feeler_connection_time = - Self::choose_next_feeler_connection_time(&self.p2p_config, now); + self.next_feeler_connection_time = Self::choose_next_feeler_connection_time( + &self.p2p_config, + now, + Self::lock_rng(&self.rng).deref_mut(), + ); } } } @@ -1533,16 +1577,15 @@ where return; } - peer.announced_addresses.insert(&address, &mut make_pseudo_rng()); + peer.announced_addresses.insert(&address, Self::lock_rng(&self.rng).deref_mut()); self.peerdb.peer_discovered(address); if !self.peerdb.is_address_banned_or_discouraged(&address.as_bannable()) { - let peer_ids = self - .subscribed_to_peer_addresses - .iter() - .cloned() - .choose_multiple(&mut make_pseudo_rng(), PEER_ADDRESS_RESEND_COUNT); + let peer_ids = self.subscribed_to_peer_addresses.iter().cloned().choose_multiple( + Self::lock_rng(&self.rng).deref_mut(), + PEER_ADDRESS_RESEND_COUNT, + ); for new_peer_id in peer_ids { self.announce_address(new_peer_id, address); } @@ -1565,22 +1608,27 @@ where let now = self.time_getter.get_time(); let addresses = self .addr_list_response_cache - .get_or_create(peer, now, || { - self.peerdb - .known_addresses() - .filter_map(|address| { - let peer_addr = address.as_peer_address(); - let bannable_addr = address.as_bannable(); - if Self::is_peer_address_discoverable(&peer_addr, &self.p2p_config) - && !self.peerdb.is_address_banned_or_discouraged(&bannable_addr) - { - Some(peer_addr) - } else { - None - } - }) - .choose_multiple(&mut make_pseudo_rng(), max_addr_count) - }) + .get_or_create( + peer, + now, + || { + self.peerdb + .known_addresses() + .filter_map(|address| { + let peer_addr = address.as_peer_address(); + let bannable_addr = address.as_bannable(); + if Self::is_peer_address_discoverable(&peer_addr, &self.p2p_config) + && !self.peerdb.is_address_banned_or_discouraged(&bannable_addr) + { + Some(peer_addr) + } else { + None + } + }) + .choose_multiple(&mut BoxedRngMutexWrapper::new(&self.rng), max_addr_count) + }, + &mut BoxedRngMutexWrapper::new(&self.rng), + ) // Note: some of the addresses may have become banned or discouraged after they've been // cached. It's not clear whether it's better to filter them out here, which will // reveal to peers what addresses we've banned or discouraged, or keep them as is. @@ -1752,7 +1800,7 @@ where } PeerManagerEvent::AddReserved(address, response_sender) => { let address = ip_or_socket_address_to_peer_address(&address, &self.chain_config); - self.peerdb.add_reserved_node(address); + self.peerdb.add_reserved_node(address, Self::lock_rng(&self.rng).deref_mut()); if self.networking_enabled { // Initiate new outbound connection without waiting for `heartbeat` self.connect(address, OutboundConnectType::Reserved); @@ -1761,7 +1809,7 @@ where } PeerManagerEvent::RemoveReserved(address, response_sender) => { let address = ip_or_socket_address_to_peer_address(&address, &self.chain_config); - self.peerdb.remove_reserved_node(address); + self.peerdb.remove_reserved_node(address, Self::lock_rng(&self.rng).deref_mut()); response_sender.send(Ok(())); } PeerManagerEvent::ListBanned(response_sender) => { @@ -2038,7 +2086,7 @@ where } } None => { - let nonce = make_pseudo_rng().gen(); + let nonce = Self::lock_rng(&self.rng).gen(); Self::send_peer_message( &mut self.peer_connectivity_handle, *peer_id, @@ -2321,8 +2369,9 @@ where *self.p2p_config.peer_manager_config.outbound_full_relay_count, 1, ); - let delay = (RESEND_OWN_ADDRESS_TO_PEER_PERIOD / delay_divisor as u32) - .mul_f64(utils::exp_rand::exponential_rand(&mut make_pseudo_rng())); + let delay = (RESEND_OWN_ADDRESS_TO_PEER_PERIOD / delay_divisor as u32).mul_f64( + utils::exp_rand::exponential_rand(Self::lock_rng(&self.rng).deref_mut()), + ); next_time_resend_own_address = (next_time_resend_own_address + delay) .expect("Time derived from local clock; cannot fail"); } diff --git a/p2p/src/peer_manager/peerdb/mod.rs b/p2p/src/peer_manager/peerdb/mod.rs index 189cd56bba..2d6cde287f 100644 --- a/p2p/src/peer_manager/peerdb/mod.rs +++ b/p2p/src/peer_manager/peerdb/mod.rs @@ -41,7 +41,7 @@ use std::{ use common::{chain::ChainConfig, primitives::time::Time, time_getter::TimeGetter}; use logging::log; use p2p_types::{bannable_address::BannableAddress, socket_address::SocketAddress}; -use randomness::{make_pseudo_rng, seq::IteratorRandom, Rng, SliceRandom}; +use randomness::{seq::IteratorRandom, Rng, SliceRandom}; use crate::config::P2pConfig; @@ -101,6 +101,7 @@ impl PeerDb { p2p_config: Arc, time_getter: TimeGetter, storage: S, + rng: &mut impl Rng, ) -> crate::Result { // Node won't start if DB loading fails! let LoadedStorage { @@ -109,7 +110,11 @@ impl PeerDb { discouraged_addresses, anchor_addresses, salt, - } = LoadedStorage::load_storage(&storage, &p2p_config.peer_manager_config.peerdb_config)?; + } = LoadedStorage::load_storage( + &storage, + &p2p_config.peer_manager_config.peerdb_config, + rng, + )?; let reserved_nodes = p2p_config .reserved_nodes @@ -215,20 +220,6 @@ impl PeerDb { cur_outbound_conn_addr_groups: &BTreeSet, additional_filter: &impl Fn(&SocketAddress) -> bool, count: usize, - ) -> Vec { - self.select_non_reserved_outbound_addresses_with_rng( - cur_outbound_conn_addr_groups, - additional_filter, - count, - &mut make_pseudo_rng(), - ) - } - - fn select_non_reserved_outbound_addresses_with_rng( - &self, - cur_outbound_conn_addr_groups: &BTreeSet, - additional_filter: &impl Fn(&SocketAddress) -> bool, - count: usize, rng: &mut impl Rng, ) -> Vec { if count == 0 { @@ -297,6 +288,7 @@ impl PeerDb { pub fn select_non_reserved_outbound_address_from_new_addr_table( &self, + rng: &mut impl Rng, ) -> Option { let now = self.time_getter.get_time(); @@ -314,7 +306,7 @@ impl PeerDb { } }) .copied() - .choose(&mut make_pseudo_rng()) + .choose(rng) } /// Selects reserved peer addresses for outbound connections @@ -401,8 +393,8 @@ impl PeerDb { /// /// When [`crate::peer_manager::PeerManager::heartbeat()`] has initiated an outbound connection /// and the connection is refused, it's reported back to the `PeerDb` so it marks the address as unreachable. - pub fn report_outbound_failure(&mut self, address: SocketAddress) { - self.change_address_state(address, AddressStateTransitionTo::ConnectionFailed); + pub fn report_outbound_failure(&mut self, address: SocketAddress, rng: &mut impl Rng) { + self.change_address_state(address, AddressStateTransitionTo::ConnectionFailed, rng); // Note: if the failed connection is a manual one, the address won't be in the addr tables, // but the 'change_address_state' call above will insert it into self.addresses. @@ -414,14 +406,14 @@ impl PeerDb { /// /// After `PeerManager` has established either an inbound or an outbound connection, /// it informs the `PeerDb` about it. - pub fn outbound_peer_connected(&mut self, address: SocketAddress) { - self.change_address_state(address, AddressStateTransitionTo::Connected); + pub fn outbound_peer_connected(&mut self, address: SocketAddress, rng: &mut impl Rng) { + self.change_address_state(address, AddressStateTransitionTo::Connected, rng); self.move_addr_to_tried(&address); } /// Handle peer disconnect event with unspecified reason - pub fn outbound_peer_disconnected(&mut self, address: SocketAddress) { - self.change_address_state(address, AddressStateTransitionTo::Disconnected); + pub fn outbound_peer_disconnected(&mut self, address: SocketAddress, rng: &mut impl Rng) { + self.change_address_state(address, AddressStateTransitionTo::Disconnected, rng); } pub fn remove_address(&mut self, address: &SocketAddress) { @@ -518,6 +510,7 @@ impl PeerDb { &mut self, address: SocketAddress, transition: AddressStateTransitionTo, + rng: &mut impl Rng, ) { let now = self.time_getter.get_time(); @@ -530,7 +523,7 @@ impl PeerDb { let old_state = address_data.state().clone(); - address_data.transition_to(transition, now, &mut make_pseudo_rng()); + address_data.transition_to(transition, now, rng); log::debug!( "Address {} state changed: {:?}, old state = {:?}, new state = {:?}", @@ -549,13 +542,13 @@ impl PeerDb { self.reserved_nodes.iter().copied() } - pub fn add_reserved_node(&mut self, address: SocketAddress) { - self.change_address_state(address, AddressStateTransitionTo::SetReserved); + pub fn add_reserved_node(&mut self, address: SocketAddress, rng: &mut impl Rng) { + self.change_address_state(address, AddressStateTransitionTo::SetReserved, rng); self.reserved_nodes.insert(address); } - pub fn remove_reserved_node(&mut self, address: SocketAddress) { - self.change_address_state(address, AddressStateTransitionTo::UnsetReserved); + pub fn remove_reserved_node(&mut self, address: SocketAddress, rng: &mut impl Rng) { + self.change_address_state(address, AddressStateTransitionTo::UnsetReserved, rng); self.reserved_nodes.remove(&address); } diff --git a/p2p/src/peer_manager/peerdb/salt.rs b/p2p/src/peer_manager/peerdb/salt.rs index f7581f254f..a0f7098f9e 100644 --- a/p2p/src/peer_manager/peerdb/salt.rs +++ b/p2p/src/peer_manager/peerdb/salt.rs @@ -15,7 +15,7 @@ use std::hash::{Hash, Hasher}; -use randomness::{make_pseudo_rng, Rng}; +use randomness::Rng; use serialization::{Decode, Encode}; /// A random number that is generated once and then mixed into certain hashes in the peer manager. @@ -27,11 +27,7 @@ impl Salt { Self(val) } - pub fn new_random() -> Self { - Self::new_random_with_rng(&mut make_pseudo_rng()) - } - - pub fn new_random_with_rng(rng: &mut R) -> Self { + pub fn new_random(rng: &mut impl Rng) -> Self { Self(rng.gen::()) } diff --git a/p2p/src/peer_manager/peerdb/storage_load.rs b/p2p/src/peer_manager/peerdb/storage_load.rs index fdf888ed52..adefdfe1d8 100644 --- a/p2p/src/peer_manager/peerdb/storage_load.rs +++ b/p2p/src/peer_manager/peerdb/storage_load.rs @@ -17,6 +17,7 @@ use std::collections::{BTreeMap, BTreeSet}; use common::primitives::time::Time; use p2p_types::{bannable_address::BannableAddress, socket_address::SocketAddress}; +use randomness::Rng; use crate::{ error::P2pError, @@ -44,13 +45,14 @@ impl LoadedStorage { pub fn load_storage( storage: &S, peerdb_config: &PeerDbConfig, + rng: &mut impl Rng, ) -> crate::Result { let tx = storage.transaction_ro()?; let version = tx.get_version()?; tx.close(); match version { - None => Self::init_storage(storage, peerdb_config), + None => Self::init_storage(storage, peerdb_config, rng), Some(CURRENT_STORAGE_VERSION) => Self::load_storage_v3(storage), Some(version) => Err(P2pError::PeerDbStorageVersionMismatch { expected_version: CURRENT_STORAGE_VERSION, @@ -62,8 +64,9 @@ impl LoadedStorage { fn init_storage( storage: &S, peerdb_config: &PeerDbConfig, + rng: &mut impl Rng, ) -> crate::Result { - let salt = peerdb_config.salt.unwrap_or_else(Salt::new_random); + let salt = peerdb_config.salt.unwrap_or_else(|| Salt::new_random(rng)); let mut tx = storage.transaction_rw()?; tx.set_version(CURRENT_STORAGE_VERSION)?; diff --git a/p2p/src/peer_manager/peerdb/tests.rs b/p2p/src/peer_manager/peerdb/tests.rs index a1eae84b8a..25742640b7 100644 --- a/p2p/src/peer_manager/peerdb/tests.rs +++ b/p2p/src/peer_manager/peerdb/tests.rs @@ -79,6 +79,7 @@ fn ban_peer(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -139,6 +140,7 @@ fn unban_peer_manually(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -186,6 +188,7 @@ fn ban_peer_twice(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -234,6 +237,7 @@ fn ban_for_max_duration(#[case] seed: Seed) { Arc::new(test_p2p_config()), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -275,6 +279,7 @@ fn discourage_peer(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -335,6 +340,7 @@ fn undiscourage_peer_manually(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -384,6 +390,7 @@ fn discourage_peer_twice(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -452,6 +459,7 @@ fn discourage_for_max_duration(#[case] seed: Seed) { })), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -488,17 +496,18 @@ fn connected_unreachable(#[case] seed: Seed) { p2p_config, time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); let address = TestAddressMaker::new_random_address(&mut rng).into(); peerdb.peer_discovered(address); - peerdb.report_outbound_failure(address); + peerdb.report_outbound_failure(address, &mut rng); assert!(peerdb.addresses.get(&address).unwrap().is_unreachable()); // User requests connection to the currently unreachable node via RPC and connection succeeds. // PeerDb should process that normally. - peerdb.outbound_peer_connected(address); + peerdb.outbound_peer_connected(address, &mut rng); assert!(peerdb.addresses.get(&address).unwrap().is_connected()); assert_addr_consistency(&peerdb); @@ -520,6 +529,7 @@ fn connected_unknown(#[case] seed: Seed) { p2p_config, time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -527,7 +537,7 @@ fn connected_unknown(#[case] seed: Seed) { // User requests connection to some unknown node via RPC and connection succeeds. // PeerDb should process that normally. - peerdb.outbound_peer_connected(address); + peerdb.outbound_peer_connected(address, &mut rng); assert!(peerdb.addresses.get(&address).unwrap().is_connected()); assert_addr_consistency(&peerdb); @@ -550,6 +560,7 @@ fn anchor_peers(#[case] seed: Seed) { Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -573,6 +584,7 @@ fn anchor_peers(#[case] seed: Seed) { Arc::clone(&p2p_config), time_getter.get_time_getter(), peerdb.storage, + &mut rng, ) .unwrap(); assert_eq!(*peerdb.anchors(), anchors); @@ -585,6 +597,7 @@ fn anchor_peers(#[case] seed: Seed) { Arc::clone(&p2p_config), time_getter.get_time_getter(), peerdb.storage, + &mut rng, ) .unwrap(); assert_eq!(*peerdb.anchors(), anchors); @@ -608,7 +621,7 @@ fn remove_addr(#[case] seed: Seed) { addr_tables_bucket_size: 10.into(), new_addr_table_bucket_count: 10.into(), tried_addr_table_bucket_count: 10.into(), - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), })); let mut peerdb = PeerDb::new( @@ -616,6 +629,7 @@ fn remove_addr(#[case] seed: Seed) { Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -630,15 +644,15 @@ fn remove_addr(#[case] seed: Seed) { // Reserved addresses are often treated differently, so mark two of the to-remove addresses // as reserved. - peerdb.add_reserved_node(*new_addrs_to_remove.first().unwrap()); - peerdb.add_reserved_node(*tried_addrs_to_remove.first().unwrap()); + peerdb.add_reserved_node(*new_addrs_to_remove.first().unwrap(), &mut rng); + peerdb.add_reserved_node(*tried_addrs_to_remove.first().unwrap(), &mut rng); for addr in &new_addrs { peerdb.peer_discovered(*addr); } for addr in &tried_addrs { - peerdb.outbound_peer_connected(*addr); + peerdb.outbound_peer_connected(*addr, &mut rng); } for addr in new_addrs_to_remove.iter().chain(tried_addrs_to_remove.iter()) { @@ -669,7 +683,7 @@ fn remove_unreachable(#[case] seed: Seed) { addr_tables_bucket_size: 10.into(), new_addr_table_bucket_count: 10.into(), tried_addr_table_bucket_count: 10.into(), - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), })); let mut peerdb = PeerDb::new( @@ -677,6 +691,7 @@ fn remove_unreachable(#[case] seed: Seed) { Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -692,7 +707,7 @@ fn remove_unreachable(#[case] seed: Seed) { } for addr in &tried_addrs { - peerdb.outbound_peer_connected(*addr); + peerdb.outbound_peer_connected(*addr, &mut rng); } assert_eq!(new_addr_table(&peerdb).addr_count(), addr_count); @@ -704,12 +719,12 @@ fn remove_unreachable(#[case] seed: Seed) { split_in_two_sets(&tried_addrs, &mut rng); for addr in &new_addrs_unreachable { - peerdb.report_outbound_failure(*addr); + peerdb.report_outbound_failure(*addr, &mut rng); } for addr in &tried_addrs_unreachable { - peerdb.outbound_peer_disconnected(*addr); - peerdb.report_outbound_failure(*addr); + peerdb.outbound_peer_disconnected(*addr, &mut rng); + peerdb.report_outbound_failure(*addr, &mut rng); } assert_addr_consistency(&peerdb); @@ -729,7 +744,7 @@ fn remove_unreachable(#[case] seed: Seed) { // Call report_outbound_failure until the fail count reaches the limit. for addr in &tried_addrs_unreachable { for _ in 0..PURGE_REACHABLE_FAIL_COUNT - 1 { - peerdb.report_outbound_failure(*addr); + peerdb.report_outbound_failure(*addr, &mut rng); } } @@ -765,7 +780,7 @@ fn new_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserved_ addr_tables_bucket_size: bucket_size.into(), new_addr_table_bucket_count: bucket_count.into(), tried_addr_table_bucket_count: bucket_count.into(), - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), })); let mut peerdb = PeerDb::new( @@ -773,6 +788,7 @@ fn new_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserved_ Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -783,13 +799,13 @@ fn new_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserved_ let addr = make_random_address(&mut rng); if use_reserved_nodes && i % 3 == 0 { - peerdb.add_reserved_node(addr); + peerdb.add_reserved_node(addr, &mut rng); } peerdb.peer_discovered(addr); if use_reserved_nodes && i % 3 == 1 { - peerdb.add_reserved_node(addr); + peerdb.add_reserved_node(addr, &mut rng); } let new_addr_count = new_addr_table(&peerdb).addr_count(); @@ -824,7 +840,7 @@ fn tried_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserve addr_tables_bucket_size: bucket_size.into(), new_addr_table_bucket_count: bucket_count.into(), tried_addr_table_bucket_count: bucket_count.into(), - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), })); let mut peerdb = PeerDb::new( @@ -832,6 +848,7 @@ fn tried_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserve Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); @@ -842,13 +859,13 @@ fn tried_addr_count_limit(#[case] seed: Seed, #[values(true, false)] use_reserve let addr = make_random_address(&mut rng); if use_reserved_nodes && i % 3 == 0 { - peerdb.add_reserved_node(addr); + peerdb.add_reserved_node(addr, &mut rng); } - peerdb.outbound_peer_connected(addr); + peerdb.outbound_peer_connected(addr, &mut rng); if use_reserved_nodes && i % 3 == 1 { - peerdb.add_reserved_node(addr); + peerdb.add_reserved_node(addr, &mut rng); } let tried_addr_count = tried_addr_table(&peerdb).addr_count(); @@ -888,7 +905,7 @@ fn new_tried_addr_selection_frequency() { addr_tables_bucket_size: bucket_size.into(), new_addr_table_bucket_count: bucket_count.into(), tried_addr_table_bucket_count: bucket_count.into(), - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), })); let mut peerdb = PeerDb::new( @@ -896,6 +913,7 @@ fn new_tried_addr_selection_frequency() { Arc::clone(&p2p_config), time_getter.get_time_getter(), db_store, + &mut rng, ) .unwrap(); // We'll be adding lots of addresses and the checks will cause a huge slowdown. @@ -916,10 +934,10 @@ fn new_tried_addr_selection_frequency() { peerdb.peer_discovered(addr); } for addr in tried_addrs { - peerdb.outbound_peer_connected(addr); + peerdb.outbound_peer_connected(addr, &mut rng); // Mark the address as disconnected, otherwise it won't be selected by // select_non_reserved_outbound_addresses. - peerdb.outbound_peer_disconnected(addr); + peerdb.outbound_peer_disconnected(addr, &mut rng); } // Advance time, so that previously connected addresses can be selected again. @@ -929,7 +947,7 @@ fn new_tried_addr_selection_frequency() { let mut total_selected_tried_addrs = 0; for _ in 0..100 { let count_to_select = rng.gen_range(count_to_select_range.clone()); - let selected_addrs = peerdb.select_non_reserved_outbound_addresses_with_rng( + let selected_addrs = peerdb.select_non_reserved_outbound_addresses( &empty_addr_groups_set, &|_| true, count_to_select, diff --git a/p2p/src/peer_manager/tests/addr_list_response_caching.rs b/p2p/src/peer_manager/tests/addr_list_response_caching.rs index c4537175e5..30d4ccb83f 100644 --- a/p2p/src/peer_manager/tests/addr_list_response_caching.rs +++ b/p2p/src/peer_manager/tests/addr_list_response_caching.rs @@ -22,11 +22,12 @@ use common::{ chain::{self, ChainConfig}, primitives::user_agent::mintlayer_core_user_agent, }; -use networking::test_helpers::TestAddressMaker; -use networking::{transport::TcpTransportSocket, types::ConnectionDirection}; +use networking::{ + test_helpers::TestAddressMaker, transport::TcpTransportSocket, types::ConnectionDirection, +}; use p2p_test_utils::expect_recv; use p2p_types::peer_address::PeerAddress; -use randomness::Rng; +use randomness::{Rng, RngCore}; use test_utils::{ assert_matches_return_val, random::{make_seedable_rng, Seed}, @@ -77,8 +78,12 @@ async fn basic_test(#[case] seed: Seed) { let p2p_config = Arc::new(make_p2p_config()); let time_getter = BasicTestTimeGetter::new(); - let (mut peer_mgr, mut cmd_receiver) = - setup_peer_mgr(&chain_config, &p2p_config, &time_getter, &mut rng); + let (mut peer_mgr, mut cmd_receiver) = setup_peer_mgr( + &chain_config, + &p2p_config, + &time_getter, + make_seedable_rng(rng.gen()), + ); let peer1_address = TestAddressMaker::new_random_address(&mut rng); let (peer1_id, peer1_info) = make_new_peer(&chain_config); @@ -271,11 +276,13 @@ fn setup_peer_mgr( chain_config: &Arc, p2p_config: &Arc, time_getter: &BasicTestTimeGetter, - rng: &mut impl Rng, + mut rng: impl RngCore + Send + 'static, ) -> ( PeerManager, UnboundedReceiver, ) { + let mut another_rng = make_seedable_rng(rng.gen()); + let (mut peer_mgr, _conn_event_sender, _peer_mgr_event_sender, cmd_receiver, _) = make_standalone_peer_manager( Arc::clone(chain_config), @@ -284,12 +291,13 @@ fn setup_peer_mgr( // establish real connections, it doesn't really matter. vec![], time_getter.get_time_getter(), + rng, ); let addresses_in_db = make_non_colliding_addresses( &[peer_mgr.peerdb.address_tables().new_addr_table()], *p2p_config.protocol_config.max_addr_list_response_address_count * 10, - rng, + &mut another_rng, ); for address in addresses_in_db { diff --git a/p2p/src/peer_manager/tests/addresses.rs b/p2p/src/peer_manager/tests/addresses.rs index 395b5ca801..238b85dd7b 100644 --- a/p2p/src/peer_manager/tests/addresses.rs +++ b/p2p/src/peer_manager/tests/addresses.rs @@ -101,6 +101,7 @@ where Arc::clone(&config), p2p_config, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -188,6 +189,7 @@ fn test_addr_list_handling_inbound(#[case] seed: Seed) { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -279,6 +281,7 @@ fn test_addr_list_handling_outbound(#[case] seed: Seed) { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -396,6 +399,7 @@ async fn resend_own_addresses(#[case] seed: Seed) { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -511,6 +515,7 @@ async fn connect_to_predefined_address_if_dns_seed_is_empty(#[case] seed: Seed) peerdb_inmemory_store(), None, Box::new(TestDnsSeed::new(Arc::new(Mutex::new(Vec::new())))), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -581,6 +586,7 @@ async fn dont_connect_to_predefined_address_if_dns_seed_is_non_empty(#[case] see Box::new(TestDnsSeed::new(Arc::new(Mutex::new(vec![ seeded_peer_address, ])))), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -654,6 +660,7 @@ async fn connect_to_predefined_address_if_dns_seed_returned_bogus_address(#[case Box::new(TestDnsSeed::new(Arc::new(Mutex::new(vec![ seeded_peer_address, ])))), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -756,6 +763,7 @@ async fn dont_use_dns_seed_if_connections_exist(#[case] seed: Seed) { Box::new(TestDnsSeed::new(Arc::new(Mutex::new(vec![ seeded_peer_address, ])))), + make_seedable_rng(rng.gen()), ) .unwrap(); diff --git a/p2p/src/peer_manager/tests/ban.rs b/p2p/src/peer_manager/tests/ban.rs index dd8069b493..9ac55eebb1 100644 --- a/p2p/src/peer_manager/tests/ban.rs +++ b/p2p/src/peer_manager/tests/ban.rs @@ -20,6 +20,7 @@ use rstest::rstest; use common::{chain::config, primitives::user_agent::mintlayer_core_user_agent}; use networking::test_helpers::{TestAddressMaker, TestTransportMaker, TestTransportTcp}; use p2p_test_utils::{expect_no_recv, expect_recv, wait_for_no_recv}; +use randomness::Rng as _; use test_utils::{ random::{make_seedable_rng, Seed}, BasicTestTimeGetter, @@ -89,6 +90,7 @@ async fn dont_auto_ban_connected_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_mgr_join_handle = tokio_spawn_in_current_tracing_span( @@ -157,6 +159,7 @@ async fn disconnect_manually_banned_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_mgr_join_handle = tokio_spawn_in_current_tracing_span( @@ -247,6 +250,7 @@ async fn reject_incoming_connection_from_banned_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -342,6 +346,7 @@ async fn no_outgoing_connection_to_banned_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -429,6 +434,7 @@ async fn banned_address_is_not_announced(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -553,6 +559,7 @@ async fn banned_address_not_in_addr_response(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( diff --git a/p2p/src/peer_manager/tests/connections.rs b/p2p/src/peer_manager/tests/connections.rs index 1976f6147f..c0a45fddc7 100644 --- a/p2p/src/peer_manager/tests/connections.rs +++ b/p2p/src/peer_manager/tests/connections.rs @@ -103,6 +103,7 @@ where A::make_transport(), A::make_address().into(), Arc::clone(&config), + make_seedable_rng(rng.gen()), ) .await; @@ -166,12 +167,14 @@ async fn validate_invalid_connection_noise(#[case] seed: Seed) { .await; } -async fn inbound_connection_invalid_magic() +async fn inbound_connection_invalid_magic(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); @@ -179,12 +182,14 @@ where A::make_transport(), addr1, Arc::new(config::create_unit_test_config()), + make_seedable_rng(rng.gen()), ) .await; let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( A::make_transport(), addr2, Arc::new(config::Builder::test_chain().magic_bytes(MagicBytes::new([1, 2, 3, 4])).build()), + make_seedable_rng(rng.gen()), ) .await; @@ -206,38 +211,48 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_invalid_magic_tcp() { +async fn inbound_connection_invalid_magic_tcp(#[case] seed: Seed) { inbound_connection_invalid_magic::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_invalid_magic_channels() { +async fn inbound_connection_invalid_magic_channels(#[case] seed: Seed) { inbound_connection_invalid_magic::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_invalid_magic_noise() { +async fn inbound_connection_invalid_magic_noise(#[case] seed: Seed) { inbound_connection_invalid_magic::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } // try to connect to an address that no one listening on and verify it fails async fn test_peer_manager_connect( + seed: Seed, transport: T::Transport, bind_addr: SocketAddress, remote_addr: SocketAddress, @@ -245,9 +260,11 @@ async fn test_peer_manager_connect( T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let config = Arc::new(config::create_unit_test_config()); let (mut peer_manager, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(transport, bind_addr, config).await; + make_peer_manager::(transport, bind_addr, config, make_seedable_rng(rng.gen())).await; peer_manager.try_connect(remote_addr, None, PeerRole::OutboundManual).unwrap(); @@ -260,14 +277,18 @@ async fn test_peer_manager_connect( )); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn test_peer_manager_connect_tcp() { +async fn test_peer_manager_connect_tcp(#[case] seed: Seed) { let transport = TestTransportTcp::make_transport(); let bind_addr = TestTransportTcp::make_address().into(); let remote_addr: SocketAddress = "[::1]:1".parse().unwrap(); test_peer_manager_connect::>( + seed, transport, bind_addr, remote_addr, @@ -275,14 +296,18 @@ async fn test_peer_manager_connect_tcp() { .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn test_peer_manager_connect_tcp_noise() { +async fn test_peer_manager_connect_tcp_noise(#[case] seed: Seed) { let transport = TestTransportNoise::make_transport(); let bind_addr = TestTransportTcp::make_address().into(); let remote_addr: SocketAddress = "[::1]:1".parse().unwrap(); test_peer_manager_connect::>( + seed, transport, bind_addr, remote_addr, @@ -292,20 +317,32 @@ async fn test_peer_manager_connect_tcp_noise() { // verify that the auto-connect functionality works if the number of active connections // is below the desired threshold and there are idle peers in the peerdb -async fn test_auto_connect() +async fn test_auto_connect(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); let config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&config)).await; - let (mut pm2, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr2, config).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; + let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr2, + config, + make_seedable_rng(rng.gen()), + ) + .await; let addr = pm2.peer_connectivity_handle.local_addresses()[0]; @@ -329,39 +366,61 @@ where )); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn test_auto_connect_tcp() { - test_auto_connect::>().await; +async fn test_auto_connect_tcp(#[case] seed: Seed) { + test_auto_connect::>(seed).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn test_auto_connect_channels() { - test_auto_connect::>() +async fn test_auto_connect_channels(#[case] seed: Seed) { + test_auto_connect::>(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn test_auto_connect_noise() { - test_auto_connect::>().await; +async fn test_auto_connect_noise(#[case] seed: Seed) { + test_auto_connect::>(seed) + .await; } -async fn connect_outbound_same_network() +async fn connect_outbound_same_network(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); let config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&config)).await; - let (mut pm2, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr2, config).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; + let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr2, + config, + make_seedable_rng(rng.gen()), + ) + .await; connect_services::( &mut pm1.peer_connectivity_handle, @@ -370,44 +429,61 @@ where .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_same_network_tcp() { - connect_outbound_same_network::>().await; +async fn connect_outbound_same_network_tcp(#[case] seed: Seed) { + connect_outbound_same_network::>(seed).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_same_network_channels() { +async fn connect_outbound_same_network_channels(#[case] seed: Seed) { connect_outbound_same_network::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_same_network_noise() { - connect_outbound_same_network::>().await; +async fn connect_outbound_same_network_noise(#[case] seed: Seed) { + connect_outbound_same_network::>(seed).await; } -async fn connect_outbound_different_network() +async fn connect_outbound_different_network(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); let config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&config)).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( A::make_transport(), addr2, Arc::new(config::Builder::test_chain().magic_bytes(MagicBytes::new([1, 2, 3, 4])).build()), + make_seedable_rng(rng.gen()), ) .await; @@ -419,50 +495,71 @@ where assert_ne!(peer_info.network, *config.magic_bytes()); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_different_network_tcp() { +async fn connect_outbound_different_network_tcp(#[case] seed: Seed) { connect_outbound_different_network::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_different_network_channels() { +async fn connect_outbound_different_network_channels(#[case] seed: Seed) { connect_outbound_different_network::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_outbound_different_network_noise() { +async fn connect_outbound_different_network_noise(#[case] seed: Seed) { connect_outbound_different_network::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } -async fn connect_inbound_same_network() +async fn connect_inbound_same_network(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); let config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&config)).await; - let (mut pm2, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr2, config).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; + let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr2, + config, + make_seedable_rng(rng.gen()), + ) + .await; let (address, peer_info, _) = connect_services::( &mut pm1.peer_connectivity_handle, @@ -479,36 +576,48 @@ where .unwrap(); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_same_network_tcp() { +async fn connect_inbound_same_network_tcp(#[case] seed: Seed) { connect_inbound_same_network::>( + seed, ) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_same_network_channel() { +async fn connect_inbound_same_network_channel(#[case] seed: Seed) { connect_inbound_same_network::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_same_network_noise() { - connect_inbound_same_network::>().await; +async fn connect_inbound_same_network_noise(#[case] seed: Seed) { + connect_inbound_same_network::>(seed).await; } -async fn connect_inbound_different_network() +async fn connect_inbound_different_network(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); @@ -516,12 +625,14 @@ where A::make_transport(), addr1, Arc::new(config::create_unit_test_config()), + make_seedable_rng(rng.gen()), ) .await; let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( A::make_transport(), addr2, Arc::new(config::Builder::test_chain().magic_bytes(MagicBytes::new([1, 2, 3, 4])).build()), + make_seedable_rng(rng.gen()), ) .await; @@ -548,42 +659,53 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_different_network_tcp() { +async fn connect_inbound_different_network_tcp(#[case] seed: Seed) { connect_inbound_different_network::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_different_network_channels() { +async fn connect_inbound_different_network_channels(#[case] seed: Seed) { connect_inbound_different_network::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connect_inbound_different_network_noise() { +async fn connect_inbound_different_network_noise(#[case] seed: Seed) { connect_inbound_different_network::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } -async fn remote_closes_connection() +async fn remote_closes_connection(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); @@ -591,12 +713,14 @@ where A::make_transport(), addr1, Arc::new(config::create_unit_test_config()), + make_seedable_rng(rng.gen()), ) .await; let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( A::make_transport(), addr2, Arc::new(config::create_unit_test_config()), + make_seedable_rng(rng.gen()), ) .await; @@ -616,40 +740,65 @@ where )); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn remote_closes_connection_tcp() { - remote_closes_connection::>() - .await; +async fn remote_closes_connection_tcp(#[case] seed: Seed) { + remote_closes_connection::>( + seed, + ) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn remote_closes_connection_channels() { - remote_closes_connection::>().await; +async fn remote_closes_connection_channels(#[case] seed: Seed) { + remote_closes_connection::>(seed).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn remote_closes_connection_noise() { - remote_closes_connection::>() - .await; +async fn remote_closes_connection_noise(#[case] seed: Seed) { + remote_closes_connection::>( + seed, + ) + .await; } -async fn inbound_connection_too_many_peers(peers: Vec<(SocketAddress, PeerInfo)>) +async fn inbound_connection_too_many_peers(seed: Seed, peers: Vec<(SocketAddress, PeerInfo)>) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2 = A::make_address().into(); let config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&config)).await; - let (mut pm2, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr2, Arc::clone(&config)).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; + let (mut pm2, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr2, + Arc::clone(&config), + make_seedable_rng(rng.gen()), + ) + .await; for peer in peers.into_iter() { pm1.try_accept_connection(peer.0, addr2, PeerRole::Inbound, peer.1, None) @@ -675,9 +824,12 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_too_many_peers_tcp() { +async fn inbound_connection_too_many_peers_tcp(#[case] seed: Seed) { let config = Arc::new(config::create_unit_test_config()); let peers = (0..*MaxInboundConnections::default()) .map(|index| { @@ -698,13 +850,16 @@ async fn inbound_connection_too_many_peers_tcp() { inbound_connection_too_many_peers::< TestTransportTcp, DefaultNetworkingService, - >(peers) + >(seed, peers) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_too_many_peers_channels() { +async fn inbound_connection_too_many_peers_channels(#[case] seed: Seed) { let config = Arc::new(config::create_unit_test_config()); let peers = (0..*MaxInboundConnections::default()) .map(|index| { @@ -725,13 +880,16 @@ async fn inbound_connection_too_many_peers_channels() { inbound_connection_too_many_peers::< TestTransportChannel, DefaultNetworkingService, - >(peers) + >(seed, peers) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn inbound_connection_too_many_peers_noise() { +async fn inbound_connection_too_many_peers_noise(#[case] seed: Seed) { let config = Arc::new(config::create_unit_test_config()); let peers = (0..*MaxInboundConnections::default()) .map(|index| { @@ -752,7 +910,7 @@ async fn inbound_connection_too_many_peers_noise() { inbound_connection_too_many_peers::< TestTransportNoise, DefaultNetworkingService, - >(peers) + >(seed, peers) .await; } @@ -831,6 +989,7 @@ async fn connection_timeout_noise() { // try to establish a new connection through RPC and verify that it is notified of the timeout async fn connection_timeout_rpc_notified( + seed: Seed, transport: T::Transport, addr1: SocketAddress, addr2: SocketAddress, @@ -838,6 +997,8 @@ async fn connection_timeout_rpc_notified( T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let config = Arc::new(config::create_unit_test_config()); let p2p_config = Arc::new(P2pConfig { outbound_connection_timeout: Duration::from_secs(1).into(), @@ -888,6 +1049,7 @@ async fn connection_timeout_rpc_notified( peer_mgr_event_receiver, time_getter, peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -918,10 +1080,14 @@ async fn connection_timeout_rpc_notified( // Address is reserved for "TEST-NET-2" documentation and examples. See: https://en.wikipedia.org/wiki/Reserved_IP_addresses const GUARANTEED_TIMEOUT_ADDRESS: &str = "198.51.100.2:1"; -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_timeout_rpc_notified_tcp() { +async fn connection_timeout_rpc_notified_tcp(#[case] seed: Seed) { connection_timeout_rpc_notified::>( + seed, TestTransportTcp::make_transport(), TestTransportTcp::make_address().into(), GUARANTEED_TIMEOUT_ADDRESS.parse().unwrap(), @@ -929,10 +1095,14 @@ async fn connection_timeout_rpc_notified_tcp() { .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_timeout_rpc_notified_channels() { +async fn connection_timeout_rpc_notified_channels(#[case] seed: Seed) { connection_timeout_rpc_notified::>( + seed, TestTransportChannel::make_transport(), TestTransportChannel::make_address().into(), GUARANTEED_TIMEOUT_ADDRESS.parse().unwrap(), @@ -940,10 +1110,14 @@ async fn connection_timeout_rpc_notified_channels() { .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_timeout_rpc_notified_noise() { +async fn connection_timeout_rpc_notified_noise(#[case] seed: Seed) { connection_timeout_rpc_notified::>( + seed, TestTransportNoise::make_transport(), TestTransportNoise::make_address().into(), GUARANTEED_TIMEOUT_ADDRESS.parse().unwrap(), @@ -952,12 +1126,14 @@ async fn connection_timeout_rpc_notified_noise() { } // verify that peer connection is made when valid reserved_node parameter is used -async fn connection_reserved_node() +async fn connection_reserved_node(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(config::create_unit_test_config()); @@ -989,6 +1165,7 @@ where Arc::clone(&chain_config), p2p_config_1, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1034,6 +1211,7 @@ where Arc::clone(&chain_config), p2p_config_2, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1059,38 +1237,52 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_reserved_node_tcp() { - connection_reserved_node::>() - .await; +async fn connection_reserved_node_tcp(#[case] seed: Seed) { + connection_reserved_node::>( + seed, + ) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_reserved_node_noise() { - connection_reserved_node::>() - .await; +async fn connection_reserved_node_noise(#[case] seed: Seed) { + connection_reserved_node::>( + seed, + ) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn connection_reserved_node_channel() { - connection_reserved_node::>() +async fn connection_reserved_node_channel(#[case] seed: Seed) { + connection_reserved_node::>(seed) .await; } // Verify that peers announce own addresses and are discovered by other peers. // All listening addresses are discovered and multiple connections are made. // All peers are in the same address group -async fn discovered_node_same_address_group() +async fn discovered_node_same_address_group(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { - let chain_config = Arc::new(config::create_unit_test_config()); + let mut rng = make_seedable_rng(seed); + let chain_config = Arc::new(config::create_unit_test_config()); let time_getter = BasicTestTimeGetter::new(); let peer_manager_config = PeerManagerConfig { @@ -1145,6 +1337,7 @@ where Arc::clone(&chain_config), p2p_config_1, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1190,6 +1383,7 @@ where Arc::clone(&chain_config), p2p_config_2, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1222,6 +1416,7 @@ where Arc::clone(&chain_config), p2p_config_3, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1263,41 +1458,55 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn discovered_node_tcp() { +async fn discovered_node_tcp(#[case] seed: Seed) { discovered_node_same_address_group::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn discovered_node_noise() { +async fn discovered_node_noise(#[case] seed: Seed) { discovered_node_same_address_group::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn discovered_node_channel() { +async fn discovered_node_channel(#[case] seed: Seed) { discovered_node_same_address_group::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } // Create 3 peers and make one of them a reserved node. // Put reserved node in a separate address group. -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn discovered_node_2_groups() { +async fn discovered_node_2_groups(#[case] seed: Seed) { + let mut rng = make_seedable_rng(seed); + let chain_config = Arc::new(config::create_unit_test_config()); let time_getter = BasicTestTimeGetter::new(); @@ -1354,6 +1563,7 @@ async fn discovered_node_2_groups() { Arc::clone(&chain_config), p2p_config_1, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1400,6 +1610,7 @@ async fn discovered_node_2_groups() { Arc::clone(&chain_config), p2p_config_2, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1433,6 +1644,7 @@ async fn discovered_node_2_groups() { Arc::clone(&chain_config), p2p_config_3, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1466,9 +1678,14 @@ async fn discovered_node_2_groups() { } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn discovered_node_separate_groups() { +async fn discovered_node_separate_groups(#[case] seed: Seed) { + let mut rng = make_seedable_rng(seed); + let chain_config = Arc::new(config::create_unit_test_config()); let time_getter = BasicTestTimeGetter::new(); @@ -1525,6 +1742,7 @@ async fn discovered_node_separate_groups() { Arc::clone(&chain_config), p2p_config_1, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1571,6 +1789,7 @@ async fn discovered_node_separate_groups() { Arc::clone(&chain_config), p2p_config_2, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1604,6 +1823,7 @@ async fn discovered_node_separate_groups() { Arc::clone(&chain_config), p2p_config_3, time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ) .await; @@ -1684,6 +1904,7 @@ async fn feeler_connections_test_impl(seed: Seed) { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -1873,7 +2094,7 @@ mod feeler_connections_test_utils { feeler_connections_interval: feeler_connections_interval.into(), peerdb_config: PeerDbConfig { - salt: Some(Salt::new_random_with_rng(rng)), + salt: Some(Salt::new_random(rng)), new_addr_table_bucket_count: Default::default(), tried_addr_table_bucket_count: Default::default(), @@ -2019,6 +2240,7 @@ async fn reject_connection_to_existing_ip(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -2169,6 +2391,7 @@ async fn feeler_connection_to_ip_address_of_inbound_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addr = TestAddressMaker::new_random_address(&mut rng); diff --git a/p2p/src/peer_manager/tests/discouragement.rs b/p2p/src/peer_manager/tests/discouragement.rs index 887da14c58..7a6ea73865 100644 --- a/p2p/src/peer_manager/tests/discouragement.rs +++ b/p2p/src/peer_manager/tests/discouragement.rs @@ -20,6 +20,7 @@ use rstest::rstest; use common::{chain::config, primitives::user_agent::mintlayer_core_user_agent}; use networking::test_helpers::{TestAddressMaker, TestTransportMaker, TestTransportTcp}; use p2p_test_utils::{expect_no_recv, expect_recv, wait_for_no_recv}; +use randomness::Rng as _; use test_utils::{ random::{make_seedable_rng, Seed}, BasicTestTimeGetter, @@ -89,6 +90,7 @@ async fn discourage_connected_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_mgr_join_handle = tokio_spawn_in_current_tracing_span( @@ -217,6 +219,7 @@ async fn dont_reject_incoming_connection_from_discouraged_peer_if_limit_not_reac Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addr: SocketAddress = TestAddressMaker::new_random_address(&mut rng).into(); @@ -293,6 +296,7 @@ async fn reject_incoming_connection_from_discouraged_peer_if_limit_reached(#[cas Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -415,6 +419,7 @@ async fn no_outgoing_connection_to_discouraged_peer(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let peer_addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -501,6 +506,7 @@ async fn discouraged_address_is_not_announced(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( @@ -624,6 +630,7 @@ async fn discouraged_address_not_in_addr_response(#[case] seed: Seed) { Arc::clone(&p2p_config), vec![bind_addr], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let addrs = make_non_colliding_addresses_for_peer_db_in_distinct_addr_groups( diff --git a/p2p/src/peer_manager/tests/eviction.rs b/p2p/src/peer_manager/tests/eviction.rs index 9399d3c906..2f646a8287 100644 --- a/p2p/src/peer_manager/tests/eviction.rs +++ b/p2p/src/peer_manager/tests/eviction.rs @@ -25,6 +25,7 @@ use common::{ use logging::log; use networking::test_helpers::{TestTransportMaker, TestTransportTcp}; use p2p_test_utils::{expect_no_recv, expect_recv}; +use randomness::Rng as _; use test_utils::{ random::{make_seedable_rng, Seed}, BasicTestTimeGetter, @@ -101,7 +102,7 @@ mod dont_evict_if_blocks_in_flight { enable_feeler_connections: false.into(), peerdb_config: PeerDbConfig { - salt: Some(Salt::new_random_with_rng(&mut rng)), + salt: Some(Salt::new_random(&mut rng)), new_addr_table_bucket_count: Default::default(), tried_addr_table_bucket_count: Default::default(), @@ -159,6 +160,7 @@ mod dont_evict_if_blocks_in_flight { Arc::clone(&p2p_config), vec![bind_address], time_getter.get_time_getter(), + make_seedable_rng(rng.gen()), ); let addr_count = 3; diff --git a/p2p/src/peer_manager/tests/mod.rs b/p2p/src/peer_manager/tests/mod.rs index b93f37c8f8..3e36ebc760 100644 --- a/p2p/src/peer_manager/tests/mod.rs +++ b/p2p/src/peer_manager/tests/mod.rs @@ -39,7 +39,7 @@ use common::{chain::ChainConfig, time_getter::TimeGetter}; use networking::transport::TcpTransportSocket; use p2p_test_utils::expect_recv; use p2p_types::socket_address::SocketAddress; -use randomness::Rng; +use randomness::{Rng, RngCore}; use test_utils::assert_matches_return_val; use crate::{ @@ -68,6 +68,7 @@ async fn make_peer_manager_custom( chain_config: Arc, p2p_config: Arc, time_getter: TimeGetter, + rng: impl RngCore + Send + 'static, ) -> ( PeerManager, UnboundedSender, @@ -104,6 +105,7 @@ where peer_mgr_event_receiver, time_getter, peerdb_inmemory_store(), + rng, ) .unwrap(); @@ -119,6 +121,7 @@ async fn make_peer_manager( transport: T::Transport, bind_address: SocketAddress, chain_config: Arc, + rng: impl RngCore + Send + 'static, ) -> ( PeerManager, oneshot::Sender<()>, @@ -136,6 +139,7 @@ where chain_config, p2p_config, Default::default(), + rng, ) .await; (peer_manager, shutdown_sender, subscribers_sender) @@ -150,6 +154,7 @@ pub fn make_standalone_peer_manager( p2p_config: Arc, bind_addresses: Vec, time_getter: TimeGetter, + rng: impl RngCore + Send + 'static, ) -> ( PeerManager, mpsc::UnboundedSender, @@ -180,6 +185,7 @@ pub fn make_standalone_peer_manager( peerdb_inmemory_store(), Some(peer_mgr_observer), Box::new(dns_seed), + rng, ) .unwrap(); @@ -198,6 +204,7 @@ async fn run_peer_manager( chain_config: Arc, p2p_config: Arc, time_getter: TimeGetter, + rng: impl RngCore + Send + 'static, ) -> ( UnboundedSender, oneshot::Sender<()>, @@ -208,7 +215,8 @@ where T::ConnectivityHandle: ConnectivityService, { let (peer_manager, peer_mgr_event_sender, shutdown_sender, subscribers_sender) = - make_peer_manager_custom::(transport, addr, chain_config, p2p_config, time_getter).await; + make_peer_manager_custom::(transport, addr, chain_config, p2p_config, time_getter, rng) + .await; tokio_spawn_in_current_tracing_span( // Rust 1.92 thinks that the unwrap call here is unreachable, even though the function // returns a normal error. @@ -235,10 +243,11 @@ async fn send_and_sync( message: PeerManagerMessage, conn_event_sender: &UnboundedSender, cmd_receiver: &mut UnboundedReceiver, + rng: &mut impl Rng, ) { conn_event_sender.send(ConnectivityEvent::Message { peer_id, message }).unwrap(); - let sent_nonce = randomness::make_pseudo_rng().gen(); + let sent_nonce = rng.gen(); conn_event_sender .send(ConnectivityEvent::Message { peer_id, diff --git a/p2p/src/peer_manager/tests/peer_types.rs b/p2p/src/peer_manager/tests/peer_types.rs index 51c6d1ed55..d82520c894 100644 --- a/p2p/src/peer_manager/tests/peer_types.rs +++ b/p2p/src/peer_manager/tests/peer_types.rs @@ -15,13 +15,19 @@ use std::sync::Arc; +use rstest::rstest; + use common::{chain::config, primitives::user_agent::mintlayer_core_user_agent}; use networking::transport::TcpTransportSocket; use p2p_types::{ services::{Service, Services}, PeerId, }; -use test_utils::BasicTestTimeGetter; +use randomness::Rng as _; +use test_utils::{ + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ config::{NodeType, P2pConfig}, @@ -35,11 +41,15 @@ use crate::{ PeerManagerEvent, }; -#[tracing::instrument] -#[test] -fn validate_services() { +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] +fn validate_services(#[case] seed: Seed) { type TestNetworkingService = DefaultNetworkingService; + let mut rng = make_seedable_rng(seed); + for node_type in [NodeType::Full, NodeType::BlocksOnly] { let chain_config = Arc::new(config::create_unit_test_config()); let p2p_config = Arc::new(P2pConfig { @@ -84,6 +94,7 @@ fn validate_services() { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); diff --git a/p2p/src/peer_manager/tests/ping.rs b/p2p/src/peer_manager/tests/ping.rs index ce7e73853d..c551d8c561 100644 --- a/p2p/src/peer_manager/tests/ping.rs +++ b/p2p/src/peer_manager/tests/ping.rs @@ -15,11 +15,20 @@ use std::{sync::Arc, time::Duration}; +use rstest::rstest; + use common::{chain::config, primitives::user_agent::mintlayer_core_user_agent}; -use networking::test_helpers::{TestTransportMaker, TestTransportTcp}; -use networking::transport::TcpTransportSocket; +use networking::{ + test_helpers::{TestTransportMaker, TestTransportTcp}, + transport::TcpTransportSocket, +}; use p2p_test_utils::expect_recv; -use test_utils::{assert_matches, assert_matches_return_val, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, assert_matches_return_val, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use utils::tokio_spawn_in_current_tracing_span; use crate::{ @@ -39,11 +48,16 @@ use crate::{ PeerManagerEvent, }; -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn ping_timeout() { +async fn ping_timeout(#[case] seed: Seed) { type TestNetworkingService = DefaultNetworkingService; + let mut rng = make_seedable_rng(seed); + let chain_config = Arc::new(config::create_unit_test_config()); let p2p_config: Arc = Arc::new(P2pConfig { ping_check_period: Duration::from_secs(1).into(), @@ -90,6 +104,7 @@ async fn ping_timeout() { peer_mgr_event_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -139,6 +154,7 @@ async fn ping_timeout() { PeerManagerMessage::PingResponse(PingResponse { nonce }), &conn_event_sender, &mut cmd_receiver, + &mut rng, ) .await; } diff --git a/p2p/src/peer_manager/tests/whitelist.rs b/p2p/src/peer_manager/tests/whitelist.rs index ec2fad7e2f..d6d37852db 100644 --- a/p2p/src/peer_manager/tests/whitelist.rs +++ b/p2p/src/peer_manager/tests/whitelist.rs @@ -15,19 +15,19 @@ use std::{net::IpAddr, sync::Arc, time::Duration}; -use p2p_types::socket_address::SocketAddress; use rstest::rstest; use common::{chain::config, primitives::user_agent::mintlayer_core_user_agent}; -use networking::test_helpers::{ - TestAddressMaker, TestTransportChannel, TestTransportMaker, TestTransportNoise, - TestTransportTcp, -}; use networking::{ + test_helpers::{ + TestAddressMaker, TestTransportChannel, TestTransportMaker, TestTransportNoise, + TestTransportTcp, + }, transport::{MpscChannelTransport, NoiseTcpTransport, TcpTransportSocket}, types::ConnectionDirection, }; -use p2p_types::bannable_address::BannableAddress; +use p2p_types::{bannable_address::BannableAddress, socket_address::SocketAddress}; +use randomness::Rng as _; use test_utils::{ random::{make_seedable_rng, Seed}, BasicTestTimeGetter, @@ -78,12 +78,14 @@ fn p2p_config_with_whitelisted(whitelisted_addresses: Vec) -> P2pConfig } } -async fn no_automatic_ban_for_whitelisted() +async fn no_automatic_ban_for_whitelisted(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1: SocketAddress = A::make_address().into(); let addr2 = A::make_address().into(); @@ -96,6 +98,7 @@ where Arc::clone(&chain_config), Arc::clone(&p2p_config), Default::default(), + make_seedable_rng(rng.gen()), ) .await; @@ -105,6 +108,7 @@ where Arc::clone(&chain_config), Arc::clone(&p2p_config), Default::default(), + make_seedable_rng(rng.gen()), ) .await; @@ -129,50 +133,66 @@ where assert!(!pm2.peerdb.is_address_banned(&addr1.as_bannable())); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_ban_for_whitelisted_tcp() { +async fn no_automatic_ban_for_whitelisted_tcp(#[case] seed: Seed) { no_automatic_ban_for_whitelisted::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_ban_for_whitelisted_channels() { +async fn no_automatic_ban_for_whitelisted_channels(#[case] seed: Seed) { no_automatic_ban_for_whitelisted::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_ban_for_whitelisted_noise() { +async fn no_automatic_ban_for_whitelisted_noise(#[case] seed: Seed) { no_automatic_ban_for_whitelisted::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } // if an address was banned it won't be unbanned automatically if whitelisted -async fn no_automatic_unban_for_whitelisted() +async fn no_automatic_unban_for_whitelisted(seed: Seed) where A: TestTransportMaker, T: NetworkingService + std::fmt::Debug + 'static, T::ConnectivityHandle: ConnectivityService, { + let mut rng = make_seedable_rng(seed); + let addr1 = A::make_address().into(); let addr2: SocketAddress = A::make_address().into(); let chain_config = Arc::new(config::create_unit_test_config()); - let (mut pm1, _shutdown_sender, _subscribers_sender) = - make_peer_manager::(A::make_transport(), addr1, Arc::clone(&chain_config)).await; + let (mut pm1, _shutdown_sender, _subscribers_sender) = make_peer_manager::( + A::make_transport(), + addr1, + Arc::clone(&chain_config), + make_seedable_rng(rng.gen()), + ) + .await; let p2p_config = Arc::new(p2p_config_with_whitelisted(vec![ addr1.ip_addr(), @@ -206,7 +226,7 @@ where let mut tx = db.transaction_rw().unwrap(); tx.set_version(CURRENT_STORAGE_VERSION).unwrap(); - tx.set_salt(Salt::new_random()).unwrap(); + tx.set_salt(Salt::new_random(&mut rng)).unwrap(); tx.add_banned_address(&BannableAddress::new(addr1.ip_addr()), ban_until) .unwrap(); tx.commit().unwrap(); @@ -221,6 +241,7 @@ where peer_receiver, time_getter.get_time_getter(), db, + make_seedable_rng(rng.gen()), ) .unwrap(); @@ -242,33 +263,42 @@ where assert!(pm2.is_whitelisted_node(PeerRole::Inbound, &addr1)); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_unban_for_whitelisted_tcp() { +async fn no_automatic_unban_for_whitelisted_tcp(#[case] seed: Seed) { no_automatic_unban_for_whitelisted::< TestTransportTcp, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_unban_for_whitelisted_channels() { +async fn no_automatic_unban_for_whitelisted_channels(#[case] seed: Seed) { no_automatic_unban_for_whitelisted::< TestTransportChannel, DefaultNetworkingService, - >() + >(seed) .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test] -async fn no_automatic_unban_for_whitelisted_noise() { +async fn no_automatic_unban_for_whitelisted_noise(#[case] seed: Seed) { no_automatic_unban_for_whitelisted::< TestTransportNoise, DefaultNetworkingService, - >() + >(seed) .await; } @@ -279,6 +309,7 @@ async fn no_automatic_unban_for_whitelisted_noise() { fn manual_ban_overrides_whitelisting(#[case] seed: Seed) { type TestNetworkingService = DefaultNetworkingService; let mut rng = make_seedable_rng(seed); + let address_1: SocketAddress = TestAddressMaker::new_random_address(&mut rng).into(); let address_2 = TestAddressMaker::new_random_address(&mut rng).into(); @@ -302,6 +333,7 @@ fn manual_ban_overrides_whitelisting(#[case] seed: Seed) { peer_receiver, time_getter.get_time_getter(), peerdb_inmemory_store(), + make_seedable_rng(rng.gen()), ) .unwrap(); diff --git a/p2p/src/tests/bad_time_diff.rs b/p2p/src/tests/bad_time_diff.rs index 521787c405..803f1a2c6a 100644 --- a/p2p/src/tests/bad_time_diff.rs +++ b/p2p/src/tests/bad_time_diff.rs @@ -15,14 +15,23 @@ use std::{sync::Arc, time::Duration}; +use rstest::rstest; + use chainstate::ChainstateConfig; use common::primitives::{time::Time, user_agent::mintlayer_core_user_agent}; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportListener, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportListener, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ config::P2pConfig, @@ -36,11 +45,13 @@ use crate::{ // Check that a handshake is rejected if the time difference between the peers is too big. // Also check that the WillDisconnect message is sent if the protocol version is big enough. -async fn bad_time_diff_outgoing() +async fn bad_time_diff_outgoing(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + for protocol_version in [SupportedProtocolVersion::V2, SupportedProtocolVersion::V3] { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -78,6 +89,7 @@ where TTM::make_address().into(), protocol_version.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -143,29 +155,40 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_outgoing_tcp() { - run_with_timeout(bad_time_diff_outgoing::()).await; +async fn bad_time_diff_outgoing_tcp(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_outgoing_channels() { - run_with_timeout(bad_time_diff_outgoing::()).await; +async fn bad_time_diff_outgoing_channels(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_outgoing_noise() { - run_with_timeout(bad_time_diff_outgoing::()).await; +async fn bad_time_diff_outgoing_noise(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_outgoing::(seed)).await; } -async fn bad_time_diff_incoming() +async fn bad_time_diff_incoming(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + for protocol_version in [SupportedProtocolVersion::V2, SupportedProtocolVersion::V3] { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -203,6 +226,7 @@ where TTM::make_address().into(), protocol_version.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -258,20 +282,29 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_incoming_tcp() { - run_with_timeout(bad_time_diff_incoming::()).await; +async fn bad_time_diff_incoming_tcp(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_incoming_channels() { - run_with_timeout(bad_time_diff_incoming::()).await; +async fn bad_time_diff_incoming_channels(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn bad_time_diff_incoming_noise() { - run_with_timeout(bad_time_diff_incoming::()).await; +async fn bad_time_diff_incoming_noise(#[case] seed: Seed) { + run_with_timeout(bad_time_diff_incoming::(seed)).await; } diff --git a/p2p/src/tests/correct_handshake.rs b/p2p/src/tests/correct_handshake.rs index b660ef48bb..fdef195e35 100644 --- a/p2p/src/tests/correct_handshake.rs +++ b/p2p/src/tests/correct_handshake.rs @@ -15,13 +15,22 @@ use std::sync::Arc; +use rstest::rstest; + use chainstate::ChainstateConfig; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportListener, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportListener, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ net::default_backend::types::{HandshakeMessage, Message, P2pTimestamp}, @@ -33,11 +42,13 @@ use crate::{ // Note: these tests are mainly a sanity check to ensure that the corresponding test harness // is working properly. -async fn correct_handshake_outgoing() +async fn correct_handshake_outgoing(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -52,6 +63,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -105,29 +117,40 @@ where assert_eq!(peer_score, 0); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_outgoing_tcp() { - run_with_timeout(correct_handshake_outgoing::()).await; +async fn correct_handshake_outgoing_tcp(#[case] seed: Seed) { + run_with_timeout(correct_handshake_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_outgoing_channels() { - run_with_timeout(correct_handshake_outgoing::()).await; +async fn correct_handshake_outgoing_channels(#[case] seed: Seed) { + run_with_timeout(correct_handshake_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_outgoing_noise() { - run_with_timeout(correct_handshake_outgoing::()).await; +async fn correct_handshake_outgoing_noise(#[case] seed: Seed) { + run_with_timeout(correct_handshake_outgoing::(seed)).await; } -async fn correct_handshake_incoming() +async fn correct_handshake_incoming(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -142,6 +165,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -189,20 +213,29 @@ where assert_eq!(peer_score, 0); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_incoming_tcp() { - run_with_timeout(correct_handshake_incoming::()).await; +async fn correct_handshake_incoming_tcp(#[case] seed: Seed) { + run_with_timeout(correct_handshake_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_incoming_channels() { - run_with_timeout(correct_handshake_incoming::()).await; +async fn correct_handshake_incoming_channels(#[case] seed: Seed) { + run_with_timeout(correct_handshake_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn correct_handshake_incoming_noise() { - run_with_timeout(correct_handshake_incoming::()).await; +async fn correct_handshake_incoming_noise(#[case] seed: Seed) { + run_with_timeout(correct_handshake_incoming::(seed)).await; } diff --git a/p2p/src/tests/disable_networking.rs b/p2p/src/tests/disable_networking.rs index b016c62e31..c5f5ced450 100644 --- a/p2p/src/tests/disable_networking.rs +++ b/p2p/src/tests/disable_networking.rs @@ -15,11 +15,17 @@ use std::{collections::BTreeSet, sync::Arc, time::Duration}; +use rstest::rstest; + use chainstate::ChainstateConfig; use logging::log; use networking::test_helpers::{TestTransportChannel, TestTransportMaker}; use p2p_test_utils::run_with_timeout; -use test_utils::BasicTestTimeGetter; +use randomness::Rng as _; +use test_utils::{ + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ error::{DialError, P2pError}, @@ -33,15 +39,20 @@ use crate::{ }, }; -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn disable_networking() { - run_with_timeout(disable_networking_impl()).await; +async fn disable_networking(#[case] seed: Seed) { + run_with_timeout(disable_networking_impl(seed)).await; } -async fn disable_networking_impl() { +async fn disable_networking_impl(seed: Seed) { type Transport = ::Transport; + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let chainstate_config = ChainstateConfig::new(); @@ -58,6 +69,7 @@ async fn disable_networking_impl() { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), Some("test_node"), + make_seedable_rng(rng.gen()), ) .await; @@ -71,6 +83,7 @@ async fn disable_networking_impl() { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), Some("other_node1"), + make_seedable_rng(rng.gen()), ) .await; @@ -84,6 +97,7 @@ async fn disable_networking_impl() { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), Some("other_node2"), + make_seedable_rng(rng.gen()), ) .await; diff --git a/p2p/src/tests/disconnect_on_will_disconnect_msg.rs b/p2p/src/tests/disconnect_on_will_disconnect_msg.rs index 69707f294f..e56c67227d 100644 --- a/p2p/src/tests/disconnect_on_will_disconnect_msg.rs +++ b/p2p/src/tests/disconnect_on_will_disconnect_msg.rs @@ -15,13 +15,22 @@ use std::{sync::Arc, time::Duration}; +use rstest::rstest; + use chainstate::{ChainstateConfig, Locator}; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ message::{HeaderList, HeaderListRequest, WillDisconnectMessage}, @@ -35,11 +44,13 @@ use crate::{ const TEST_PROTOCOL_VERSION: SupportedProtocolVersion = SupportedProtocolVersion::V3; // Check that the node will also initiate disconnection when it receives the WillDisconnect message. -async fn disconnect_on_will_disconnect_msg() +async fn disconnect_on_will_disconnect_msg(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -54,6 +65,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -112,20 +124,35 @@ where test_node.join().await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn disconnect_on_will_disconnect_msg_tcp() { - run_with_timeout(disconnect_on_will_disconnect_msg::()).await; +async fn disconnect_on_will_disconnect_msg_tcp(#[case] seed: Seed) { + run_with_timeout(disconnect_on_will_disconnect_msg::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn disconnect_on_will_disconnect_msg_channels() { - run_with_timeout(disconnect_on_will_disconnect_msg::()).await; +async fn disconnect_on_will_disconnect_msg_channels(#[case] seed: Seed) { + run_with_timeout(disconnect_on_will_disconnect_msg::( + seed, + )) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn disconnect_on_will_disconnect_msg_noise() { - run_with_timeout(disconnect_on_will_disconnect_msg::()).await; +async fn disconnect_on_will_disconnect_msg_noise(#[case] seed: Seed) { + run_with_timeout(disconnect_on_will_disconnect_msg::( + seed, + )) + .await; } diff --git a/p2p/src/tests/helpers/mod.rs b/p2p/src/tests/helpers/mod.rs index 6903e9b7c8..b08cf56af6 100644 --- a/p2p/src/tests/helpers/mod.rs +++ b/p2p/src/tests/helpers/mod.rs @@ -21,6 +21,7 @@ use std::{ }; use async_trait::async_trait; +use randomness::RngCore; use tokio::sync::mpsc::UnboundedSender; use logging::log; @@ -157,7 +158,7 @@ impl TestDnsSeed { #[async_trait] impl DnsSeed for TestDnsSeed { - async fn obtain_addresses(&self) -> Vec { + async fn obtain_addresses(&self, _rng: &mut (dyn RngCore + Send)) -> Vec { self.addresses.lock().unwrap().clone() } } diff --git a/p2p/src/tests/helpers/test_node.rs b/p2p/src/tests/helpers/test_node.rs index 2312a57c17..162dd75c6f 100644 --- a/p2p/src/tests/helpers/test_node.rs +++ b/p2p/src/tests/helpers/test_node.rs @@ -37,6 +37,7 @@ use mempool::MempoolConfig; use networking::transport::{TransportListener, TransportSocket}; use p2p_test_utils::SHORT_TIMEOUT; use p2p_types::{p2p_event::P2pEventHandler, socket_address::SocketAddress}; +use randomness::RngCore; use storage_inmemory::InMemory; use subsystem::ShutdownTrigger; use utils::{atomics::SeqCstAtomicBool, tokio_spawn_in_tracing_span}; @@ -113,6 +114,7 @@ where bind_address: SocketAddress, protocol_version: ProtocolVersion, node_name: Option<&str>, + rng: impl RngCore + Send + 'static, ) -> Self { let socket = transport.bind(vec![bind_address.socket_addr()]).await.unwrap(); let local_address = socket.local_addresses().unwrap()[0]; @@ -190,6 +192,7 @@ where peerdb_inmemory_store(), Some(peer_mgr_observer), Box::new(TestDnsSeed::new(dns_seed_addresses.clone())), + rng, ) .unwrap(); let peer_mgr_join_handle = tokio_spawn_in_tracing_span( diff --git a/p2p/src/tests/incorrect_handshake.rs b/p2p/src/tests/incorrect_handshake.rs index 40fe1bb8c3..72ea9c9029 100644 --- a/p2p/src/tests/incorrect_handshake.rs +++ b/p2p/src/tests/incorrect_handshake.rs @@ -15,13 +15,22 @@ use std::sync::Arc; +use rstest::rstest; + use chainstate::ChainstateConfig; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportListener, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportListener, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ message::HeaderList, @@ -31,11 +40,13 @@ use crate::{ tests::helpers::TestNode, }; -async fn incorrect_handshake_outgoing_manual() +async fn incorrect_handshake_outgoing_manual(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -50,6 +61,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -96,29 +108,49 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_manual_tcp() { - run_with_timeout(incorrect_handshake_outgoing_manual::()).await; +async fn incorrect_handshake_outgoing_manual_tcp(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_manual::( + seed, + )) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_manual_channels() { - run_with_timeout(incorrect_handshake_outgoing_manual::()).await; +async fn incorrect_handshake_outgoing_manual_channels(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_manual::( + seed, + )) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_manual_noise() { - run_with_timeout(incorrect_handshake_outgoing_manual::()).await; +async fn incorrect_handshake_outgoing_manual_noise(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_manual::( + seed, + )) + .await; } -async fn incorrect_handshake_outgoing_auto() +async fn incorrect_handshake_outgoing_auto(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -133,6 +165,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -178,29 +211,46 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_auto_tcp() { - run_with_timeout(incorrect_handshake_outgoing_auto::()).await; +async fn incorrect_handshake_outgoing_auto_tcp(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_auto::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_auto_channels() { - run_with_timeout(incorrect_handshake_outgoing_auto::()).await; +async fn incorrect_handshake_outgoing_auto_channels(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_auto::( + seed, + )) + .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_outgoing_auto_noise() { - run_with_timeout(incorrect_handshake_outgoing_auto::()).await; +async fn incorrect_handshake_outgoing_auto_noise(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_outgoing_auto::( + seed, + )) + .await; } -async fn incorrect_handshake_incoming() +async fn incorrect_handshake_incoming(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -215,6 +265,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -247,20 +298,29 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_incoming_tcp() { - run_with_timeout(incorrect_handshake_incoming::()).await; +async fn incorrect_handshake_incoming_tcp(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_incoming_channels() { - run_with_timeout(incorrect_handshake_incoming::()).await; +async fn incorrect_handshake_incoming_channels(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn incorrect_handshake_incoming_noise() { - run_with_timeout(incorrect_handshake_incoming::()).await; +async fn incorrect_handshake_incoming_noise(#[case] seed: Seed) { + run_with_timeout(incorrect_handshake_incoming::(seed)).await; } diff --git a/p2p/src/tests/min_peer_software_version.rs b/p2p/src/tests/min_peer_software_version.rs index 7e62edea1a..4f9d119761 100644 --- a/p2p/src/tests/min_peer_software_version.rs +++ b/p2p/src/tests/min_peer_software_version.rs @@ -29,7 +29,12 @@ use networking::{ }; use p2p_test_utils::run_with_timeout; use p2p_types::socket_address::SocketAddress; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ config::P2pConfig, @@ -146,11 +151,15 @@ fn make_p2p_config(test_params: &TestParams) -> P2pConfig { } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] #[rstest_reuse::apply(test_params_list)] #[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn outbound_manual_connection(test_params: TestParams) { +async fn outbound_manual_connection(#[case] seed: Seed, test_params: TestParams) { + let mut rng = make_seedable_rng(seed); + run_with_timeout(async { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -166,6 +175,7 @@ async fn outbound_manual_connection(test_params: TestParams) { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -255,11 +265,15 @@ async fn outbound_manual_connection(test_params: TestParams) { .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] #[rstest_reuse::apply(test_params_list)] #[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn outbound_auto_connection(test_params: TestParams) { +async fn outbound_auto_connection(#[case] seed: Seed, test_params: TestParams) { + let mut rng = make_seedable_rng(seed); + run_with_timeout(async { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -275,6 +289,7 @@ async fn outbound_auto_connection(test_params: TestParams) { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -369,11 +384,15 @@ async fn outbound_auto_connection(test_params: TestParams) { .await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] #[rstest_reuse::apply(test_params_list)] #[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn inbound_connection(test_params: TestParams) { +async fn inbound_connection(#[case] seed: Seed, test_params: TestParams) { + let mut rng = make_seedable_rng(seed); + run_with_timeout(async { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -389,6 +408,7 @@ async fn inbound_connection(test_params: TestParams) { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; diff --git a/p2p/src/tests/misbehavior.rs b/p2p/src/tests/misbehavior.rs index 83a063337f..395c79ace4 100644 --- a/p2p/src/tests/misbehavior.rs +++ b/p2p/src/tests/misbehavior.rs @@ -15,13 +15,22 @@ use std::sync::Arc; +use rstest::rstest; + use chainstate::{ban_score::BanScore, ChainstateConfig}; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ error::{P2pError, ProtocolError}, @@ -31,11 +40,13 @@ use crate::{ tests::helpers::TestNode, }; -async fn unexpected_handshake_message() +async fn unexpected_handshake_message(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -50,6 +61,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -110,20 +122,29 @@ where assert_eq!(peer_score, expected_score); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unexpected_handshake_message_tcp() { - run_with_timeout(unexpected_handshake_message::()).await; +async fn unexpected_handshake_message_tcp(#[case] seed: Seed) { + run_with_timeout(unexpected_handshake_message::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unexpected_handshake_message_channels() { - run_with_timeout(unexpected_handshake_message::()).await; +async fn unexpected_handshake_message_channels(#[case] seed: Seed) { + run_with_timeout(unexpected_handshake_message::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unexpected_handshake_message_noise() { - run_with_timeout(unexpected_handshake_message::()).await; +async fn unexpected_handshake_message_noise(#[case] seed: Seed) { + run_with_timeout(unexpected_handshake_message::(seed)).await; } diff --git a/p2p/src/tests/peer_discovery_on_stale_tip.rs b/p2p/src/tests/peer_discovery_on_stale_tip.rs index ffc5999643..f965b6148f 100644 --- a/p2p/src/tests/peer_discovery_on_stale_tip.rs +++ b/p2p/src/tests/peer_discovery_on_stale_tip.rs @@ -24,7 +24,11 @@ use logging::log; use networking::test_helpers::{TestTransportChannel, TestTransportMaker}; use p2p_test_utils::{run_with_timeout, SHORT_TIMEOUT}; use p2p_types::socket_address::SocketAddress; -use test_utils::{random::Seed, BasicTestTimeGetter}; +use randomness::{Rng as _, RngCore}; +use test_utils::{ + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ config::P2pConfig, @@ -80,7 +84,7 @@ async fn peer_discovery_on_stale_tip_impl( start_in_ibd: bool, use_extra_block_relay_peers: bool, ) { - let mut rng = test_utils::random::make_seedable_rng(seed); + let mut rng = make_seedable_rng(seed); let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); // The heavy checks don't make much sense for this test and it's relatively lengthy, @@ -154,6 +158,7 @@ async fn peer_discovery_on_stale_tip_impl( i + 1, initial_block.clone(), &format!("node{i}"), + make_seedable_rng(rng.gen()), ) .await, ); @@ -217,6 +222,7 @@ async fn peer_discovery_on_stale_tip_impl( new_node_idx, initial_block.clone(), "new_node", + make_seedable_rng(rng.gen()), ) .await; let new_node_addr = *new_node.local_address(); @@ -279,7 +285,8 @@ async fn new_full_relay_connections_on_stale_tip(#[case] seed: Seed) { } async fn new_full_relay_connections_on_stale_tip_impl(seed: Seed) { - let mut rng = test_utils::random::make_seedable_rng(seed); + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let start_time = time_getter.get_time_getter().get_time(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -363,6 +370,7 @@ async fn new_full_relay_connections_on_stale_tip_impl(seed: Seed) { 0, Some(initial_block.clone()), "main", + make_seedable_rng(rng.gen()), ) .await; let main_node_address = *main_node.local_address(); @@ -378,6 +386,7 @@ async fn new_full_relay_connections_on_stale_tip_impl(seed: Seed) { i + 1, Some(initial_block.clone()), &format!("extra{i}"), + make_seedable_rng(rng.gen()), ) .await, ); @@ -510,6 +519,7 @@ pub fn make_p2p_config(peer_manager_config: PeerManagerConfig) -> P2pConfig { } } +#[allow(clippy::too_many_arguments)] async fn start_node( time_getter: &BasicTestTimeGetter, chain_config: &Arc, @@ -518,6 +528,7 @@ async fn start_node( node_index: usize, initial_block: Option, name: &str, + rng: impl RngCore + Send + 'static, ) -> TestNode { let node = TestNode::::start( true, @@ -529,6 +540,7 @@ async fn start_node( TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), Some(name), + rng, ) .await; diff --git a/p2p/src/tests/same_handshake_nonce.rs b/p2p/src/tests/same_handshake_nonce.rs index 8762732f5c..e0a36a9965 100644 --- a/p2p/src/tests/same_handshake_nonce.rs +++ b/p2p/src/tests/same_handshake_nonce.rs @@ -15,13 +15,22 @@ use std::sync::Arc; +use rstest::rstest; + use chainstate::ChainstateConfig; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportListener, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportListener, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ disconnection_reason::DisconnectionReason, @@ -34,11 +43,13 @@ use crate::{ // Simulate a self-connection by sending the same nonce in Hello. // Check that the WillDisconnect message is sent if the protocol version is big enough. -async fn same_handshake_nonce() +async fn same_handshake_nonce(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + for protocol_version in [SupportedProtocolVersion::V2, SupportedProtocolVersion::V3] { let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); @@ -54,6 +65,7 @@ where TTM::make_address().into(), protocol_version.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -129,20 +141,29 @@ where } } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn same_handshake_nonce_tcp() { - run_with_timeout(same_handshake_nonce::()).await; +async fn same_handshake_nonce_tcp(#[case] seed: Seed) { + run_with_timeout(same_handshake_nonce::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn same_handshake_nonce_channels() { - run_with_timeout(same_handshake_nonce::()).await; +async fn same_handshake_nonce_channels(#[case] seed: Seed) { + run_with_timeout(same_handshake_nonce::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn same_handshake_nonce_noise() { - run_with_timeout(same_handshake_nonce::()).await; +async fn same_handshake_nonce_noise(#[case] seed: Seed) { + run_with_timeout(same_handshake_nonce::(seed)).await; } diff --git a/p2p/src/tests/unsupported_message.rs b/p2p/src/tests/unsupported_message.rs index d8623e1072..f735aa9560 100644 --- a/p2p/src/tests/unsupported_message.rs +++ b/p2p/src/tests/unsupported_message.rs @@ -22,10 +22,11 @@ use networking::{ transport::{BufferedTranscoder, TransportSocket as _}, }; use p2p_test_utils::run_with_timeout; +use randomness::Rng as _; use serialization::{Decode, Encode}; use test_utils::{ assert_matches, assert_matches_return_val, - random::{gen_random_bytes, Seed}, + random::{gen_random_bytes, make_seedable_rng, Seed}, BasicTestTimeGetter, }; @@ -59,7 +60,7 @@ async fn unsupported_message(#[case] seed: Seed, #[values(false, true)] make_msg async fn unsupported_message_impl(seed: Seed, make_msg_too_big: bool) { type Transport = ::Transport; - let mut rng = test_utils::random::make_seedable_rng(seed); + let mut rng = make_seedable_rng(seed); let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let max_message_size = 1024; @@ -84,6 +85,7 @@ async fn unsupported_message_impl(seed: Seed, make_msg_too_big: bool) { TestTransportChannel::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; diff --git a/p2p/src/tests/unsupported_version.rs b/p2p/src/tests/unsupported_version.rs index f848d3f358..c585d4b6f2 100644 --- a/p2p/src/tests/unsupported_version.rs +++ b/p2p/src/tests/unsupported_version.rs @@ -15,13 +15,22 @@ use std::sync::Arc; +use rstest::rstest; + use chainstate::ChainstateConfig; -use networking::test_helpers::{ - TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, +use networking::{ + test_helpers::{ + TestTransportChannel, TestTransportMaker, TestTransportNoise, TestTransportTcp, + }, + transport::{BufferedTranscoder, TransportListener, TransportSocket}, }; -use networking::transport::{BufferedTranscoder, TransportListener, TransportSocket}; use p2p_test_utils::run_with_timeout; -use test_utils::{assert_matches, BasicTestTimeGetter}; +use randomness::Rng as _; +use test_utils::{ + assert_matches, + random::{make_seedable_rng, Seed}, + BasicTestTimeGetter, +}; use crate::{ net::default_backend::types::{HandshakeMessage, Message, P2pTimestamp}, @@ -30,11 +39,13 @@ use crate::{ tests::helpers::TestNode, }; -async fn unsupported_version_outgoing() +async fn unsupported_version_outgoing(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -49,6 +60,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -100,29 +112,40 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_outgoing_tcp() { - run_with_timeout(unsupported_version_outgoing::()).await; +async fn unsupported_version_outgoing_tcp(#[case] seed: Seed) { + run_with_timeout(unsupported_version_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_outgoing_channels() { - run_with_timeout(unsupported_version_outgoing::()).await; +async fn unsupported_version_outgoing_channels(#[case] seed: Seed) { + run_with_timeout(unsupported_version_outgoing::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_outgoing_noise() { - run_with_timeout(unsupported_version_outgoing::()).await; +async fn unsupported_version_outgoing_noise(#[case] seed: Seed) { + run_with_timeout(unsupported_version_outgoing::(seed)).await; } -async fn unsupported_version_incoming() +async fn unsupported_version_incoming(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -137,6 +160,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -177,31 +201,42 @@ where ); } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_incoming_tcp() { - run_with_timeout(unsupported_version_incoming::()).await; +async fn unsupported_version_incoming_tcp(#[case] seed: Seed) { + run_with_timeout(unsupported_version_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_incoming_channels() { - run_with_timeout(unsupported_version_incoming::()).await; +async fn unsupported_version_incoming_channels(#[case] seed: Seed) { + run_with_timeout(unsupported_version_incoming::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_incoming_noise() { - run_with_timeout(unsupported_version_incoming::()).await; +async fn unsupported_version_incoming_noise(#[case] seed: Seed) { + run_with_timeout(unsupported_version_incoming::(seed)).await; } // Here we have a peer with an unsupported version and a normal peer connected at the same time. // The unsupported peer should be disconnected, while the normal one should remain connected. -async fn unsupported_version_two_peers() +async fn unsupported_version_two_peers(seed: Seed) where TTM: TestTransportMaker, TTM::Transport: TransportSocket, { + let mut rng = make_seedable_rng(seed); + let time_getter = BasicTestTimeGetter::new(); let chain_config = Arc::new(common::chain::config::create_unit_test_config()); let p2p_config = Arc::new(test_p2p_config()); @@ -216,6 +251,7 @@ where TTM::make_address().into(), TEST_PROTOCOL_VERSION.into(), None, + make_seedable_rng(rng.gen()), ) .await; @@ -285,20 +321,29 @@ where test_node.join().await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_two_peers_tcp() { - run_with_timeout(unsupported_version_two_peers::()).await; +async fn unsupported_version_two_peers_tcp(#[case] seed: Seed) { + run_with_timeout(unsupported_version_two_peers::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_two_peers_channels() { - run_with_timeout(unsupported_version_two_peers::()).await; +async fn unsupported_version_two_peers_channels(#[case] seed: Seed) { + run_with_timeout(unsupported_version_two_peers::(seed)).await; } -#[tracing::instrument] +#[tracing::instrument(skip(seed))] +#[rstest] +#[trace] +#[case(Seed::from_entropy())] #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn unsupported_version_two_peers_noise() { - run_with_timeout(unsupported_version_two_peers::()).await; +async fn unsupported_version_two_peers_noise(#[case] seed: Seed) { + run_with_timeout(unsupported_version_two_peers::(seed)).await; } diff --git a/randomness/Cargo.toml b/randomness/Cargo.toml index 1d5cffb7a2..14fbaa6e38 100644 --- a/randomness/Cargo.toml +++ b/randomness/Cargo.toml @@ -9,3 +9,6 @@ license.workspace = true [dependencies] rand.workspace = true + +[dev-dependencies] +static_assertions.workspace = true diff --git a/randomness/src/lib.rs b/randomness/src/lib.rs index c84df3c7b1..4bf415059b 100644 --- a/randomness/src/lib.rs +++ b/randomness/src/lib.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Mutex; + pub use rand::prelude::SliceRandom; pub use rand::{seq, CryptoRng, Rng, RngCore, SeedableRng}; @@ -39,3 +41,73 @@ pub fn make_true_rng() -> impl Rng + CryptoRng { pub fn make_pseudo_rng() -> impl Rng { rand::rngs::ThreadRng::default() } + +/// A wrapper over `Mutex>` that implements `RngCore` and `CryptoRng` if `R` does the same. +/// +/// This can be passed to a function that accept `impl Rng`, to avoid the need to lock the mutex +/// for the entire duration of the function call. +/// In particular, this is useful in async code, because passing a `MutexGuard` across an `await` +/// point produces a non-Send future. +pub struct BoxedRngMutexWrapper<'a, R: ?Sized>(&'a Mutex>); + +impl<'a, R: ?Sized> BoxedRngMutexWrapper<'a, R> { + pub fn new(rng: &'a Mutex>) -> Self { + Self(rng) + } +} + +impl<'a, R: RngCore + ?Sized> RngCore for BoxedRngMutexWrapper<'a, R> { + fn next_u32(&mut self) -> u32 { + self.0.lock().expect("poisoned mutex").next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.0.lock().expect("poisoned mutex").next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.lock().expect("poisoned mutex").fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + self.0.lock().expect("poisoned mutex").try_fill_bytes(dest) + } +} + +impl<'a, R: CryptoRng> CryptoRng for BoxedRngMutexWrapper<'a, R> {} + +#[cfg(test)] +mod tests { + use static_assertions::{assert_impl_all, assert_not_impl_any}; + + use super::*; + + // `DumbRng` implements `RngCore` but not `CryptoRng`. + #[allow(dead_code)] + struct DumbRng; + + impl RngCore for DumbRng { + fn next_u32(&mut self) -> u32 { + 0 + } + + fn next_u64(&mut self) -> u64 { + 0 + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + dest.fill(0); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + dest.fill(0); + Ok(()) + } + } + + assert_impl_all!(BoxedRngMutexWrapper<'static, DumbRng>: RngCore); + assert_not_impl_any!(BoxedRngMutexWrapper<'static, DumbRng>: CryptoRng); + + // Note: `ThreadRng` actually implements `CryptoRng`, even though we use it in `make_pseudo_rng`. + assert_impl_all!(BoxedRngMutexWrapper<'static, rand::rngs::ThreadRng>: RngCore, CryptoRng); +}