backport to master: Handling of disabled validators in backing subsystem (#1259) (#2764)

#1259 was merged into a feature branch, but we've decided to merge
node-side changes for disabling straight into master.
This is a dependency of #1841 and #2637.

---------

Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>
This commit is contained in:
ordian
2024-01-08 20:58:30 +01:00
committed by GitHub
parent 4fdab499c4
commit a02b53475b
7 changed files with 575 additions and 74 deletions
+78 -2
View File
@@ -55,6 +55,7 @@ use sp_core::ByteArray;
use sp_keystore::{Error as KeystoreError, KeystorePtr};
use std::time::Duration;
use thiserror::Error;
use vstaging::get_disabled_validators_with_fallback;
pub use metered;
pub use polkadot_node_network_protocol::MIN_GOSSIP_PEERS;
@@ -79,6 +80,9 @@ pub mod inclusion_emulator;
/// Convenient and efficient runtime info access.
pub mod runtime;
/// Helpers for working with unreleased runtime calls
pub mod vstaging;
/// Nested message sending
///
/// Useful for having mostly synchronous code, with submodules spawning short lived asynchronous
@@ -92,6 +96,8 @@ mod determine_new_blocks;
#[cfg(test)]
mod tests;
const LOG_TARGET: &'static str = "parachain::subsystem-util";
/// Duration a job will wait after sending a stop signal before hard-aborting.
pub const JOB_GRACEFUL_STOP_DURATION: Duration = Duration::from_secs(1);
/// Capacity of channels to and from individual jobs
@@ -157,6 +163,62 @@ where
rx
}
/// Verifies if `ParachainHost` runtime api is at least at version `required_runtime_version`. This
/// method is used to determine if a given runtime call is supported by the runtime.
pub async fn has_required_runtime<Sender>(
sender: &mut Sender,
relay_parent: Hash,
required_runtime_version: u32,
) -> bool
where
Sender: SubsystemSender<RuntimeApiMessage>,
{
gum::trace!(target: LOG_TARGET, ?relay_parent, "Fetching ParachainHost runtime api version");
let (tx, rx) = oneshot::channel();
sender
.send_message(RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::Version(tx)))
.await;
match rx.await {
Result::Ok(Ok(runtime_version)) => {
gum::trace!(
target: LOG_TARGET,
?relay_parent,
?runtime_version,
?required_runtime_version,
"Fetched ParachainHost runtime api version"
);
runtime_version >= required_runtime_version
},
Result::Ok(Err(RuntimeApiError::Execution { source: error, .. })) => {
gum::trace!(
target: LOG_TARGET,
?relay_parent,
?error,
"Execution error while fetching ParachainHost runtime api version"
);
false
},
Result::Ok(Err(RuntimeApiError::NotSupported { .. })) => {
gum::trace!(
target: LOG_TARGET,
?relay_parent,
"NotSupported error while fetching ParachainHost runtime api version"
);
false
},
Result::Err(_) => {
gum::trace!(
target: LOG_TARGET,
?relay_parent,
"Cancelled error while fetching ParachainHost runtime api version"
);
false
},
}
}
/// Construct specialized request functions for the runtime.
///
/// These would otherwise get pretty repetitive.
@@ -378,6 +440,7 @@ pub struct Validator {
signing_context: SigningContext,
key: ValidatorId,
index: ValidatorIndex,
disabled: bool,
}
impl Validator {
@@ -399,7 +462,12 @@ impl Validator {
let validators = validators?;
Self::construct(&validators, signing_context, keystore)
// TODO: https://github.com/paritytech/polkadot-sdk/issues/1940
// When `DisabledValidators` is released remove this and add a
// `request_disabled_validators` call here
let disabled_validators = get_disabled_validators_with_fallback(sender, parent).await?;
Self::construct(&validators, &disabled_validators, signing_context, keystore)
}
/// Construct a validator instance without performing runtime fetches.
@@ -407,13 +475,16 @@ impl Validator {
/// This can be useful if external code also needs the same data.
pub fn construct(
validators: &[ValidatorId],
disabled_validators: &[ValidatorIndex],
signing_context: SigningContext,
keystore: KeystorePtr,
) -> Result<Self, Error> {
let (key, index) =
signing_key_and_index(validators, &keystore).ok_or(Error::NotAValidator)?;
Ok(Validator { signing_context, key, index })
let disabled = disabled_validators.iter().any(|d: &ValidatorIndex| *d == index);
Ok(Validator { signing_context, key, index, disabled })
}
/// Get this validator's id.
@@ -426,6 +497,11 @@ impl Validator {
self.index
}
/// Get the enabled/disabled state of this validator
pub fn disabled(&self) -> bool {
self.disabled
}
/// Get the current signing context.
pub fn signing_context(&self) -> &SigningContext {
&self.signing_context