enable disputes (#3478)

* initial integration and migration code

* fix tests

* fix counting test

* assume the current version on missing file

* use SelectRelayChain

* remove duplicate metric

* Update node/service/src/lib.rs

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>

* remove ApprovalCheckingVotingRule

* address my concern

* never mode for StagnantCheckInterval

* REVERTME: some logs

* w00t

* it's ugly but it works

* Revert "REVERTME: some logs"

This reverts commit e210505a2e83e31c381394924500b69277bb042e.

* it's handle, not handler

* fix a few typos

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
Andronik Ordian
2021-07-26 14:46:31 +02:00
committed by GitHub
parent 8fbd3a4f62
commit bd9b743872
19 changed files with 405 additions and 368 deletions
+1 -197
View File
@@ -23,179 +23,7 @@ use sp_runtime::generic::BlockId;
use sp_runtime::traits::Header as _;
#[cfg(feature = "full-node")]
use {
polkadot_primitives::v1::{Hash, Block as PolkadotBlock, Header as PolkadotHeader},
polkadot_subsystem::messages::ApprovalVotingMessage,
prometheus_endpoint::{self, Registry},
polkadot_overseer::Handle,
futures::channel::oneshot,
};
/// A custom GRANDPA voting rule that acts as a diagnostic for the approval
/// voting subsystem's desired votes.
///
/// The practical effect of this voting rule is to implement a fixed delay of
/// blocks and to issue a prometheus metric on the lag behind the head that
/// approval checking would indicate.
#[cfg(feature = "full-node")]
#[derive(Clone)]
pub(crate) struct ApprovalCheckingVotingRule {
checking_lag: Option<prometheus_endpoint::Gauge<prometheus_endpoint::U64>>,
overseer: Handle,
}
#[cfg(feature = "full-node")]
impl ApprovalCheckingVotingRule {
/// Create a new approval checking diagnostic voting rule.
pub fn new(overseer: Handle, registry: Option<&Registry>)
-> Result<Self, prometheus_endpoint::PrometheusError>
{
Ok(ApprovalCheckingVotingRule {
checking_lag: if let Some(registry) = registry {
Some(prometheus_endpoint::register(
prometheus_endpoint::Gauge::with_opts(
prometheus_endpoint::Opts::new(
"parachain_approval_checking_finality_lag",
"How far behind the head of the chain the Approval Checking protocol wants to vote",
)
)?,
registry,
)?)
} else {
None
},
overseer,
})
}
}
#[cfg(feature = "full-node")]
#[derive(Debug, PartialEq)]
/// Vote explicitly on the given hash.
enum ParachainVotingRuleTarget<H, N> {
Explicit((H, N)),
/// Vote on the current target.
Current,
/// Vote on the base target - the minimal possible vote.
Base,
}
#[cfg(feature = "full-node")]
fn approval_checking_vote_to_grandpa_vote<H, N: PartialOrd>(
approval_checking_vote: Option<(H, N)>,
current_number: N,
) -> ParachainVotingRuleTarget<H, N> {
match approval_checking_vote {
Some((hash, number)) => if number > current_number {
// respect other voting rule.
ParachainVotingRuleTarget::Current
} else {
ParachainVotingRuleTarget::Explicit((hash, number))
},
// If approval-voting chooses 'None', that means we should vote on the base (last round estimate).
None => ParachainVotingRuleTarget::Base,
}
}
/// The maximum amount of unfinalized blocks we are willing to allow due to approval checking lag.
/// This is a safety net that should be removed at some point in the future.
#[cfg(feature = "full-node")]
const MAX_APPROVAL_CHECKING_FINALITY_LAG: polkadot_primitives::v1::BlockNumber = 50;
#[cfg(feature = "full-node")]
impl<B> grandpa::VotingRule<PolkadotBlock, B> for ApprovalCheckingVotingRule
where B: sp_blockchain::HeaderBackend<PolkadotBlock> + 'static
{
fn restrict_vote(
&self,
backend: Arc<B>,
base: &PolkadotHeader,
best_target: &PolkadotHeader,
current_target: &PolkadotHeader,
) -> grandpa::VotingRuleResult<PolkadotBlock> {
// Query approval checking and issue metrics.
let mut overseer = self.overseer.clone();
let checking_lag = self.checking_lag.clone();
let best_hash = best_target.hash();
let best_number = best_target.number.clone();
let best_header = best_target.clone();
let current_hash = current_target.hash();
let current_number = current_target.number.clone();
let base_hash = base.hash();
let base_number = base.number;
Box::pin(async move {
let (tx, rx) = oneshot::channel();
let approval_checking_subsystem_vote = {
overseer.send_msg(
ApprovalVotingMessage::ApprovedAncestor(
best_hash,
base_number,
tx,
),
std::any::type_name::<Self>(),
).await;
rx.await.ok().and_then(|v| v)
};
let approval_checking_subsystem_lag = approval_checking_subsystem_vote.map_or(
best_number - base_number,
|(_h, n)| best_number - n,
);
if let Some(ref checking_lag) = checking_lag {
checking_lag.set(approval_checking_subsystem_lag as _);
}
let min_vote = {
let diff = best_number.saturating_sub(base_number);
if diff >= MAX_APPROVAL_CHECKING_FINALITY_LAG {
// Catch up to the best, with some extra lag.
let target_number = best_number - MAX_APPROVAL_CHECKING_FINALITY_LAG;
if target_number >= current_number {
Some((current_hash, current_number))
} else {
walk_backwards_to_target_block(&*backend, target_number, &best_header).ok()
}
} else {
Some((base_hash, base_number))
}
};
let vote = match approval_checking_vote_to_grandpa_vote(
approval_checking_subsystem_vote,
current_number,
) {
ParachainVotingRuleTarget::Explicit(vote) => {
if min_vote.as_ref().map_or(false, |min| min.1 > vote.1) {
min_vote
} else {
Some(vote)
}
}
ParachainVotingRuleTarget::Current => Some((current_hash, current_number)),
ParachainVotingRuleTarget::Base => min_vote.or(Some((base_hash, base_number))),
};
tracing::trace!(
target: "parachain::approval-voting",
?vote,
?approval_checking_subsystem_vote,
approval_checking_subsystem_lag,
current_number,
best_number,
base_number,
"GRANDPA: voting based on approved ancestor.",
);
vote
})
}
}
use polkadot_primitives::v1::Hash;
/// Returns the block hash of the block at the given `target_number` by walking
/// backwards from the given `current_header`.
@@ -433,7 +261,6 @@ mod tests {
use sp_runtime::{generic::BlockId, traits::Header};
use consensus_common::BlockOrigin;
use std::sync::Arc;
use super::{approval_checking_vote_to_grandpa_vote, ParachainVotingRuleTarget};
#[test]
fn grandpa_pause_voting_rule_works() {
@@ -545,27 +372,4 @@ mod tests {
None,
);
}
#[test]
fn approval_checking_to_grandpa_rules() {
assert_eq!(
approval_checking_vote_to_grandpa_vote::<(), _>(None, 5),
ParachainVotingRuleTarget::Base,
);
assert_eq!(
approval_checking_vote_to_grandpa_vote(Some(("2", 2)), 3),
ParachainVotingRuleTarget::Explicit(("2", 2)),
);
assert_eq!(
approval_checking_vote_to_grandpa_vote(Some(("2", 2)), 2),
ParachainVotingRuleTarget::Explicit(("2", 2)),
);
assert_eq!(
approval_checking_vote_to_grandpa_vote(Some(("2", 2)), 1),
ParachainVotingRuleTarget::Current,
);
}
}
+50 -38
View File
@@ -42,6 +42,11 @@ use {
polkadot_node_core_av_store::Error as AvailabilityError,
polkadot_node_core_approval_voting::Config as ApprovalVotingConfig,
polkadot_node_core_candidate_validation::Config as CandidateValidationConfig,
polkadot_node_core_chain_selection::{
self as chain_selection_subsystem,
Config as ChainSelectionConfig,
},
polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig,
polkadot_overseer::BlockInfo,
sp_trie::PrefixedMemoryDB,
sc_client_api::ExecutorProvider,
@@ -56,7 +61,7 @@ pub use {
sp_authority_discovery::AuthorityDiscoveryApi,
sc_client_api::AuxStore,
polkadot_primitives::v1::ParachainHost,
polkadot_overseer::{Overseer, Handle},
polkadot_overseer::{Overseer, Handle, OverseerHandle},
};
pub use sp_core::traits::SpawnNamed;
@@ -214,7 +219,7 @@ fn jaeger_launch_collector_with_agent(spawner: impl SpawnNamed, config: &Configu
}
#[cfg(feature = "full-node")]
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
type FullSelectChain = relay_chain_selection::SelectRelayChain<FullBackend>;
#[cfg(feature = "full-node")]
type FullGrandpaBlockImport<RuntimeApi, Executor> = grandpa::GrandpaBlockImport<
FullBackend, Block, FullClient<RuntimeApi, Executor>, FullSelectChain
@@ -298,7 +303,11 @@ fn new_partial<RuntimeApi, Executor>(
jaeger_launch_collector_with_agent(task_manager.spawn_handle(), &*config, jaeger_agent)?;
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let select_chain = relay_chain_selection::SelectRelayChain::new(
backend.clone(),
Handle::new_disconnected(),
polkadot_node_subsystem_util::metrics::Metrics::register(config.prometheus_registry())?,
);
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
config.transaction_pool.clone(),
@@ -427,7 +436,7 @@ fn new_partial<RuntimeApi, Executor>(
pub struct NewFull<C> {
pub task_manager: TaskManager,
pub client: C,
pub overseer_handler: Option<Handle>,
pub overseer_handle: Option<Handle>,
pub network: Arc<sc_network::NetworkService<Block, <Block as BlockT>::Hash>>,
pub rpc_handlers: RpcHandlers,
pub backend: Arc<FullBackend>,
@@ -440,7 +449,7 @@ impl<C> NewFull<C> {
NewFull {
client: func(self.client),
task_manager: self.task_manager,
overseer_handler: self.overseer_handler,
overseer_handle: self.overseer_handle,
network: self.network,
rpc_handlers: self.rpc_handlers,
backend: self.backend,
@@ -480,7 +489,7 @@ impl IsCollator {
/// Returns the active leaves the overseer should start with.
#[cfg(feature = "full-node")]
async fn active_leaves<RuntimeApi, Executor>(
select_chain: &sc_consensus::LongestChain<FullBackend, Block>,
select_chain: &impl SelectChain<Block>,
client: &FullClient<RuntimeApi, Executor>,
) -> Result<Vec<BlockInfo>, Error>
where
@@ -573,7 +582,7 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
backend,
mut task_manager,
keystore_container,
select_chain,
mut select_chain,
import_queue,
transaction_pool,
other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry)
@@ -655,6 +664,15 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
},
};
let chain_selection_config = ChainSelectionConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_chain_selection_data,
stagnant_check_interval: chain_selection_subsystem::StagnantCheckInterval::never(),
};
let dispute_coordinator_config = DisputeCoordinatorConfig {
col_data: crate::parachains_db::REAL_COLUMNS.col_dispute_coordinator_data,
};
let chain_spec = config.chain_spec.cloned_box();
let rpc_handlers = service::spawn_tasks(service::SpawnTasksParams {
config,
@@ -714,8 +732,6 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
None
};
// we'd say let overseer_handler = authority_discovery_service.map(|authority_discovery_service|, ...),
// but in that case we couldn't use ? to propagate errors
let local_keystore = keystore_container.local_keystore();
if local_keystore.is_none() {
tracing::info!("Cannot run as validator without local keystore.");
@@ -724,8 +740,8 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
let maybe_params = local_keystore
.and_then(move |k| authority_discovery_service.map(|a| (a, k)));
let overseer_handler = if let Some((authority_discovery_service, keystore)) = maybe_params {
let (overseer, overseer_handler) = overseer_gen.generate::<
let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params {
let (overseer, overseer_handle) = overseer_gen.generate::<
service::SpawnTaskHandle,
FullClient<RuntimeApi, Executor>,
>(
@@ -734,23 +750,26 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
keystore,
runtime_client: overseer_client.clone(),
parachains_db,
availability_config,
approval_voting_config,
network_service: network.clone(),
authority_discovery_service,
request_multiplexer,
registry: prometheus_registry.as_ref(),
spawner,
is_collator,
approval_voting_config,
availability_config,
candidate_validation_config,
chain_selection_config,
dispute_coordinator_config,
}
)?;
let overseer_handler_clone = overseer_handler.clone();
let handle = Handle::Connected(overseer_handle.clone());
let handle_clone = handle.clone();
task_manager.spawn_essential_handle().spawn_blocking("overseer", Box::pin(async move {
use futures::{pin_mut, select, FutureExt};
let forward = polkadot_overseer::forward_events(overseer_client, overseer_handler_clone);
let forward = polkadot_overseer::forward_events(overseer_client, handle_clone);
let forward = forward.fuse();
let overseer_fut = overseer.run().fuse();
@@ -764,8 +783,19 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
complete => (),
}
}));
// we should remove this check before we deploy parachains on polkadot
// TODO: https://github.com/paritytech/polkadot/issues/3326
let should_connect_overseer = chain_spec.is_kusama()
|| chain_spec.is_westend()
|| chain_spec.is_rococo()
|| chain_spec.is_wococo();
Some(overseer_handler)
if should_connect_overseer {
select_chain.connect_to_overseer(overseer_handle.clone());
} else {
tracing::info!("Overseer is running in the disconnected state");
}
Some(handle)
} else {
None
};
@@ -783,7 +813,7 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
);
let client_clone = client.clone();
let overseer_handler = overseer_handler.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone();
let overseer_handle = overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone();
let slot_duration = babe_link.config().slot_duration();
let babe_config = babe::BabeParams {
keystore: keystore_container.sync_keystore(),
@@ -795,11 +825,11 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
justification_sync_link: network.clone(),
create_inherent_data_providers: move |parent, ()| {
let client_clone = client_clone.clone();
let overseer_handler = overseer_handler.clone();
let overseer_handle = overseer_handle.clone();
async move {
let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create(
&*client_clone,
overseer_handler,
overseer_handle,
parent,
).await.map_err(|e| Box::new(e))?;
@@ -889,24 +919,6 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
// after the given pause block is finalized and restarting after the
// given delay.
let builder = grandpa::VotingRulesBuilder::default();
// we should enable approval checking voting rule before we deploy parachains on polkadot
let enable_approval_checking_voting_rule = chain_spec.is_kusama()
|| chain_spec.is_westend()
|| chain_spec.is_rococo()
|| chain_spec.is_wococo();
let builder = if let Some(ref overseer) = overseer_handler {
if enable_approval_checking_voting_rule {
builder.add(grandpa_support::ApprovalCheckingVotingRule::new(
overseer.clone(),
prometheus_registry.as_ref(),
)?)
} else {
builder
}
} else {
builder
};
let voting_rule = match grandpa_pause {
Some((block, delay)) => {
@@ -946,7 +958,7 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
Ok(NewFull {
task_manager,
client,
overseer_handler,
overseer_handle,
network,
rpc_handlers,
backend,
+41 -10
View File
@@ -28,7 +28,9 @@ use polkadot_network_bridge::RequestMultiplexer;
use polkadot_node_core_av_store::Config as AvailabilityConfig;
use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, Handle};
use polkadot_node_core_chain_selection::Config as ChainSelectionConfig;
use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandle};
use polkadot_primitives::v1::ParachainHost;
use sc_authority_discovery::Service as AuthorityDiscoveryService;
use sp_api::ProvideRuntimeApi;
@@ -54,6 +56,10 @@ pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem;
pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem;
pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem;
pub use polkadot_node_core_dispute_participation::DisputeParticipationSubsystem;
pub use polkadot_dispute_distribution::DisputeDistributionSubsystem;
pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem;
/// Arguments passed for overseer construction.
pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> where
@@ -69,10 +75,6 @@ pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> where
pub runtime_client: Arc<RuntimeClient>,
/// The underlying key value store for the parachains.
pub parachains_db: Arc<dyn kvdb::KeyValueDB>,
/// Configuration for the availability store subsystem.
pub availability_config: AvailabilityConfig,
/// Configuration for the approval voting subsystem.
pub approval_voting_config: ApprovalVotingConfig,
/// Underlying network service implementation.
pub network_service: Arc<sc_network::NetworkService<Block, Hash>>,
/// Underlying authority discovery service.
@@ -85,8 +87,16 @@ pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> where
pub spawner: Spawner,
/// Determines the behavior of the collator.
pub is_collator: IsCollator,
/// Configuration for the approval voting subsystem.
pub approval_voting_config: ApprovalVotingConfig,
/// Configuration for the availability store subsystem.
pub availability_config: AvailabilityConfig,
/// Configuration for the candidate validation subsystem.
pub candidate_validation_config: CandidateValidationConfig,
/// Configuration for the chain selection subsystem.
pub chain_selection_config: ChainSelectionConfig,
/// Configuration for the dispute coordinator subsystem.
pub dispute_coordinator_config: DisputeCoordinatorConfig,
}
/// Create a default, unaltered set of subsystems.
@@ -99,15 +109,17 @@ pub fn create_default_subsystems<'a, Spawner, RuntimeClient>
keystore,
runtime_client,
parachains_db,
availability_config,
approval_voting_config,
network_service,
authority_discovery_service,
request_multiplexer,
registry,
spawner,
is_collator,
approval_voting_config,
availability_config,
candidate_validation_config,
chain_selection_config,
dispute_coordinator_config,
..
} : OverseerGenArgs<'a, Spawner, RuntimeClient>
) -> Result<
@@ -129,6 +141,10 @@ pub fn create_default_subsystems<'a, Spawner, RuntimeClient>
ApprovalDistributionSubsystem,
ApprovalVotingSubsystem,
GossipSupportSubsystem,
DisputeCoordinatorSubsystem,
DisputeParticipationSubsystem,
DisputeDistributionSubsystem<AuthorityDiscoveryService>,
ChainSelectionSubsystem,
>,
Error
>
@@ -218,7 +234,7 @@ where
),
approval_voting: ApprovalVotingSubsystem::with_config(
approval_voting_config,
parachains_db,
parachains_db.clone(),
keystore.clone(),
Box::new(network_service.clone()),
Metrics::register(registry)?,
@@ -226,6 +242,21 @@ where
gossip_support: GossipSupportSubsystem::new(
keystore.clone(),
),
dispute_coordinator: DisputeCoordinatorSubsystem::new(
parachains_db.clone(),
dispute_coordinator_config,
keystore.clone(),
),
dispute_participation: DisputeParticipationSubsystem::new(),
dispute_distribution: DisputeDistributionSubsystem::new(
keystore.clone(),
authority_discovery_service.clone(),
Metrics::register(registry)?,
),
chain_selection: ChainSelectionSubsystem::new(
chain_selection_config,
parachains_db,
),
};
Ok(all_subsystems)
}
@@ -237,7 +268,7 @@ where
/// would do.
pub trait OverseerGen {
/// Overwrite the full generation of the overseer, including the subsystems.
fn generate<'a, Spawner, RuntimeClient>(&self, args: OverseerGenArgs<'a, Spawner, RuntimeClient>) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, Handle), Error>
fn generate<'a, Spawner, RuntimeClient>(&self, args: OverseerGenArgs<'a, Spawner, RuntimeClient>) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
@@ -256,7 +287,7 @@ pub struct RealOverseerGen;
impl OverseerGen for RealOverseerGen {
fn generate<'a, Spawner, RuntimeClient>(&self,
args : OverseerGenArgs<'a, Spawner, RuntimeClient>
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, Handle), Error>
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
+15 -4
View File
@@ -22,16 +22,21 @@ use {
kvdb::KeyValueDB,
};
#[cfg(feature = "full-node")]
mod upgrade;
#[cfg(any(test,feature = "full-node"))]
mod columns {
pub const NUM_COLUMNS: u32 = 3;
pub(crate) mod columns {
pub mod v0 {
pub const NUM_COLUMNS: u32 = 3;
}
pub const NUM_COLUMNS: u32 = 5;
pub const COL_AVAILABILITY_DATA: u32 = 0;
pub const COL_AVAILABILITY_META: u32 = 1;
pub const COL_APPROVAL_DATA: u32 = 2;
pub const COL_CHAIN_SELECTION_DATA: u32 = 3;
pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4;
}
/// Columns used by different subsystems.
@@ -44,6 +49,10 @@ pub struct ColumnsConfig {
pub col_availability_meta: u32,
/// The column used by approval voting for data.
pub col_approval_data: u32,
/// The column used by chain selection for data.
pub col_chain_selection_data: u32,
/// The column used by dispute coordinator for data.
pub col_dispute_coordinator_data: u32,
}
/// The real columns used by the parachains DB.
@@ -52,6 +61,8 @@ pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig {
col_availability_data: columns::COL_AVAILABILITY_DATA,
col_availability_meta: columns::COL_AVAILABILITY_META,
col_approval_data: columns::COL_APPROVAL_DATA,
col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA,
col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA,
};
/// The cache size for each column, in megabytes.
@@ -76,7 +87,7 @@ impl Default for CacheSizes {
}
#[cfg(feature = "full-node")]
fn other_io_error(err: String) -> io::Error {
pub(crate) fn other_io_error(err: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
@@ -27,7 +27,7 @@ type Version = u32;
const VERSION_FILE_NAME: &'static str = "parachain_db_version";
/// Current db version.
const CURRENT_VERSION: Version = 0;
const CURRENT_VERSION: Version = 1;
#[derive(thiserror::Error, Debug)]
pub enum Error {
@@ -56,6 +56,7 @@ pub fn try_upgrade_db(db_path: &Path) -> Result<(), Error> {
let is_empty = db_path.read_dir().map_or(true, |mut d| d.next().is_none());
if !is_empty {
match current_version(db_path)? {
0 => migrate_from_version_0_to_1(db_path)?,
CURRENT_VERSION => (),
v => return Err(Error::FutureVersion {
current: CURRENT_VERSION,
@@ -68,10 +69,10 @@ pub fn try_upgrade_db(db_path: &Path) -> Result<(), Error> {
}
/// Reads current database version from the file at given path.
/// If the file does not exist, assumes version 0.
/// If the file does not exist, assumes the current version.
fn current_version(path: &Path) -> Result<Version, Error> {
match fs::read_to_string(version_file_path(path)) {
Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(0),
Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(CURRENT_VERSION),
Err(err) => Err(err.into()),
Ok(content) => u32::from_str(&content).map_err(|_| Error::CorruptedVersionFile),
}
@@ -90,3 +91,20 @@ fn version_file_path(path: &Path) -> PathBuf {
file_path.push(VERSION_FILE_NAME);
file_path
}
/// Migration from version 0 to version 1:
/// * the number of columns has changed from 3 to 5;
fn migrate_from_version_0_to_1(path: &Path) -> Result<(), Error> {
use kvdb_rocksdb::{Database, DatabaseConfig};
let db_path = path.to_str()
.ok_or_else(|| super::other_io_error("Invalid database path".into()))?;
let db_cfg = DatabaseConfig::with_columns(super::columns::v0::NUM_COLUMNS);
let db = Database::open(&db_cfg, db_path)?;
db.add_column()?;
db.add_column()?;
Ok(())
}
@@ -41,7 +41,7 @@ use {
},
polkadot_subsystem::messages::{ApprovalVotingMessage, ChainSelectionMessage},
polkadot_node_subsystem_util::metrics::{self, prometheus},
polkadot_overseer::Handle,
polkadot_overseer::{Handle, OverseerHandle},
futures::channel::oneshot,
consensus_common::{Error as ConsensusError, SelectChain},
sp_blockchain::HeaderBackend,
@@ -125,7 +125,6 @@ impl<B> SelectRelayChain<B>
{
/// Create a new [`SelectRelayChain`] wrapping the given chain backend
/// and a handle to the overseer.
#[allow(unused)]
pub fn new(backend: Arc<B>, overseer: Handle, metrics: Metrics) -> Self {
SelectRelayChain {
fallback: sc_consensus::LongestChain::new(backend.clone()),
@@ -167,14 +166,13 @@ impl<B> SelectRelayChain<B>
}
impl<B> SelectRelayChain<B> {
/// Given an overseer handler, this connects the [`SelectRelayChain`]'s
/// internal handler to the same overseer.
#[allow(unused)]
pub fn connect_overseer_handler(
/// Given an overseer handle, connects the [`SelectRelayChain`]'s
/// internal handle and its clones to the same overseer.
pub fn connect_to_overseer(
&mut self,
other_handler: &Handle,
handle: OverseerHandle,
) {
other_handler.connect_other(&mut self.overseer);
self.overseer.connect_to_overseer(handle);
}
}