mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Support both polkadot and kusama runtimes (#704)
* Allow both polkadot and kusama runtimes * Allow both polkadot and kusama runtimes * Make `collator` build * Removed kusama runtime * Introduced common runtime * Updated for latest substrate * Updated CI targets * Updated CI version check * Removed unused dependency * Pulled latests substrate * Pulled latest substrate * Fixed version * Apply suggestions from code review Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * NEW_HEADS_IDENTIFIER moved to primitives * Updated CI check script * Fixed script * Set epoch duration for polkadot * ci: check_runtime for both runtimes Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: gabriel klawitter <gabreal@users.noreply.github.com>
This commit is contained in:
committed by
Gavin Wood
parent
9a9bbd1c2d
commit
a00d74d825
@@ -11,15 +11,15 @@ client = { package = "sc-client", git = "https://github.com/paritytech/substrate
|
||||
client-api = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
|
||||
polkadot-runtime = { path = "../runtime" }
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
polkadot-cli = { path = "../cli" }
|
||||
polkadot-network = { path = "../network" }
|
||||
polkadot-validation = { path = "../validation" }
|
||||
polkadot-service = { path = "../service" }
|
||||
log = "0.4.8"
|
||||
tokio = "0.2.1"
|
||||
tokio = "0.1.22"
|
||||
futures-timer = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
+173
-186
@@ -51,7 +51,7 @@ use std::time::Duration;
|
||||
use std::pin::Pin;
|
||||
|
||||
use futures::{future, Future, Stream, FutureExt, TryFutureExt, StreamExt, task::Spawn};
|
||||
use log::{warn, error};
|
||||
use log::warn;
|
||||
use client::BlockchainEvents;
|
||||
use primitives::{Pair, Blake2Hasher};
|
||||
use polkadot_primitives::{
|
||||
@@ -62,13 +62,12 @@ use polkadot_primitives::{
|
||||
}
|
||||
};
|
||||
use polkadot_cli::{
|
||||
Worker, IntoExit, ProvideRuntimeApi, AbstractService, CustomConfiguration, ParachainHost,
|
||||
ProvideRuntimeApi, AbstractService, ParachainHost, IsKusama, WrappedExecutor,
|
||||
service::{self, Roles, SelectChain}
|
||||
};
|
||||
use polkadot_network::validation::{LeafWorkParams, ValidationNetwork};
|
||||
use polkadot_network::PolkadotProtocol;
|
||||
use polkadot_runtime::RuntimeApi;
|
||||
|
||||
pub use polkadot_cli::VersionInfo;
|
||||
pub use polkadot_cli::{VersionInfo, load_spec, service::Configuration};
|
||||
pub use polkadot_network::validation::Incoming;
|
||||
pub use polkadot_validation::SignedStatement;
|
||||
pub use polkadot_primitives::parachain::CollatorId;
|
||||
@@ -129,7 +128,7 @@ impl<R: fmt::Display> fmt::Display for Error<R> {
|
||||
}
|
||||
|
||||
/// The Polkadot client type.
|
||||
pub type PolkadotClient<B, E> = client::Client<B, E, Block, RuntimeApi>;
|
||||
pub type PolkadotClient<B, E, R> = client::Client<B, E, Block, R>;
|
||||
|
||||
/// Something that can build a `ParachainContext`.
|
||||
pub trait BuildParachainContext {
|
||||
@@ -137,9 +136,9 @@ pub trait BuildParachainContext {
|
||||
type ParachainContext: self::ParachainContext;
|
||||
|
||||
/// Build the `ParachainContext`.
|
||||
fn build<B, E, SP>(
|
||||
fn build<B, E, R, SP>(
|
||||
self,
|
||||
client: Arc<PolkadotClient<B, E>>,
|
||||
client: Arc<PolkadotClient<B, E, R>>,
|
||||
spawner: SP,
|
||||
network: Arc<dyn Network>,
|
||||
) -> Result<Self::ParachainContext, ()>
|
||||
@@ -266,205 +265,179 @@ impl<P: 'static, E: 'static, SP: 'static> RelayChainContext for ApiContext<P, E,
|
||||
}
|
||||
}
|
||||
|
||||
struct CollationNode<P, E> {
|
||||
build_parachain_context: P,
|
||||
/// Run the collator node using the given `service`.
|
||||
fn run_collator_node<S, E, P>(
|
||||
service: S,
|
||||
exit: E,
|
||||
para_id: ParaId,
|
||||
key: Arc<CollatorPair>,
|
||||
}
|
||||
|
||||
impl<P, E> IntoExit for CollationNode<P, E> where
|
||||
E: futures::Future<Output=()> + Unpin + Send + 'static
|
||||
{
|
||||
type Exit = E;
|
||||
fn into_exit(self) -> Self::Exit {
|
||||
self.exit
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, E> Worker for CollationNode<P, E> where
|
||||
P: BuildParachainContext + Send + 'static,
|
||||
P::ParachainContext: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send + 'static,
|
||||
E: futures::Future<Output=()> + Clone + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
type Work = Box<dyn Future<Output=()> + Unpin + Send>;
|
||||
|
||||
fn configuration(&self) -> CustomConfiguration {
|
||||
let mut config = CustomConfiguration::default();
|
||||
config.collating_for = Some((
|
||||
self.key.public(),
|
||||
self.para_id,
|
||||
));
|
||||
config
|
||||
}
|
||||
|
||||
fn work<S, SC, B, CE, SP>(self, service: &S, spawner: SP) -> Self::Work
|
||||
build_parachain_context: P,
|
||||
) -> polkadot_cli::error::Result<()>
|
||||
where
|
||||
S: AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = RuntimeApi,
|
||||
Backend = B,
|
||||
SelectChain = SC,
|
||||
NetworkSpecialization = PolkadotProtocol,
|
||||
CallExecutor = CE,
|
||||
>,
|
||||
SC: polkadot_service::SelectChain<Block> + 'static,
|
||||
B: client_api::backend::Backend<Block, Blake2Hasher> + 'static,
|
||||
CE: client::CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync + 'static,
|
||||
SP: Spawn + Clone + Send + Sync + 'static,
|
||||
{
|
||||
let CollationNode { build_parachain_context, exit, para_id, key } = self;
|
||||
let client = service.client();
|
||||
let network = service.network();
|
||||
let known_oracle = client.clone();
|
||||
let select_chain = if let Some(select_chain) = service.select_chain() {
|
||||
select_chain
|
||||
} else {
|
||||
error!("The node cannot work because it can't select chain.");
|
||||
return Box::new(future::ready(()));
|
||||
};
|
||||
S: AbstractService<Block = service::Block, NetworkSpecialization = service::PolkadotProtocol>,
|
||||
client::Client<S::Backend, S::CallExecutor, service::Block, S::RuntimeApi>: ProvideRuntimeApi,
|
||||
<client::Client<S::Backend, S::CallExecutor, service::Block, S::RuntimeApi> as ProvideRuntimeApi>::Api:
|
||||
ParachainHost<service::Block, Error = sp_blockchain::Error>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::Backend: service::Backend<service::Block, service::Blake2Hasher>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::CallExecutor: service::CallExecutor<service::Block, service::Blake2Hasher>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::SelectChain: service::SelectChain<service::Block>,
|
||||
E: futures::Future<Output=()> + Clone + Unpin + Send + Sync + 'static,
|
||||
P: BuildParachainContext,
|
||||
P::ParachainContext: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send,
|
||||
{
|
||||
let runtime = tokio::runtime::Runtime::new().map_err(|e| format!("{:?}", e))?;
|
||||
let spawner = WrappedExecutor(service.spawn_task_handle());
|
||||
|
||||
let is_known = move |block_hash: &Hash| {
|
||||
use consensus_common::BlockStatus;
|
||||
use polkadot_network::gossip::Known;
|
||||
let client = service.client();
|
||||
let network = service.network();
|
||||
let known_oracle = client.clone();
|
||||
let select_chain = if let Some(select_chain) = service.select_chain() {
|
||||
select_chain
|
||||
} else {
|
||||
return Err(polkadot_cli::error::Error::Other("The node cannot work because it can't select chain.".into()))
|
||||
};
|
||||
|
||||
match known_oracle.block_status(&BlockId::hash(*block_hash)) {
|
||||
Err(_) | Ok(BlockStatus::Unknown) | Ok(BlockStatus::Queued) => None,
|
||||
Ok(BlockStatus::KnownBad) => Some(Known::Bad),
|
||||
Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) =>
|
||||
match select_chain.leaves() {
|
||||
Err(_) => None,
|
||||
Ok(leaves) => if leaves.contains(block_hash) {
|
||||
Some(Known::Leaf)
|
||||
} else {
|
||||
Some(Known::Old)
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
let is_known = move |block_hash: &Hash| {
|
||||
use consensus_common::BlockStatus;
|
||||
use polkadot_network::gossip::Known;
|
||||
|
||||
let message_validator = polkadot_network::gossip::register_validator(
|
||||
network.clone(),
|
||||
(is_known, client.clone()),
|
||||
&spawner
|
||||
);
|
||||
match known_oracle.block_status(&BlockId::hash(*block_hash)) {
|
||||
Err(_) | Ok(BlockStatus::Unknown) | Ok(BlockStatus::Queued) => None,
|
||||
Ok(BlockStatus::KnownBad) => Some(Known::Bad),
|
||||
Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) =>
|
||||
match select_chain.leaves() {
|
||||
Err(_) => None,
|
||||
Ok(leaves) => if leaves.contains(block_hash) {
|
||||
Some(Known::Leaf)
|
||||
} else {
|
||||
Some(Known::Old)
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let validation_network = Arc::new(ValidationNetwork::new(
|
||||
message_validator,
|
||||
exit.clone(),
|
||||
client.clone(),
|
||||
spawner.clone(),
|
||||
));
|
||||
let message_validator = polkadot_network::gossip::register_validator(
|
||||
network.clone(),
|
||||
(is_known, client.clone()),
|
||||
&spawner,
|
||||
);
|
||||
|
||||
let parachain_context = match build_parachain_context.build(
|
||||
client.clone(),
|
||||
spawner,
|
||||
validation_network.clone(),
|
||||
) {
|
||||
Ok(ctx) => ctx,
|
||||
Err(()) => {
|
||||
error!("Could not build the parachain context!");
|
||||
return Box::new(future::ready(()))
|
||||
}
|
||||
};
|
||||
let validation_network = Arc::new(ValidationNetwork::new(
|
||||
message_validator,
|
||||
exit.clone(),
|
||||
client.clone(),
|
||||
spawner.clone(),
|
||||
));
|
||||
|
||||
let inner_exit = exit.clone();
|
||||
let work = client.import_notification_stream()
|
||||
.for_each(move |notification| {
|
||||
macro_rules! try_fr {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(e) => return future::Either::Left(future::err(Error::Polkadot(
|
||||
format!("{:?}", e)
|
||||
))),
|
||||
}
|
||||
let parachain_context = match build_parachain_context.build(
|
||||
client.clone(),
|
||||
spawner,
|
||||
validation_network.clone(),
|
||||
) {
|
||||
Ok(ctx) => ctx,
|
||||
Err(()) => {
|
||||
return Err(polkadot_cli::error::Error::Other("Could not build the parachain context!".into()))
|
||||
}
|
||||
};
|
||||
|
||||
let inner_exit = exit.clone();
|
||||
let work = client.import_notification_stream()
|
||||
.for_each(move |notification| {
|
||||
macro_rules! try_fr {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(e) => return future::Either::Left(future::err(Error::Polkadot(
|
||||
format!("{:?}", e)
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let relay_parent = notification.hash;
|
||||
let id = BlockId::hash(relay_parent);
|
||||
let relay_parent = notification.hash;
|
||||
let id = BlockId::hash(relay_parent);
|
||||
|
||||
let network = network.clone();
|
||||
let client = client.clone();
|
||||
let key = key.clone();
|
||||
let parachain_context = parachain_context.clone();
|
||||
let validation_network = validation_network.clone();
|
||||
let inner_exit_2 = inner_exit.clone();
|
||||
let network = network.clone();
|
||||
let client = client.clone();
|
||||
let key = key.clone();
|
||||
let parachain_context = parachain_context.clone();
|
||||
let validation_network = validation_network.clone();
|
||||
let inner_exit_2 = inner_exit.clone();
|
||||
|
||||
let work = future::lazy(move |_| {
|
||||
let api = client.runtime_api();
|
||||
let status = match try_fr!(api.parachain_status(&id, para_id)) {
|
||||
Some(status) => status,
|
||||
None => return future::Either::Left(future::ok(())),
|
||||
};
|
||||
let work = future::lazy(move |_| {
|
||||
let api = client.runtime_api();
|
||||
let status = match try_fr!(api.parachain_status(&id, para_id)) {
|
||||
Some(status) => status,
|
||||
None => return future::Either::Left(future::ok(())),
|
||||
};
|
||||
|
||||
let validators = try_fr!(api.validators(&id));
|
||||
let validators = try_fr!(api.validators(&id));
|
||||
|
||||
let targets = compute_targets(
|
||||
para_id,
|
||||
validators.as_slice(),
|
||||
try_fr!(api.duty_roster(&id)),
|
||||
);
|
||||
|
||||
let context = ApiContext {
|
||||
network: validation_network,
|
||||
parent_hash: relay_parent,
|
||||
validators,
|
||||
};
|
||||
|
||||
let collation_work = collate(
|
||||
relay_parent,
|
||||
para_id,
|
||||
status,
|
||||
context,
|
||||
parachain_context,
|
||||
key,
|
||||
).map_ok(move |(collation, outgoing)| {
|
||||
network.with_spec(move |spec, ctx| {
|
||||
let res = spec.add_local_collation(
|
||||
ctx,
|
||||
relay_parent,
|
||||
targets,
|
||||
collation,
|
||||
outgoing,
|
||||
);
|
||||
|
||||
let exit = inner_exit_2.clone();
|
||||
tokio::spawn(future::select(res.boxed(), exit).map(drop));
|
||||
})
|
||||
});
|
||||
|
||||
future::Either::Right(collation_work)
|
||||
});
|
||||
|
||||
let deadlined = future::select(
|
||||
work,
|
||||
futures_timer::Delay::new(COLLATION_TIMEOUT)
|
||||
let targets = compute_targets(
|
||||
para_id,
|
||||
validators.as_slice(),
|
||||
try_fr!(api.duty_roster(&id)),
|
||||
);
|
||||
|
||||
let silenced = deadlined
|
||||
.map(|either| {
|
||||
if let future::Either::Right(_) = either {
|
||||
warn!("Collation failure: timeout");
|
||||
}
|
||||
});
|
||||
let context = ApiContext {
|
||||
network: validation_network,
|
||||
parent_hash: relay_parent,
|
||||
validators,
|
||||
};
|
||||
|
||||
let collation_work = collate(
|
||||
relay_parent,
|
||||
para_id,
|
||||
status,
|
||||
context,
|
||||
parachain_context,
|
||||
key,
|
||||
).map_ok(move |(collation, outgoing)| {
|
||||
network.with_spec(move |spec, ctx| {
|
||||
let res = spec.add_local_collation(
|
||||
ctx,
|
||||
relay_parent,
|
||||
targets,
|
||||
collation,
|
||||
outgoing,
|
||||
);
|
||||
|
||||
let exit = inner_exit_2.clone();
|
||||
tokio::spawn(future::select(res.boxed(), exit).map(drop).map(|_| Ok(())).compat());
|
||||
})
|
||||
});
|
||||
|
||||
future::Either::Right(collation_work)
|
||||
});
|
||||
|
||||
let deadlined = future::select(
|
||||
work,
|
||||
futures_timer::Delay::new(COLLATION_TIMEOUT)
|
||||
);
|
||||
|
||||
let silenced = deadlined
|
||||
.map(|either| {
|
||||
if let future::Either::Right(_) = either {
|
||||
warn!("Collation failure: timeout");
|
||||
}
|
||||
});
|
||||
|
||||
let future = future::select(
|
||||
silenced,
|
||||
inner_exit.clone()
|
||||
).map(drop);
|
||||
|
||||
tokio::spawn(future);
|
||||
future::ready(())
|
||||
});
|
||||
tokio::spawn(future.map(|_| Ok(())).compat());
|
||||
future::ready(())
|
||||
});
|
||||
|
||||
let work_and_exit = future::select(work, exit)
|
||||
.map(|_| ());
|
||||
service.spawn_essential_task(work.map(|_| Ok::<_, ()>(())).compat());
|
||||
|
||||
Box::new(work_and_exit)
|
||||
}
|
||||
polkadot_cli::run_until_exit(runtime, service, exit)
|
||||
}
|
||||
|
||||
fn compute_targets(para_id: ParaId, session_keys: &[ValidatorId], roster: DutyRoster) -> HashSet<ValidatorId> {
|
||||
@@ -477,6 +450,11 @@ fn compute_targets(para_id: ParaId, session_keys: &[ValidatorId], roster: DutyRo
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Set the `collating_for` parameter of the configuration.
|
||||
fn prepare_config(config: &mut Configuration, para_id: ParaId, key: &Arc<CollatorPair>) {
|
||||
config.custom.collating_for = Some((key.public(), para_id));
|
||||
}
|
||||
|
||||
/// Run a collator node with the given `RelayChainContext` and `ParachainContext`
|
||||
/// build by the given `BuildParachainContext` and arguments to the underlying polkadot node.
|
||||
///
|
||||
@@ -487,15 +465,25 @@ pub fn run_collator<P, E>(
|
||||
para_id: ParaId,
|
||||
exit: E,
|
||||
key: Arc<CollatorPair>,
|
||||
version: VersionInfo,
|
||||
mut config: Configuration,
|
||||
) -> polkadot_cli::error::Result<()> where
|
||||
P: BuildParachainContext + Send + 'static,
|
||||
P: BuildParachainContext,
|
||||
P::ParachainContext: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send,
|
||||
E: futures::Future<Output = ()> + Unpin + Send + Clone + Sync + 'static,
|
||||
{
|
||||
let node_logic = CollationNode { build_parachain_context, exit, para_id, key };
|
||||
polkadot_cli::run(node_logic, version)
|
||||
prepare_config(&mut config, para_id, &key);
|
||||
|
||||
match (config.is_kusama(), config.roles) {
|
||||
(true, Roles::LIGHT) =>
|
||||
run_collator_node(service::kusama_new_light(config)?, exit, para_id, key, build_parachain_context),
|
||||
(true, _) =>
|
||||
run_collator_node(service::kusama_new_full(config)?, exit, para_id, key, build_parachain_context),
|
||||
(false, Roles::LIGHT) =>
|
||||
run_collator_node(service::polkadot_new_light(config)?, exit, para_id, key, build_parachain_context),
|
||||
(false, _) =>
|
||||
run_collator_node(service::polkadot_new_full(config)?, exit, para_id, key, build_parachain_context),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -601,4 +589,3 @@ mod tests {
|
||||
assert_eq!(collation.info.egress_queue_roots, vec![(a, root_a), (b, root_b)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user