make chain selection typed and more explicit in naming and logging (#4345)

* minor: assure conditions match

This simplifies visual integrity checks that an overseer is connected
when it has to be.

* fix: avoid printing a misleading log in case of the disabled disputes feature

* chore: comments

* add expressive types for the selection algorithm
This commit is contained in:
Bernhard Schuster
2021-11-30 07:36:50 +01:00
committed by GitHub
parent eb3d681c90
commit 13f0e5d734
2 changed files with 76 additions and 33 deletions
@@ -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<B: sc_client_api::Backend<PolkadotBlock>> {
Yes(SelectRelayChainInner<B, Handle>),
No,
}
impl<B> Clone for IsDisputesAwareWithOverseer<B>
where
B: sc_client_api::Backend<PolkadotBlock>,
SelectRelayChainInner<B, Handle>: 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<B: sc_client_api::Backend<PolkadotBlock>> {
is_relay_chain: bool,
longest_chain: sc_consensus::LongestChain<B, PolkadotBlock>,
selection: SelectRelayChainInner<B, Handle>,
selection: IsDisputesAwareWithOverseer<B>,
}
impl<B> Clone for SelectRelayChain<B>
@@ -121,11 +141,7 @@ where
SelectRelayChainInner<B, Handle>: 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<B> SelectRelayChain<B>
where
B: sc_client_api::Backend<PolkadotBlock> + 'static,
{
/// Use the plain longest chain algorithm exclusively.
pub fn new_longest_chain(backend: Arc<B>) -> 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<B>, overseer: Handle, is_relay_chain: bool, metrics: Metrics) -> Self {
pub fn new_disputes_aware(backend: Arc<B>, 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<PolkadotBlock> + 'static,
{
async fn leaves(&self) -> Result<Vec<Hash>, 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<PolkadotHeader, ConsensusError> {
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
}
}