From 60d7578e691c92b1f839cee53aa22d9214d66fe4 Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Wed, 31 Mar 2021 16:11:49 +0200 Subject: [PATCH 1/5] gossip: do not issue a connection request if we are not a validator --- Cargo.lock | 2 ++ node/network/gossip-support/Cargo.toml | 3 +++ node/network/gossip-support/src/lib.rs | 33 ++++++++++++++++++++++---- node/service/src/lib.rs | 4 +++- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3954423333dc..ab4abc9462fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5497,6 +5497,8 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", + "sp-application-crypto", + "sp-keystore", "tracing", ] diff --git a/node/network/gossip-support/Cargo.toml b/node/network/gossip-support/Cargo.toml index 56d239f121c2..0de20c53781d 100644 --- a/node/network/gossip-support/Cargo.toml +++ b/node/network/gossip-support/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } + polkadot-node-network-protocol = { path = "../protocol" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index 2e3e7e9bc30b..0c3c07bdd972 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -34,11 +34,15 @@ use polkadot_primitives::v1::{ Hash, ValidatorId, SessionIndex, }; use polkadot_node_network_protocol::peer_set::PeerSet; +use sp_keystore::{CryptoStore, SyncCryptoStorePtr}; +use sp_application_crypto::{Public, AppKey}; const LOG_TARGET: &str = "parachain::gossip-support"; /// The Gossip Support subsystem. -pub struct GossipSupport {} +pub struct GossipSupport { + keystore: SyncCryptoStorePtr, +} #[derive(Default)] struct State { @@ -49,8 +53,10 @@ struct State { impl GossipSupport { /// Create a new instance of the [`GossipSupport`] subsystem. - pub fn new() -> Self { - Self {} + pub fn new(keystore: SyncCryptoStorePtr) -> Self { + Self { + keystore + } } #[tracing::instrument(skip(self, ctx), fields(subsystem = LOG_TARGET))] @@ -59,6 +65,7 @@ impl GossipSupport { Context: SubsystemContext, { let mut state = State::default(); + let Self { keystore } = self; loop { let message = match ctx.recv().await { Ok(message) => message, @@ -80,7 +87,7 @@ impl GossipSupport { tracing::trace!(target: LOG_TARGET, "active leaves signal"); let leaves = activated.into_iter().map(|a| a.hash); - if let Err(e) = state.handle_active_leaves(&mut ctx, leaves).await { + if let Err(e) = state.handle_active_leaves(&mut ctx, &keystore, leaves).await { tracing::debug!(target: LOG_TARGET, error = ?e); } } @@ -102,6 +109,22 @@ async fn determine_relevant_validators( Ok(validators) } +/// Return an error if we're not a validator in the given set (do not have keys). +async fn ensure_i_am_a_validator( + keystore: &SyncCryptoStorePtr, + validators: &[ValidatorId], +) -> Result<(), util::Error> { + for v in validators.iter() { + if CryptoStore::has_keys(&**keystore, &[(v.to_raw_vec(), ValidatorId::ID)]) + .await + { + return Ok(()); + } + } + Err(util::Error::NotAValidator) +} + + impl State { /// 1. Determine if the current session index has changed. /// 2. If it has, determine relevant validators @@ -109,6 +132,7 @@ impl State { async fn handle_active_leaves( &mut self, ctx: &mut impl SubsystemContext, + keystore: &SyncCryptoStorePtr, leaves: impl Iterator, ) -> Result<(), util::Error> { for leaf in leaves { @@ -121,6 +145,7 @@ impl State { if let Some((new_session, relay_parent)) = maybe_new_session { tracing::debug!(target: LOG_TARGET, %new_session, "New session detected"); let validators = determine_relevant_validators(ctx, relay_parent, new_session).await?; + ensure_i_am_a_validator(keystore, &validators).await?; tracing::debug!(target: LOG_TARGET, num = ?validators.len(), "Issuing a connection request"); let request = validator_discovery::connect_to_validators_in_session( diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index b0be6abd8acc..1e13a322bcd0 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -538,7 +538,9 @@ where keystore.clone(), Metrics::register(registry)?, )?, - gossip_support: GossipSupportSubsystem::new(), + gossip_support: GossipSupportSubsystem::new( + keystore.clone(), + ), }; Overseer::new( From 2c21070be5d868adf4720a7ee87497a90caaa049 Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Wed, 31 Mar 2021 16:37:51 +0200 Subject: [PATCH 2/5] guide updates --- node/network/gossip-support/src/lib.rs | 3 ++- roadmap/implementers-guide/src/SUMMARY.md | 1 + .../src/node/utility/gossip-support.md | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 roadmap/implementers-guide/src/node/utility/gossip-support.md diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index 0c3c07bdd972..bf73052c5ffd 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -16,7 +16,8 @@ //! This subsystem is responsible for keeping track of session changes //! and issuing a connection request to the validators relevant to -//! the gossiping subsystems on every new session. +//! the gossiping subsystems on every new session. But only if we +//! are a validator in the current session. use futures::FutureExt as _; use polkadot_node_subsystem::{ diff --git a/roadmap/implementers-guide/src/SUMMARY.md b/roadmap/implementers-guide/src/SUMMARY.md index 3e6a824d9098..06e525192b40 100644 --- a/roadmap/implementers-guide/src/SUMMARY.md +++ b/roadmap/implementers-guide/src/SUMMARY.md @@ -57,6 +57,7 @@ - [Candidate Validation](node/utility/candidate-validation.md) - [Provisioner](node/utility/provisioner.md) - [Network Bridge](node/utility/network-bridge.md) + - [Gossip Support](node/utility/gossip-support.md) - [Misbehavior Arbitration](node/utility/misbehavior-arbitration.md) - [Peer Set Manager](node/utility/peer-set-manager.md) - [Runtime API Requests](node/utility/runtime-api.md) diff --git a/roadmap/implementers-guide/src/node/utility/gossip-support.md b/roadmap/implementers-guide/src/node/utility/gossip-support.md new file mode 100644 index 000000000000..c13f616fa6e2 --- /dev/null +++ b/roadmap/implementers-guide/src/node/utility/gossip-support.md @@ -0,0 +1,10 @@ +# Gossip Support + +The Gossip Support Subsystem is responsible for keeping track of session changes +and issuing a connection request to all validators in the current session if we are a validator. +The request will add all validators to the reserved PeerSet, meaning any validator in that set can +send us a message. + +Gossiping subsystems will be notified when a new peer connects or disconnects by network bridge. +It is their responsibility to limit the amount of outgoing gossip messages. +At the moment we use enforce a cap of `max(sqrt(peer.len()), 25)` message recipients at a time in each gossiping subsystem. From c139fbe38c60e1f75cc517a870e4b1d2c1c411ce Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Wed, 31 Mar 2021 22:02:07 +0200 Subject: [PATCH 3/5] use all relevant authorities when issuing a request --- node/core/runtime-api/src/cache.rs | 23 +++++++++++ node/core/runtime-api/src/lib.rs | 36 +++++++++++++++- node/network/gossip-support/src/lib.rs | 41 +++++++++---------- node/network/protocol/src/peer_set.rs | 9 ++-- node/subsystem-util/src/lib.rs | 3 ++ .../subsystem-util/src/validator_discovery.rs | 3 +- node/subsystem/src/messages.rs | 2 + primitives/src/v1.rs | 4 ++ .../src/node/utility/gossip-support.md | 9 ++-- runtime/kusama/src/lib.rs | 4 ++ runtime/polkadot/src/lib.rs | 4 ++ runtime/rococo/src/lib.rs | 4 ++ runtime/test-runtime/src/lib.rs | 4 ++ runtime/westend/src/lib.rs | 4 ++ 14 files changed, 119 insertions(+), 31 deletions(-) diff --git a/node/core/runtime-api/src/cache.rs b/node/core/runtime-api/src/cache.rs index 1dce87e68c22..1bc6f682ff67 100644 --- a/node/core/runtime-api/src/cache.rs +++ b/node/core/runtime-api/src/cache.rs @@ -19,6 +19,7 @@ use polkadot_primitives::v1::{ CoreState, GroupRotationInfo, InboundDownwardMessage, InboundHrmpMessage, Hash, PersistedValidationData, Id as ParaId, OccupiedCoreAssumption, SessionIndex, SessionInfo, ValidationCode, ValidatorId, ValidatorIndex, + AuthorityDiscoveryId, }; use sp_consensus_babe::Epoch; use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; @@ -28,6 +29,7 @@ use memory_lru::{MemoryLruCache, ResidentSize}; use std::collections::btree_map::BTreeMap; +const AUTHORITIES_CACHE_SIZE: usize = 128 * 1024; const VALIDATORS_CACHE_SIZE: usize = 64 * 1024; const VALIDATOR_GROUPS_CACHE_SIZE: usize = 64 * 1024; const AVAILABILITY_CORES_CACHE_SIZE: usize = 64 * 1024; @@ -59,7 +61,18 @@ impl ResidentSize for DoesNotAllocate { } } +// this is an ugly workaround for `AuthorityDiscoveryId` +// not implementing `MallocSizeOf` +struct VecOfDoesNotAllocate(Vec); + +impl ResidentSize for VecOfDoesNotAllocate { + fn resident_size(&self) -> usize { + std::mem::size_of::() * self.0.capacity() + } +} + pub(crate) struct RequestResultCache { + authorities: MemoryLruCache>, validators: MemoryLruCache>>, validator_groups: MemoryLruCache>, GroupRotationInfo)>>, availability_cores: MemoryLruCache>>, @@ -79,6 +92,7 @@ pub(crate) struct RequestResultCache { impl Default for RequestResultCache { fn default() -> Self { Self { + authorities: MemoryLruCache::new(AUTHORITIES_CACHE_SIZE), validators: MemoryLruCache::new(VALIDATORS_CACHE_SIZE), validator_groups: MemoryLruCache::new(VALIDATOR_GROUPS_CACHE_SIZE), availability_cores: MemoryLruCache::new(AVAILABILITY_CORES_CACHE_SIZE), @@ -98,6 +112,14 @@ impl Default for RequestResultCache { } impl RequestResultCache { + pub(crate) fn authorities(&mut self, relay_parent: &Hash) -> Option<&Vec> { + self.authorities.get(relay_parent).map(|v| &v.0) + } + + pub(crate) fn cache_authorities(&mut self, relay_parent: Hash, authorities: Vec) { + self.authorities.insert(relay_parent, VecOfDoesNotAllocate(authorities)); + } + pub(crate) fn validators(&mut self, relay_parent: &Hash) -> Option<&Vec> { self.validators.get(relay_parent).map(|v| &v.0) } @@ -212,6 +234,7 @@ impl RequestResultCache { } pub(crate) enum RequestResult { + Authorities(Hash, Vec), Validators(Hash, Vec), ValidatorGroups(Hash, (Vec>, GroupRotationInfo)), AvailabilityCores(Hash, Vec), diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index d7dfa8b162f4..8b701aae0271 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -102,6 +102,8 @@ impl RuntimeApiSubsystem where use RequestResult::*; match result { + Authorities(relay_parent, authorities) => + self.requests_cache.cache_authorities(relay_parent, authorities), Validators(relay_parent, validators) => self.requests_cache.cache_validators(relay_parent, validators), ValidatorGroups(relay_parent, groups) => @@ -160,6 +162,8 @@ impl RuntimeApiSubsystem where } match request { + Request::Authorities(sender) => query!(authorities(), sender) + .map(|sender| Request::Authorities(sender)), Request::Validators(sender) => query!(validators(), sender) .map(|sender| Request::Validators(sender)), Request::ValidatorGroups(sender) => query!(validator_groups(), sender) @@ -327,6 +331,7 @@ where } match request { + Request::Authorities(sender) => query!(Authorities, authorities(), sender), Request::Validators(sender) => query!(Validators, validators(), sender), Request::ValidatorGroups(sender) => query!(ValidatorGroups, validator_groups(), sender), Request::AvailabilityCores(sender) => query!(AvailabilityCores, availability_cores(), sender), @@ -416,7 +421,7 @@ mod tests { ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, PersistedValidationData, Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode, CommittedCandidateReceipt, CandidateEvent, InboundDownwardMessage, - BlockNumber, InboundHrmpMessage, SessionInfo, + BlockNumber, InboundHrmpMessage, SessionInfo, AuthorityDiscoveryId, }; use polkadot_node_subsystem_test_helpers as test_helpers; use sp_core::testing::TaskExecutor; @@ -428,6 +433,7 @@ mod tests { #[derive(Default, Clone)] struct MockRuntimeApi { + authorities: Vec, validators: Vec, validator_groups: Vec>, availability_cores: Vec, @@ -455,6 +461,10 @@ mod tests { sp_api::mock_impl_runtime_apis! { impl ParachainHost for MockRuntimeApi { + fn authorities(&self) -> Vec { + self.authorities.clone() + } + fn validators(&self) -> Vec { self.validators.clone() } @@ -584,6 +594,30 @@ mod tests { } } + #[test] + fn requests_authorities() { + let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); + let runtime_api = Arc::new(MockRuntimeApi::default()); + let relay_parent = [1; 32].into(); + let spawner = sp_core::testing::TaskExecutor::new(); + + let subsystem = RuntimeApiSubsystem::new(runtime_api.clone(), Metrics(None), spawner); + let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap()); + let test_task = async move { + let (tx, rx) = oneshot::channel(); + + ctx_handle.send(FromOverseer::Communication { + msg: RuntimeApiMessage::Request(relay_parent, Request::Authorities(tx)) + }).await; + + assert_eq!(rx.await.unwrap().unwrap(), runtime_api.authorities); + + ctx_handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; + + futures::executor::block_on(future::join(subsystem_task, test_task)); + } + #[test] fn requests_validators() { let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index bf73052c5ffd..11bcb9fb87ba 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -19,7 +19,7 @@ //! the gossiping subsystems on every new session. But only if we //! are a validator in the current session. -use futures::FutureExt as _; +use futures::{channel::mpsc, FutureExt as _}; use polkadot_node_subsystem::{ messages::{ GossipSupportMessage, @@ -28,13 +28,13 @@ use polkadot_node_subsystem::{ Subsystem, SpawnedSubsystem, SubsystemContext, }; use polkadot_node_subsystem_util::{ - validator_discovery::{ConnectionRequest, self}, + validator_discovery, self as util, }; use polkadot_primitives::v1::{ - Hash, ValidatorId, SessionIndex, + Hash, SessionIndex, AuthorityDiscoveryId, }; -use polkadot_node_network_protocol::peer_set::PeerSet; +use polkadot_node_network_protocol::{peer_set::PeerSet, PeerId}; use sp_keystore::{CryptoStore, SyncCryptoStorePtr}; use sp_application_crypto::{Public, AppKey}; @@ -49,7 +49,7 @@ pub struct GossipSupport { struct State { last_session_index: Option, /// when we overwrite this, it automatically drops the previous request - _last_connection_request: Option, + _last_connection_request: Option>, } impl GossipSupport { @@ -101,22 +101,21 @@ impl GossipSupport { } } -async fn determine_relevant_validators( +async fn determine_relevant_authorities( ctx: &mut impl SubsystemContext, relay_parent: Hash, - _session: SessionIndex, -) -> Result, util::Error> { - let validators = util::request_validators_ctx(relay_parent, ctx).await?.await??; - Ok(validators) +) -> Result, util::Error> { + let authorities = util::request_authorities_ctx(relay_parent, ctx).await?.await??; + Ok(authorities) } /// Return an error if we're not a validator in the given set (do not have keys). -async fn ensure_i_am_a_validator( +async fn ensure_i_am_an_authority( keystore: &SyncCryptoStorePtr, - validators: &[ValidatorId], + authorities: &[AuthorityDiscoveryId], ) -> Result<(), util::Error> { - for v in validators.iter() { - if CryptoStore::has_keys(&**keystore, &[(v.to_raw_vec(), ValidatorId::ID)]) + for v in authorities { + if CryptoStore::has_keys(&**keystore, &[(v.to_raw_vec(), AuthorityDiscoveryId::ID)]) .await { return Ok(()); @@ -145,17 +144,15 @@ impl State { if let Some((new_session, relay_parent)) = maybe_new_session { tracing::debug!(target: LOG_TARGET, %new_session, "New session detected"); - let validators = determine_relevant_validators(ctx, relay_parent, new_session).await?; - ensure_i_am_a_validator(keystore, &validators).await?; - tracing::debug!(target: LOG_TARGET, num = ?validators.len(), "Issuing a connection request"); + let authorities = determine_relevant_authorities(ctx, relay_parent).await?; + ensure_i_am_an_authority(keystore, &authorities).await?; + tracing::debug!(target: LOG_TARGET, num = ?authorities.len(), "Issuing a connection request"); - let request = validator_discovery::connect_to_validators_in_session( + let request = validator_discovery::connect_to_authorities( ctx, - relay_parent, - validators, + authorities, PeerSet::Validation, - new_session, - ).await?; + ).await; self.last_session_index = Some(new_session); self._last_connection_request = Some(request); diff --git a/node/network/protocol/src/peer_set.rs b/node/network/protocol/src/peer_set.rs index ee85da54a5cc..9a7561f98beb 100644 --- a/node/network/protocol/src/peer_set.rs +++ b/node/network/protocol/src/peer_set.rs @@ -57,9 +57,12 @@ impl PeerSet { notifications_protocol: protocol, max_notification_size, set_config: sc_network::config::SetConfig { - // we want our gossip subset to always include reserved peers - in_peers: super::MIN_GOSSIP_PEERS as u32 / 2, - out_peers: 0, + // we allow full nodes to connect to validators for gossip + // to ensure any `MIN_GOSSIP_PEERS` always include reserved peers + // we limit the amount of non-reserved slots to be less + // than `MIN_GOSSIP_PEERS` in total + in_peers: super::MIN_GOSSIP_PEERS as u32 / 2 - 1, + out_peers: super::MIN_GOSSIP_PEERS as u32 / 2 - 1, reserved_nodes: Vec::new(), non_reserved_mode: sc_network::config::NonReservedPeerMode::Accept, }, diff --git a/node/subsystem-util/src/lib.rs b/node/subsystem-util/src/lib.rs index 47c4406a95c3..fbcc6588bc36 100644 --- a/node/subsystem-util/src/lib.rs +++ b/node/subsystem-util/src/lib.rs @@ -39,6 +39,7 @@ use polkadot_primitives::v1::{ CandidateEvent, CommittedCandidateReceipt, CoreState, EncodeAs, PersistedValidationData, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, SessionIndex, Signed, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, SessionInfo, + AuthorityDiscoveryId, }; use sp_core::{traits::SpawnNamed, Public}; use sp_application_crypto::AppKey; @@ -166,6 +167,7 @@ macro_rules! specialize_requests { } specialize_requests! { + fn request_authorities() -> Vec; Authorities; fn request_validators() -> Vec; Validators; fn request_validator_groups() -> (Vec>, GroupRotationInfo); ValidatorGroups; fn request_availability_cores() -> Vec; AvailabilityCores; @@ -247,6 +249,7 @@ macro_rules! specialize_requests_ctx { } specialize_requests_ctx! { + fn request_authorities_ctx() -> Vec; Authorities; fn request_validators_ctx() -> Vec; Validators; fn request_validator_groups_ctx() -> (Vec>, GroupRotationInfo); ValidatorGroups; fn request_availability_cores_ctx() -> Vec; AvailabilityCores; diff --git a/node/subsystem-util/src/validator_discovery.rs b/node/subsystem-util/src/validator_discovery.rs index 292daa62f0b7..d851ebd6ebd9 100644 --- a/node/subsystem-util/src/validator_discovery.rs +++ b/node/subsystem-util/src/validator_discovery.rs @@ -115,7 +115,8 @@ pub async fn connect_to_validators_in_session( }) } -async fn connect_to_authorities( +/// A helper function for making a `ConnectToValidators` request. +pub async fn connect_to_authorities( ctx: &mut Context, validator_ids: Vec, peer_set: PeerSet, diff --git a/node/subsystem/src/messages.rs b/node/subsystem/src/messages.rs index 06d41def8083..03ca4314fd16 100644 --- a/node/subsystem/src/messages.rs +++ b/node/subsystem/src/messages.rs @@ -436,6 +436,8 @@ pub type RuntimeApiSender = oneshot::Sender>), /// Get the current validator set. Validators(RuntimeApiSender>), /// Get the validator groups and group rotation info. diff --git a/primitives/src/v1.rs b/primitives/src/v1.rs index 4cb8a09b812c..69cfcf92bd16 100644 --- a/primitives/src/v1.rs +++ b/primitives/src/v1.rs @@ -798,6 +798,10 @@ sp_api::decl_runtime_apis! { // Additionally, some runtime APIs may depend on state that is pruned on the `on_initialize`. // At the moment of writing, this is `candidate_events`. + /// Get the next, current and some previous authority keys deduplicated. + #[skip_initialize_block] + fn authorities() -> Vec; + /// Get the current validators. #[skip_initialize_block] fn validators() -> Vec; diff --git a/roadmap/implementers-guide/src/node/utility/gossip-support.md b/roadmap/implementers-guide/src/node/utility/gossip-support.md index c13f616fa6e2..6eb28c8d9f29 100644 --- a/roadmap/implementers-guide/src/node/utility/gossip-support.md +++ b/roadmap/implementers-guide/src/node/utility/gossip-support.md @@ -1,10 +1,11 @@ # Gossip Support The Gossip Support Subsystem is responsible for keeping track of session changes -and issuing a connection request to all validators in the current session if we are a validator. -The request will add all validators to the reserved PeerSet, meaning any validator in that set can -send us a message. +and issuing a connection request to all validators in the current session and a few past sessions +if we are a validator in these sessions. +The request will add all validators to a reserved PeerSet, meaning we will not reject a connection request +from any validator in that set. Gossiping subsystems will be notified when a new peer connects or disconnects by network bridge. It is their responsibility to limit the amount of outgoing gossip messages. -At the moment we use enforce a cap of `max(sqrt(peer.len()), 25)` message recipients at a time in each gossiping subsystem. +At the moment we enforce a cap of `max(sqrt(peers.len()), 25)` message recipients at a time in each gossiping subsystem. diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 9624c6698392..7c20c90c92a8 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -1157,6 +1157,10 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { + fn authorities() -> Vec { + Vec::new() + } + fn validators() -> Vec { Vec::new() } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 5db5d37f97e5..66f796311ae5 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -1184,6 +1184,10 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { + fn authorities() -> Vec { + Vec::new() + } + fn validators() -> Vec { Vec::new() } diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index e841939c02f9..cf6531ae2a9c 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -809,6 +809,10 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { + fn authorities() -> Vec { + runtime_api_impl::relevant_authority_ids::() + } + fn validators() -> Vec { runtime_api_impl::validators::() } diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index 685c5918c525..9ad0bb169ae6 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -633,6 +633,10 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { + fn authorities() -> Vec { + runtime_impl::relevant_authority_ids::() + } + fn validators() -> Vec { runtime_impl::validators::() } diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 9709366306d5..0ccaf1ab79e7 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -856,6 +856,10 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { + fn authorities() -> Vec { + Vec::new() + } + fn validators() -> Vec { Vec::new() } From 73534e4b6f27447806a9bb436880277267b98e80 Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Thu, 1 Apr 2021 00:11:11 +0200 Subject: [PATCH 4/5] use AuthorityDiscoveryApi instead --- Cargo.lock | 2 + node/core/runtime-api/src/cache.rs | 23 ---------- node/core/runtime-api/src/lib.rs | 36 +--------------- node/network/gossip-support/Cargo.toml | 2 + node/network/gossip-support/src/lib.rs | 58 ++++++++++++++++++-------- node/service/src/lib.rs | 6 ++- node/subsystem-util/src/lib.rs | 3 -- node/subsystem/src/messages.rs | 2 - primitives/src/v1.rs | 4 -- runtime/kusama/src/lib.rs | 4 -- runtime/polkadot/src/lib.rs | 4 -- runtime/rococo/src/lib.rs | 4 -- runtime/test-runtime/src/lib.rs | 4 -- runtime/westend/src/lib.rs | 4 -- 14 files changed, 49 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab4abc9462fa..578607489285 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5497,7 +5497,9 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", + "sp-api", "sp-application-crypto", + "sp-authority-discovery", "sp-keystore", "tracing", ] diff --git a/node/core/runtime-api/src/cache.rs b/node/core/runtime-api/src/cache.rs index 1bc6f682ff67..1dce87e68c22 100644 --- a/node/core/runtime-api/src/cache.rs +++ b/node/core/runtime-api/src/cache.rs @@ -19,7 +19,6 @@ use polkadot_primitives::v1::{ CoreState, GroupRotationInfo, InboundDownwardMessage, InboundHrmpMessage, Hash, PersistedValidationData, Id as ParaId, OccupiedCoreAssumption, SessionIndex, SessionInfo, ValidationCode, ValidatorId, ValidatorIndex, - AuthorityDiscoveryId, }; use sp_consensus_babe::Epoch; use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; @@ -29,7 +28,6 @@ use memory_lru::{MemoryLruCache, ResidentSize}; use std::collections::btree_map::BTreeMap; -const AUTHORITIES_CACHE_SIZE: usize = 128 * 1024; const VALIDATORS_CACHE_SIZE: usize = 64 * 1024; const VALIDATOR_GROUPS_CACHE_SIZE: usize = 64 * 1024; const AVAILABILITY_CORES_CACHE_SIZE: usize = 64 * 1024; @@ -61,18 +59,7 @@ impl ResidentSize for DoesNotAllocate { } } -// this is an ugly workaround for `AuthorityDiscoveryId` -// not implementing `MallocSizeOf` -struct VecOfDoesNotAllocate(Vec); - -impl ResidentSize for VecOfDoesNotAllocate { - fn resident_size(&self) -> usize { - std::mem::size_of::() * self.0.capacity() - } -} - pub(crate) struct RequestResultCache { - authorities: MemoryLruCache>, validators: MemoryLruCache>>, validator_groups: MemoryLruCache>, GroupRotationInfo)>>, availability_cores: MemoryLruCache>>, @@ -92,7 +79,6 @@ pub(crate) struct RequestResultCache { impl Default for RequestResultCache { fn default() -> Self { Self { - authorities: MemoryLruCache::new(AUTHORITIES_CACHE_SIZE), validators: MemoryLruCache::new(VALIDATORS_CACHE_SIZE), validator_groups: MemoryLruCache::new(VALIDATOR_GROUPS_CACHE_SIZE), availability_cores: MemoryLruCache::new(AVAILABILITY_CORES_CACHE_SIZE), @@ -112,14 +98,6 @@ impl Default for RequestResultCache { } impl RequestResultCache { - pub(crate) fn authorities(&mut self, relay_parent: &Hash) -> Option<&Vec> { - self.authorities.get(relay_parent).map(|v| &v.0) - } - - pub(crate) fn cache_authorities(&mut self, relay_parent: Hash, authorities: Vec) { - self.authorities.insert(relay_parent, VecOfDoesNotAllocate(authorities)); - } - pub(crate) fn validators(&mut self, relay_parent: &Hash) -> Option<&Vec> { self.validators.get(relay_parent).map(|v| &v.0) } @@ -234,7 +212,6 @@ impl RequestResultCache { } pub(crate) enum RequestResult { - Authorities(Hash, Vec), Validators(Hash, Vec), ValidatorGroups(Hash, (Vec>, GroupRotationInfo)), AvailabilityCores(Hash, Vec), diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index 8b701aae0271..d7dfa8b162f4 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -102,8 +102,6 @@ impl RuntimeApiSubsystem where use RequestResult::*; match result { - Authorities(relay_parent, authorities) => - self.requests_cache.cache_authorities(relay_parent, authorities), Validators(relay_parent, validators) => self.requests_cache.cache_validators(relay_parent, validators), ValidatorGroups(relay_parent, groups) => @@ -162,8 +160,6 @@ impl RuntimeApiSubsystem where } match request { - Request::Authorities(sender) => query!(authorities(), sender) - .map(|sender| Request::Authorities(sender)), Request::Validators(sender) => query!(validators(), sender) .map(|sender| Request::Validators(sender)), Request::ValidatorGroups(sender) => query!(validator_groups(), sender) @@ -331,7 +327,6 @@ where } match request { - Request::Authorities(sender) => query!(Authorities, authorities(), sender), Request::Validators(sender) => query!(Validators, validators(), sender), Request::ValidatorGroups(sender) => query!(ValidatorGroups, validator_groups(), sender), Request::AvailabilityCores(sender) => query!(AvailabilityCores, availability_cores(), sender), @@ -421,7 +416,7 @@ mod tests { ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, PersistedValidationData, Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode, CommittedCandidateReceipt, CandidateEvent, InboundDownwardMessage, - BlockNumber, InboundHrmpMessage, SessionInfo, AuthorityDiscoveryId, + BlockNumber, InboundHrmpMessage, SessionInfo, }; use polkadot_node_subsystem_test_helpers as test_helpers; use sp_core::testing::TaskExecutor; @@ -433,7 +428,6 @@ mod tests { #[derive(Default, Clone)] struct MockRuntimeApi { - authorities: Vec, validators: Vec, validator_groups: Vec>, availability_cores: Vec, @@ -461,10 +455,6 @@ mod tests { sp_api::mock_impl_runtime_apis! { impl ParachainHost for MockRuntimeApi { - fn authorities(&self) -> Vec { - self.authorities.clone() - } - fn validators(&self) -> Vec { self.validators.clone() } @@ -594,30 +584,6 @@ mod tests { } } - #[test] - fn requests_authorities() { - let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); - let runtime_api = Arc::new(MockRuntimeApi::default()); - let relay_parent = [1; 32].into(); - let spawner = sp_core::testing::TaskExecutor::new(); - - let subsystem = RuntimeApiSubsystem::new(runtime_api.clone(), Metrics(None), spawner); - let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap()); - let test_task = async move { - let (tx, rx) = oneshot::channel(); - - ctx_handle.send(FromOverseer::Communication { - msg: RuntimeApiMessage::Request(relay_parent, Request::Authorities(tx)) - }).await; - - assert_eq!(rx.await.unwrap().unwrap(), runtime_api.authorities); - - ctx_handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; - }; - - futures::executor::block_on(future::join(subsystem_task, test_task)); - } - #[test] fn requests_validators() { let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); diff --git a/node/network/gossip-support/Cargo.toml b/node/network/gossip-support/Cargo.toml index 0de20c53781d..b16061734348 100644 --- a/node/network/gossip-support/Cargo.toml +++ b/node/network/gossip-support/Cargo.toml @@ -5,8 +5,10 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } polkadot-node-network-protocol = { path = "../protocol" } polkadot-node-subsystem = { path = "../../subsystem" } diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index 11bcb9fb87ba..43b862bba4c0 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -20,6 +20,9 @@ //! are a validator in the current session. use futures::{channel::mpsc, FutureExt as _}; +use std::sync::Arc; +use sp_api::ProvideRuntimeApi; +use sp_authority_discovery::AuthorityDiscoveryApi; use polkadot_node_subsystem::{ messages::{ GossipSupportMessage, @@ -32,7 +35,7 @@ use polkadot_node_subsystem_util::{ self as util, }; use polkadot_primitives::v1::{ - Hash, SessionIndex, AuthorityDiscoveryId, + Hash, SessionIndex, AuthorityDiscoveryId, Block, BlockId, }; use polkadot_node_network_protocol::{peer_set::PeerSet, PeerId}; use sp_keystore::{CryptoStore, SyncCryptoStorePtr}; @@ -41,7 +44,8 @@ use sp_application_crypto::{Public, AppKey}; const LOG_TARGET: &str = "parachain::gossip-support"; /// The Gossip Support subsystem. -pub struct GossipSupport { +pub struct GossipSupport { + client: Arc, keystore: SyncCryptoStorePtr, } @@ -52,11 +56,16 @@ struct State { _last_connection_request: Option>, } -impl GossipSupport { +impl GossipSupport +where + Client: ProvideRuntimeApi, + Client::Api: AuthorityDiscoveryApi, +{ /// Create a new instance of the [`GossipSupport`] subsystem. - pub fn new(keystore: SyncCryptoStorePtr) -> Self { + pub fn new(keystore: SyncCryptoStorePtr, client: Arc) -> Self { Self { - keystore + client, + keystore, } } @@ -66,7 +75,7 @@ impl GossipSupport { Context: SubsystemContext, { let mut state = State::default(); - let Self { keystore } = self; + let Self { client, keystore } = self; loop { let message = match ctx.recv().await { Ok(message) => message, @@ -88,7 +97,7 @@ impl GossipSupport { tracing::trace!(target: LOG_TARGET, "active leaves signal"); let leaves = activated.into_iter().map(|a| a.hash); - if let Err(e) = state.handle_active_leaves(&mut ctx, &keystore, leaves).await { + if let Err(e) = state.handle_active_leaves(&mut ctx, client.clone(), &keystore, leaves).await { tracing::debug!(target: LOG_TARGET, error = ?e); } } @@ -101,12 +110,18 @@ impl GossipSupport { } } -async fn determine_relevant_authorities( - ctx: &mut impl SubsystemContext, +async fn determine_relevant_authorities( + client: Arc, relay_parent: Hash, -) -> Result, util::Error> { - let authorities = util::request_authorities_ctx(relay_parent, ctx).await?.await??; - Ok(authorities) +) -> Result, util::Error> +where + Client: ProvideRuntimeApi, + Client::Api: AuthorityDiscoveryApi, +{ + let api = client.runtime_api(); + let result = api.authorities(&BlockId::Hash(relay_parent)) + .map_err(|e| util::Error::RuntimeApi(format!("{:?}", e).into())); + result } /// Return an error if we're not a validator in the given set (do not have keys). @@ -129,12 +144,17 @@ impl State { /// 1. Determine if the current session index has changed. /// 2. If it has, determine relevant validators /// and issue a connection request. - async fn handle_active_leaves( + async fn handle_active_leaves( &mut self, ctx: &mut impl SubsystemContext, + client: Arc, keystore: &SyncCryptoStorePtr, leaves: impl Iterator, - ) -> Result<(), util::Error> { + ) -> Result<(), util::Error> + where + Client: ProvideRuntimeApi, + Client::Api: AuthorityDiscoveryApi, + { for leaf in leaves { let current_index = util::request_session_index_for_child_ctx(leaf, ctx).await?.await??; let maybe_new_session = match self.last_session_index { @@ -144,7 +164,7 @@ impl State { if let Some((new_session, relay_parent)) = maybe_new_session { tracing::debug!(target: LOG_TARGET, %new_session, "New session detected"); - let authorities = determine_relevant_authorities(ctx, relay_parent).await?; + let authorities = determine_relevant_authorities(client.clone(), relay_parent).await?; ensure_i_am_an_authority(keystore, &authorities).await?; tracing::debug!(target: LOG_TARGET, num = ?authorities.len(), "Issuing a connection request"); @@ -163,11 +183,13 @@ impl State { } } -impl Subsystem for GossipSupport +impl Subsystem for GossipSupport where - C: SubsystemContext + Sync + Send, + Context: SubsystemContext + Sync + Send, + Client: ProvideRuntimeApi + Send + 'static + Sync, + Client::Api: AuthorityDiscoveryApi, { - fn start(self, ctx: C) -> SpawnedSubsystem { + fn start(self, ctx: Context) -> SpawnedSubsystem { let future = self.run(ctx) .map(|_| Ok(())) .boxed(); diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index 1e13a322bcd0..e93138525cd6 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -34,6 +34,7 @@ use { polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandler}, polkadot_primitives::v1::ParachainHost, sc_authority_discovery::Service as AuthorityDiscoveryService, + sp_authority_discovery::AuthorityDiscoveryApi, sp_blockchain::HeaderBackend, sp_trie::PrefixedMemoryDB, sc_client_api::{AuxStore, ExecutorProvider}, @@ -406,7 +407,7 @@ fn real_overseer( ) -> Result<(Overseer, OverseerHandler), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, Spawner: 'static + SpawnNamed + Clone + Unpin, { Overseer::new( @@ -434,7 +435,7 @@ fn real_overseer( ) -> Result<(Overseer, OverseerHandler), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, Spawner: 'static + SpawnNamed + Clone + Unpin, { use polkadot_node_subsystem_util::metrics::Metrics; @@ -540,6 +541,7 @@ where )?, gossip_support: GossipSupportSubsystem::new( keystore.clone(), + runtime_client.clone(), ), }; diff --git a/node/subsystem-util/src/lib.rs b/node/subsystem-util/src/lib.rs index fbcc6588bc36..47c4406a95c3 100644 --- a/node/subsystem-util/src/lib.rs +++ b/node/subsystem-util/src/lib.rs @@ -39,7 +39,6 @@ use polkadot_primitives::v1::{ CandidateEvent, CommittedCandidateReceipt, CoreState, EncodeAs, PersistedValidationData, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, SessionIndex, Signed, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, SessionInfo, - AuthorityDiscoveryId, }; use sp_core::{traits::SpawnNamed, Public}; use sp_application_crypto::AppKey; @@ -167,7 +166,6 @@ macro_rules! specialize_requests { } specialize_requests! { - fn request_authorities() -> Vec; Authorities; fn request_validators() -> Vec; Validators; fn request_validator_groups() -> (Vec>, GroupRotationInfo); ValidatorGroups; fn request_availability_cores() -> Vec; AvailabilityCores; @@ -249,7 +247,6 @@ macro_rules! specialize_requests_ctx { } specialize_requests_ctx! { - fn request_authorities_ctx() -> Vec; Authorities; fn request_validators_ctx() -> Vec; Validators; fn request_validator_groups_ctx() -> (Vec>, GroupRotationInfo); ValidatorGroups; fn request_availability_cores_ctx() -> Vec; AvailabilityCores; diff --git a/node/subsystem/src/messages.rs b/node/subsystem/src/messages.rs index 03ca4314fd16..06d41def8083 100644 --- a/node/subsystem/src/messages.rs +++ b/node/subsystem/src/messages.rs @@ -436,8 +436,6 @@ pub type RuntimeApiSender = oneshot::Sender>), /// Get the current validator set. Validators(RuntimeApiSender>), /// Get the validator groups and group rotation info. diff --git a/primitives/src/v1.rs b/primitives/src/v1.rs index 69cfcf92bd16..4cb8a09b812c 100644 --- a/primitives/src/v1.rs +++ b/primitives/src/v1.rs @@ -798,10 +798,6 @@ sp_api::decl_runtime_apis! { // Additionally, some runtime APIs may depend on state that is pruned on the `on_initialize`. // At the moment of writing, this is `candidate_events`. - /// Get the next, current and some previous authority keys deduplicated. - #[skip_initialize_block] - fn authorities() -> Vec; - /// Get the current validators. #[skip_initialize_block] fn validators() -> Vec; diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 7c20c90c92a8..9624c6698392 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -1157,10 +1157,6 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { - fn authorities() -> Vec { - Vec::new() - } - fn validators() -> Vec { Vec::new() } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 66f796311ae5..5db5d37f97e5 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -1184,10 +1184,6 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { - fn authorities() -> Vec { - Vec::new() - } - fn validators() -> Vec { Vec::new() } diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index cf6531ae2a9c..e841939c02f9 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -809,10 +809,6 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { - fn authorities() -> Vec { - runtime_api_impl::relevant_authority_ids::() - } - fn validators() -> Vec { runtime_api_impl::validators::() } diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index 9ad0bb169ae6..685c5918c525 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -633,10 +633,6 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { - fn authorities() -> Vec { - runtime_impl::relevant_authority_ids::() - } - fn validators() -> Vec { runtime_impl::validators::() } diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 0ccaf1ab79e7..9709366306d5 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -856,10 +856,6 @@ sp_api::impl_runtime_apis! { } impl primitives::v1::ParachainHost for Runtime { - fn authorities() -> Vec { - Vec::new() - } - fn validators() -> Vec { Vec::new() } From 0b5025b4c3e53de21e20921c15ff8f59c448f6cc Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Thu, 1 Apr 2021 15:24:07 +0200 Subject: [PATCH 5/5] update comments to the status quo --- node/network/gossip-support/src/lib.rs | 3 +-- roadmap/implementers-guide/src/node/utility/gossip-support.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index 43b862bba4c0..0f68f5af7143 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -16,8 +16,7 @@ //! This subsystem is responsible for keeping track of session changes //! and issuing a connection request to the validators relevant to -//! the gossiping subsystems on every new session. But only if we -//! are a validator in the current session. +//! the gossiping subsystems on every new session. use futures::{channel::mpsc, FutureExt as _}; use std::sync::Arc; diff --git a/roadmap/implementers-guide/src/node/utility/gossip-support.md b/roadmap/implementers-guide/src/node/utility/gossip-support.md index 6eb28c8d9f29..55fafd7ca2b7 100644 --- a/roadmap/implementers-guide/src/node/utility/gossip-support.md +++ b/roadmap/implementers-guide/src/node/utility/gossip-support.md @@ -1,7 +1,7 @@ # Gossip Support The Gossip Support Subsystem is responsible for keeping track of session changes -and issuing a connection request to all validators in the current session and a few past sessions +and issuing a connection request to all validators in the next, current and a few past sessions if we are a validator in these sessions. The request will add all validators to a reserved PeerSet, meaning we will not reject a connection request from any validator in that set.