diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs index 224d65641a..16e1fcd743 100644 --- a/polkadot/node/service/src/lib.rs +++ b/polkadot/node/service/src/lib.rs @@ -719,15 +719,21 @@ where let chain_spec = config.chain_spec.cloned_box(); let local_keystore = basics.keystore_container.local_keystore(); - let requires_overseer_for_chain_sel = - local_keystore.is_some() && (role.is_authority() || is_collator.is_collator()); + let auth_or_collator = role.is_authority() || is_collator.is_collator(); + let requires_overseer_for_chain_sel = local_keystore.is_some() && auth_or_collator; - let select_chain = SelectRelayChain::new( - basics.backend.clone(), - overseer_handle.clone(), - requires_overseer_for_chain_sel, - polkadot_node_subsystem_util::metrics::Metrics::register(prometheus_registry.as_ref())?, - ); + let select_chain = if requires_overseer_for_chain_sel { + let metrics = + polkadot_node_subsystem_util::metrics::Metrics::register(prometheus_registry.as_ref())?; + + SelectRelayChain::new_disputes_aware( + basics.backend.clone(), + overseer_handle.clone(), + metrics, + ) + } else { + SelectRelayChain::new_longest_chain(basics.backend.clone()) + }; let service::PartialComponents::<_, _, SelectRelayChain<_>, _, _, _> { client, @@ -876,7 +882,7 @@ where let active_leaves = futures::executor::block_on(active_leaves(select_chain.as_longest_chain(), &*client))?; - let authority_discovery_service = if role.is_authority() || is_collator.is_collator() { + let authority_discovery_service = if auth_or_collator { use futures::StreamExt; use sc_network::Event; diff --git a/polkadot/node/service/src/relay_chain_selection.rs b/polkadot/node/service/src/relay_chain_selection.rs index c195b91c78..afcbac7655 100644 --- a/polkadot/node/service/src/relay_chain_selection.rs +++ b/polkadot/node/service/src/relay_chain_selection.rs @@ -108,11 +108,31 @@ impl Metrics { } } +/// Determines whether the chain is a relay chain +/// and hence has to take approval votes and disputes +/// into account. +enum IsDisputesAwareWithOverseer> { + Yes(SelectRelayChainInner), + No, +} + +impl Clone for IsDisputesAwareWithOverseer +where + B: sc_client_api::Backend, + SelectRelayChainInner: Clone, +{ + fn clone(&self) -> Self { + match self { + Self::Yes(ref inner) => Self::Yes(inner.clone()), + Self::No => Self::No, + } + } +} + /// A chain-selection implementation which provides safety for relay chains. pub struct SelectRelayChain> { - is_relay_chain: bool, longest_chain: sc_consensus::LongestChain, - selection: SelectRelayChainInner, + selection: IsDisputesAwareWithOverseer, } impl Clone for SelectRelayChain @@ -121,11 +141,7 @@ where SelectRelayChainInner: Clone, { fn clone(&self) -> Self { - Self { - longest_chain: self.longest_chain.clone(), - is_relay_chain: self.is_relay_chain, - selection: self.selection.clone(), - } + Self { longest_chain: self.longest_chain.clone(), selection: self.selection.clone() } } } @@ -133,18 +149,35 @@ impl SelectRelayChain where B: sc_client_api::Backend + 'static, { + /// Use the plain longest chain algorithm exclusively. + pub fn new_longest_chain(backend: Arc) -> Self { + tracing::debug!(target: LOG_TARGET, "Using {} chain selection algorithm", "longest"); + + Self { + longest_chain: sc_consensus::LongestChain::new(backend.clone()), + selection: IsDisputesAwareWithOverseer::No, + } + } + /// Create a new [`SelectRelayChain`] wrapping the given chain backend /// and a handle to the overseer. - pub fn new(backend: Arc, overseer: Handle, is_relay_chain: bool, metrics: Metrics) -> Self { + pub fn new_disputes_aware(backend: Arc, overseer: Handle, metrics: Metrics) -> Self { tracing::debug!( target: LOG_TARGET, - "Using {} as chain selection algorithm", - if is_relay_chain { "dispute aware relay" } else { "longest" } + "Using {} chain selection algorithm", + if cfg!(feature = "disputes") { + "dispute aware relay" + } else { + // no disputes are queried, that logic is disabled + // in `fn finality_target_with_longest_chain`. + "short-circuited relay" + } ); SelectRelayChain { longest_chain: sc_consensus::LongestChain::new(backend.clone()), - selection: SelectRelayChainInner::new(backend, overseer, metrics), - is_relay_chain, + selection: IsDisputesAwareWithOverseer::Yes(SelectRelayChainInner::new( + backend, overseer, metrics, + )), } } @@ -160,18 +193,17 @@ where B: sc_client_api::Backend + 'static, { async fn leaves(&self) -> Result, ConsensusError> { - if !self.is_relay_chain { - return self.longest_chain.leaves().await + match self.selection { + IsDisputesAwareWithOverseer::Yes(ref selection) => selection.leaves().await, + IsDisputesAwareWithOverseer::No => self.longest_chain.leaves().await, } - - self.selection.leaves().await } async fn best_chain(&self) -> Result { - if !self.is_relay_chain { - return self.longest_chain.best_chain().await + match self.selection { + IsDisputesAwareWithOverseer::Yes(ref selection) => selection.best_chain().await, + IsDisputesAwareWithOverseer::No => self.longest_chain.best_chain().await, } - self.selection.best_chain().await } async fn finality_target( @@ -182,12 +214,17 @@ where let longest_chain_best = self.longest_chain.finality_target(target_hash, maybe_max_number).await?; - if !self.is_relay_chain { - return Ok(longest_chain_best) + if let IsDisputesAwareWithOverseer::Yes(ref selection) = self.selection { + selection + .finality_target_with_longest_chain( + target_hash, + longest_chain_best, + maybe_max_number, + ) + .await + } else { + Ok(longest_chain_best) } - self.selection - .finality_target_with_longest_chain(target_hash, longest_chain_best, maybe_max_number) - .await } }