mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-10 04:07:59 +00:00
Drop sc-client (#1037)
* WIP * collator * fix missing reference * Make collator builder more generic * all clear * revert start colator fn * fix return type of start_collator * sc-consensus * bump back to master * Update collator/src/lib.rs Co-Authored-By: Benjamin Kampmann <ben@gnunicorn.org> * Update collator/src/lib.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * uncomment type MaxIterations * reactivate append storage feature Co-authored-by: Benjamin Kampmann <ben@gnunicorn.org> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
This commit is contained in:
Generated
+166
-185
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@ codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
client = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -20,7 +20,6 @@ structopt = "0.3.8"
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-db = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
+50
-70
@@ -15,9 +15,8 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use log::info;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use service::{IdentifyVariant, Block, self, RuntimeApiCollection, TFullClient};
|
||||
use sp_api::ConstructRuntimeApi;
|
||||
use service::{IdentifyVariant, self};
|
||||
use sc_executor::NativeExecutionDispatch;
|
||||
use sc_cli::{SubstrateCli, Result};
|
||||
use crate::cli::{Cli, Subcommand};
|
||||
|
||||
@@ -82,23 +81,56 @@ pub fn run() -> Result<()> {
|
||||
info!(" KUSAMA FOUNDATION ");
|
||||
info!("----------------------------");
|
||||
|
||||
run_node::<
|
||||
service::kusama_runtime::RuntimeApi,
|
||||
service::KusamaExecutor,
|
||||
service::kusama_runtime::UncheckedExtrinsic,
|
||||
>(runtime, authority_discovery_enabled, grandpa_pause)
|
||||
runtime.run_node(
|
||||
|config| {
|
||||
service::kusama_new_light(config)
|
||||
},
|
||||
|config| {
|
||||
service::kusama_new_full(
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
authority_discovery_enabled,
|
||||
6000,
|
||||
grandpa_pause
|
||||
).map(|(s, _, _)| s)
|
||||
},
|
||||
service::KusamaExecutor::native_version().runtime_version
|
||||
)
|
||||
} else if config.chain_spec.is_westend() {
|
||||
run_node::<
|
||||
service::westend_runtime::RuntimeApi,
|
||||
service::WestendExecutor,
|
||||
service::westend_runtime::UncheckedExtrinsic,
|
||||
>(runtime, authority_discovery_enabled, grandpa_pause)
|
||||
runtime.run_node(
|
||||
|config| {
|
||||
service::westend_new_light(config)
|
||||
},
|
||||
|config| {
|
||||
service::westend_new_full(
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
authority_discovery_enabled,
|
||||
6000,
|
||||
grandpa_pause
|
||||
).map(|(s, _, _)| s)
|
||||
},
|
||||
service::WestendExecutor::native_version().runtime_version
|
||||
)
|
||||
} else {
|
||||
run_node::<
|
||||
service::polkadot_runtime::RuntimeApi,
|
||||
service::PolkadotExecutor,
|
||||
service::polkadot_runtime::UncheckedExtrinsic,
|
||||
>(runtime, authority_discovery_enabled, grandpa_pause)
|
||||
runtime.run_node(
|
||||
|config| {
|
||||
service::polkadot_new_light(config)
|
||||
},
|
||||
|config| {
|
||||
service::polkadot_new_full(
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
authority_discovery_enabled,
|
||||
6000,
|
||||
grandpa_pause
|
||||
).map(|(s, _, _)| s)
|
||||
},
|
||||
service::PolkadotExecutor::native_version().runtime_version
|
||||
)
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Base(subcommand)) => {
|
||||
@@ -160,55 +192,3 @@ pub fn run() -> Result<()> {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn run_node<R, D, E>(
|
||||
runtime: sc_cli::Runner<Cli>,
|
||||
authority_discovery_enabled: bool,
|
||||
grandpa_pause: Option<(u32, u32)>,
|
||||
) -> sc_cli::Result<()>
|
||||
where
|
||||
R: ConstructRuntimeApi<Block, service::TFullClient<Block, R, D>>
|
||||
+ Send + Sync + 'static,
|
||||
<R as ConstructRuntimeApi<Block, service::TFullClient<Block, R, D>>>::RuntimeApi:
|
||||
RuntimeApiCollection<E, StateBackend = sc_client_api::StateBackendFor<service::TFullBackend<Block>, Block>>,
|
||||
<R as ConstructRuntimeApi<Block, service::TLightClient<Block, R, D>>>::RuntimeApi:
|
||||
RuntimeApiCollection<E, StateBackend = sc_client_api::StateBackendFor<service::TLightBackend<Block>, Block>>,
|
||||
E: service::Codec + Send + Sync + 'static,
|
||||
D: service::NativeExecutionDispatch + 'static,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
<<R as ConstructRuntimeApi<Block, TFullClient<Block, R, D>>>::RuntimeApi as sp_api::ApiExt<Block>>::StateBackend:
|
||||
sp_api::StateBackend<BlakeTwo256>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/43580
|
||||
R: ConstructRuntimeApi<
|
||||
Block,
|
||||
TLightClient<R, D>
|
||||
>,
|
||||
{
|
||||
runtime.run_node(
|
||||
|config| service::new_light::<R, D, E>(config),
|
||||
|config| service::new_full::<R, D, E>(
|
||||
config,
|
||||
None,
|
||||
None,
|
||||
authority_discovery_enabled,
|
||||
6000,
|
||||
grandpa_pause,
|
||||
).map(|(s, _)| s),
|
||||
D::native_version().runtime_version,
|
||||
)
|
||||
}
|
||||
|
||||
// We can't simply use `service::TLightClient` due to a
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/43580
|
||||
type TLightClient<Runtime, Dispatch> = sc_client::Client<
|
||||
sc_client::light::backend::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>,
|
||||
sc_client::light::call_executor::GenesisCallExecutor<
|
||||
sc_client::light::backend::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>,
|
||||
sc_client::LocalCallExecutor<
|
||||
sc_client::light::backend::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>,
|
||||
sc_executor::NativeExecutor<Dispatch>
|
||||
>
|
||||
>,
|
||||
Block,
|
||||
Runtime
|
||||
>;
|
||||
|
||||
@@ -7,7 +7,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.4"
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -52,9 +52,8 @@ use std::pin::Pin;
|
||||
|
||||
use futures::{future, Future, Stream, FutureExt, TryFutureExt, StreamExt, task::Spawn};
|
||||
use log::warn;
|
||||
use sc_client::BlockchainEvents;
|
||||
use sc_client_api::StateBackend;
|
||||
use sp_core::Pair;
|
||||
use sp_runtime::traits::BlakeTwo256;
|
||||
use polkadot_primitives::{
|
||||
BlockId, Hash, Block,
|
||||
parachain::{
|
||||
@@ -72,7 +71,9 @@ pub use polkadot_validation::SignedStatement;
|
||||
pub use polkadot_primitives::parachain::CollatorId;
|
||||
pub use sc_network::PeerId;
|
||||
pub use service::RuntimeApiCollection;
|
||||
use sc_service::ClientProvider;
|
||||
pub use sc_cli::SubstrateCli;
|
||||
use sp_api::{ConstructRuntimeApi, ApiExt, HashFor};
|
||||
|
||||
const COLLATION_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
@@ -114,34 +115,24 @@ impl fmt::Display for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// The Polkadot client type.
|
||||
pub type PolkadotClient<B, E, R> = sc_client::Client<B, E, Block, R>;
|
||||
|
||||
/// Something that can build a `ParachainContext`.
|
||||
pub trait BuildParachainContext {
|
||||
/// The parachain context produced by the `build` function.
|
||||
type ParachainContext: self::ParachainContext;
|
||||
|
||||
/// Build the `ParachainContext`.
|
||||
fn build<B, E, R, SP, Extrinsic>(
|
||||
fn build<Client, SP, Extrinsic>(
|
||||
self,
|
||||
client: Arc<PolkadotClient<B, E, R>>,
|
||||
client: Arc<Client>,
|
||||
spawner: SP,
|
||||
network: impl Network + Clone + 'static,
|
||||
) -> Result<Self::ParachainContext, ()>
|
||||
where
|
||||
PolkadotClient<B, E, R>: ProvideRuntimeApi<Block>,
|
||||
<PolkadotClient<B, E, R> as ProvideRuntimeApi<Block>>::Api: RuntimeApiCollection<Extrinsic>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
<<PolkadotClient<B, E, R> as ProvideRuntimeApi<Block>>::Api as sp_api::ApiExt<Block>>::StateBackend:
|
||||
sp_api::StateBackend<BlakeTwo256>,
|
||||
Client: ProvideRuntimeApi<Block>,
|
||||
Client::Api: RuntimeApiCollection<Extrinsic>,
|
||||
<Client::Api as ApiExt<Block>>::StateBackend: StateBackend<HashFor<Block>>,
|
||||
Extrinsic: codec::Codec + Send + Sync + 'static,
|
||||
E: sc_client::CallExecutor<Block> + Clone + Send + Sync + 'static,
|
||||
SP: Spawn + Clone + Send + Sync + 'static,
|
||||
R: Send + Sync + 'static,
|
||||
B: sc_client_api::Backend<Block> + 'static,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
B::State: sp_api::StateBackend<BlakeTwo256>;
|
||||
SP: Spawn + Clone + Send + Sync + 'static;
|
||||
}
|
||||
|
||||
/// Parachain context needed for collation.
|
||||
@@ -209,38 +200,40 @@ pub async fn collate<P>(
|
||||
Ok(collation)
|
||||
}
|
||||
|
||||
fn build_collator_service<S, P, Extrinsic>(
|
||||
service: (S, polkadot_service::FullNodeHandles),
|
||||
|
||||
fn build_collator_service<SP, P, C, E, R, Extrinsic>(
|
||||
spawner: SP,
|
||||
handles: polkadot_service::FullNodeHandles,
|
||||
client: Arc<C>,
|
||||
para_id: ParaId,
|
||||
key: Arc<CollatorPair>,
|
||||
build_parachain_context: P,
|
||||
) -> Result<S, polkadot_service::Error>
|
||||
) -> Result<impl Future<Output = ()> + Send + 'static, polkadot_service::Error>
|
||||
where
|
||||
S: AbstractService<Block = service::Block>,
|
||||
sc_client::Client<S::Backend, S::CallExecutor, service::Block, S::RuntimeApi>: ProvideRuntimeApi<Block>,
|
||||
<sc_client::Client<S::Backend, S::CallExecutor, service::Block, S::RuntimeApi> as ProvideRuntimeApi<Block>>::Api:
|
||||
RuntimeApiCollection<
|
||||
C: ClientProvider<
|
||||
service::Block,
|
||||
service::TFullBackend<service::Block>,
|
||||
service::TFullCallExecutor<service::Block, E>,
|
||||
R
|
||||
> + 'static,
|
||||
R: ConstructRuntimeApi<service::Block, C> + Sync + Send,
|
||||
<R as ConstructRuntimeApi<service::Block, C>>::RuntimeApi:
|
||||
sp_api::ApiExt<
|
||||
service::Block,
|
||||
StateBackend = <service::TFullBackend<service::Block> as service::Backend<service::Block>>::State,
|
||||
>
|
||||
+ RuntimeApiCollection<
|
||||
Extrinsic,
|
||||
Error = sp_blockchain::Error,
|
||||
StateBackend = sc_client_api::StateBackendFor<S::Backend, Block>
|
||||
>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::Backend: service::Backend<service::Block>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
<S::Backend as service::Backend<service::Block>>::State:
|
||||
sp_api::StateBackend<sp_runtime::traits::HashFor<Block>>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::CallExecutor: service::CallExecutor<service::Block>,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
S::SelectChain: service::SelectChain<service::Block>,
|
||||
StateBackend = <service::TFullBackend<service::Block> as service::Backend<service::Block>>::State,
|
||||
>
|
||||
+ Sync + Send,
|
||||
E: sc_executor::NativeExecutionDispatch + 'static,
|
||||
P: BuildParachainContext,
|
||||
P::ParachainContext: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send,
|
||||
Extrinsic: service::Codec + Send + Sync + 'static,
|
||||
SP: Spawn + Clone + Send + Sync + 'static,
|
||||
{
|
||||
let (service, handles) = service;
|
||||
let spawner = service.spawn_task_handle();
|
||||
|
||||
let polkadot_network = handles.polkadot_network
|
||||
.ok_or_else(|| "Collator cannot run when Polkadot-specific networking has not been started")?;
|
||||
|
||||
@@ -250,8 +243,6 @@ fn build_collator_service<S, P, Extrinsic>(
|
||||
handles.validation_service_handle
|
||||
.ok_or_else(|| "Collator cannot run when validation networking has not been started")?;
|
||||
|
||||
let client = service.client();
|
||||
|
||||
let parachain_context = match build_parachain_context.build(
|
||||
client.clone(),
|
||||
spawner,
|
||||
@@ -334,9 +325,7 @@ fn build_collator_service<S, P, Extrinsic>(
|
||||
}
|
||||
}.boxed();
|
||||
|
||||
service.spawn_essential_task("collation", work);
|
||||
|
||||
Ok(service)
|
||||
Ok(work)
|
||||
}
|
||||
|
||||
/// Async function that will run the collator node with the given `RelayChainContext` and `ParachainContext`
|
||||
@@ -348,29 +337,55 @@ pub async fn start_collator<P>(
|
||||
config: Configuration,
|
||||
) -> Result<(), polkadot_service::Error>
|
||||
where
|
||||
P: BuildParachainContext,
|
||||
P: 'static + BuildParachainContext,
|
||||
P::ParachainContext: Send + 'static,
|
||||
<P::ParachainContext as ParachainContext>::ProduceCandidate: Send,
|
||||
{
|
||||
let is_kusama = config.chain_spec.is_kusama();
|
||||
match (is_kusama, &config.role) {
|
||||
(_, Role::Light) => return Err(
|
||||
(_, Role::Light) => Err(
|
||||
polkadot_service::Error::Other("light nodes are unsupported as collator".into())
|
||||
).into(),
|
||||
(true, _) =>
|
||||
(true, _) => {
|
||||
let (service, client, handlers) = service::kusama_new_full(
|
||||
config,
|
||||
Some((key.public(), para_id)),
|
||||
None,
|
||||
false,
|
||||
6000,
|
||||
None
|
||||
)?;
|
||||
let spawn_handle = service.spawn_task_handle();
|
||||
build_collator_service(
|
||||
service::kusama_new_full(config, Some((key.public(), para_id)), None, false, 6000, None)?,
|
||||
spawn_handle,
|
||||
handlers,
|
||||
client,
|
||||
para_id,
|
||||
key,
|
||||
build_parachain_context
|
||||
)?.await;
|
||||
Ok(())
|
||||
},
|
||||
(false, _) => {
|
||||
let (service, client, handles) = service::polkadot_new_full(
|
||||
config,
|
||||
Some((key.public(), para_id)),
|
||||
None,
|
||||
false,
|
||||
6000,
|
||||
None
|
||||
)?;
|
||||
let spawn_handle = service.spawn_task_handle();
|
||||
build_collator_service(
|
||||
spawn_handle,
|
||||
handles,
|
||||
client,
|
||||
para_id,
|
||||
key,
|
||||
build_parachain_context,
|
||||
)?.await,
|
||||
(false, _) =>
|
||||
build_collator_service(
|
||||
service::polkadot_new_full(config, Some((key.public(), para_id)), None, false, 6000, None)?,
|
||||
para_id,
|
||||
key,
|
||||
build_parachain_context,
|
||||
)?.await,
|
||||
)?.await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,9 +428,9 @@ mod tests {
|
||||
impl BuildParachainContext for BuildDummyParachainContext {
|
||||
type ParachainContext = DummyParachainContext;
|
||||
|
||||
fn build<B, E, R, SP, Extrinsic>(
|
||||
fn build<C, SP, Extrinsic>(
|
||||
self,
|
||||
_: Arc<PolkadotClient<B, E, R>>,
|
||||
_: Arc<C>,
|
||||
_: SP,
|
||||
_: impl Network + Clone + 'static,
|
||||
) -> Result<Self::ParachainContext, ()> {
|
||||
|
||||
@@ -23,7 +23,6 @@ futures = "0.3.4"
|
||||
log = "0.4.8"
|
||||
exit-future = "0.2.0"
|
||||
futures-timer = "2.0"
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
wasm-timer = "0.2.4"
|
||||
|
||||
@@ -10,10 +10,11 @@ log = "0.4.8"
|
||||
parking_lot = "0.10.0"
|
||||
futures = "0.3.1"
|
||||
rand = "0.7.2"
|
||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-service = { git = "https://github.com/paritytech/substrate", features = ["test-helpers"], branch = "master" }
|
||||
sc-network-test = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -34,8 +34,8 @@ use sc_client_api::{
|
||||
client::BlockBackend,
|
||||
backend::{TransactionFor, AuxStore, Backend, Finalizer},
|
||||
};
|
||||
use sc_consensus::LongestChain;
|
||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||
use sc_client::LongestChain;
|
||||
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
|
||||
use sp_consensus::import_queue::{
|
||||
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
|
||||
@@ -53,14 +53,23 @@ use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
use sp_runtime::Justification;
|
||||
pub use sc_network_test::PassThroughVerifier;
|
||||
use sc_service::client::Client;
|
||||
|
||||
pub use polkadot_test_runtime_client::runtime::{Block, Extrinsic, Hash};
|
||||
pub use polkadot_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt};
|
||||
|
||||
pub type PeersFullClient =
|
||||
sc_client::Client<polkadot_test_runtime_client::Backend, polkadot_test_runtime_client::Executor, Block, polkadot_test_runtime_client::runtime::RuntimeApi>;
|
||||
pub type PeersLightClient =
|
||||
sc_client::Client<polkadot_test_runtime_client::LightBackend, polkadot_test_runtime_client::LightExecutor, Block, polkadot_test_runtime_client::runtime::RuntimeApi>;
|
||||
pub type PeersFullClient = Client<
|
||||
polkadot_test_runtime_client::Backend,
|
||||
polkadot_test_runtime_client::Executor,
|
||||
Block,
|
||||
polkadot_test_runtime_client::runtime::RuntimeApi
|
||||
>;
|
||||
pub type PeersLightClient = Client<
|
||||
polkadot_test_runtime_client::LightBackend,
|
||||
polkadot_test_runtime_client::LightExecutor,
|
||||
Block,
|
||||
polkadot_test_runtime_client::runtime::RuntimeApi
|
||||
>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum PeersClient {
|
||||
|
||||
@@ -10,7 +10,6 @@ parachain = { package = "polkadot-parachain", path = "../../.." }
|
||||
collator = { package = "polkadot-collator", path = "../../../../collator" }
|
||||
primitives = { package = "polkadot-primitives", path = "../../../../primitives" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
client = { package = "sc-client", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
client-api = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
parking_lot = "0.10.0"
|
||||
codec = { package = "parity-scale-codec", version = "1.2.0" }
|
||||
|
||||
@@ -101,9 +101,9 @@ impl ParachainContext for AdderContext {
|
||||
impl BuildParachainContext for AdderContext {
|
||||
type ParachainContext = Self;
|
||||
|
||||
fn build<B, E, R, SP, Extrinsic>(
|
||||
fn build<Client, SP, Extrinsic>(
|
||||
self,
|
||||
_: Arc<collator::PolkadotClient<B, E, R>>,
|
||||
_: Arc<Client>,
|
||||
_: SP,
|
||||
network: impl Network + Clone + 'static,
|
||||
) -> Result<Self::ParachainContext, ()> {
|
||||
|
||||
@@ -5,9 +5,10 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
client = { package = "sc-client", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
jsonrpc-core = "14.0.3"
|
||||
polkadot-primitives = { path = "../primitives" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -23,6 +23,8 @@ use std::sync::Arc;
|
||||
use polkadot_primitives::{Block, AccountId, Nonce, Balance};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use txpool_api::TransactionPool;
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sc_client_api::light::{Fetcher, RemoteBlockchain};
|
||||
|
||||
/// A type representing all RPC extensions.
|
||||
pub type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
|
||||
@@ -30,7 +32,7 @@ pub type RpcExtension = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
|
||||
/// Instantiate all RPC extensions.
|
||||
pub fn create_full<C, P, UE>(client: Arc<C>, pool: Arc<P>) -> RpcExtension where
|
||||
C: ProvideRuntimeApi<Block>,
|
||||
C: client::blockchain::HeaderBackend<Block>,
|
||||
C: HeaderBackend<Block>,
|
||||
C: Send + Sync + 'static,
|
||||
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
|
||||
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance, UE>,
|
||||
@@ -53,18 +55,18 @@ pub fn create_full<C, P, UE>(client: Arc<C>, pool: Arc<P>) -> RpcExtension where
|
||||
/// Instantiate all RPC extensions for light node.
|
||||
pub fn create_light<C, P, F, UE>(
|
||||
client: Arc<C>,
|
||||
remote_blockchain: Arc<dyn client::light::blockchain::RemoteBlockchain<Block>>,
|
||||
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
|
||||
fetcher: Arc<F>,
|
||||
pool: Arc<P>,
|
||||
) -> RpcExtension
|
||||
where
|
||||
C: ProvideRuntimeApi<Block>,
|
||||
C: client::blockchain::HeaderBackend<Block>,
|
||||
C: HeaderBackend<Block>,
|
||||
C: Send + Sync + 'static,
|
||||
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
|
||||
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance, UE>,
|
||||
P: TransactionPool + Sync + Send + 'static,
|
||||
F: client::light::fetcher::Fetcher<Block> + 'static,
|
||||
F: Fetcher<Block> + 'static,
|
||||
UE: codec::Codec + Send + Sync + 'static,
|
||||
{
|
||||
use frame_rpc_system::{LightSystem, SystemApi};
|
||||
|
||||
@@ -7,6 +7,8 @@ license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["test-helpers"], default-features = false }
|
||||
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
polkadot-test-runtime = { path = ".." }
|
||||
@@ -17,6 +19,5 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
futures = "0.3.1"
|
||||
|
||||
@@ -22,16 +22,19 @@ use std::sync::Arc;
|
||||
use std::collections::BTreeMap;
|
||||
pub use substrate_test_client::*;
|
||||
pub use polkadot_test_runtime as runtime;
|
||||
pub use sc_client::LongestChain;
|
||||
|
||||
use sp_core::{sr25519, ChangesTrieConfiguration, map, twox_128};
|
||||
use sp_core::storage::{ChildInfo, Storage, StorageChild};
|
||||
use polkadot_test_runtime::genesismap::GenesisConfig;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, HashFor};
|
||||
use sc_client::{
|
||||
light::fetcher::{
|
||||
RemoteCallRequest, RemoteBodyRequest,
|
||||
use sc_consensus::LongestChain;
|
||||
use sc_client_api::light::{RemoteCallRequest, RemoteBodyRequest};
|
||||
use sc_service::client::{
|
||||
light::{
|
||||
call_executor::GenesisCallExecutor, backend as light_backend,
|
||||
new_light_blockchain, new_light_backend,
|
||||
},
|
||||
genesis, Client as SubstrateClient, LocalCallExecutor
|
||||
};
|
||||
|
||||
/// A prelude to import in tests.
|
||||
@@ -57,7 +60,7 @@ sc_executor::native_executor_instance! {
|
||||
pub type Backend = substrate_test_client::Backend<polkadot_test_runtime::Block>;
|
||||
|
||||
/// Test client executor.
|
||||
pub type Executor = sc_client::LocalCallExecutor<
|
||||
pub type Executor = LocalCallExecutor<
|
||||
Backend,
|
||||
NativeExecutor<LocalExecutor>,
|
||||
>;
|
||||
@@ -66,10 +69,10 @@ pub type Executor = sc_client::LocalCallExecutor<
|
||||
pub type LightBackend = substrate_test_client::LightBackend<polkadot_test_runtime::Block>;
|
||||
|
||||
/// Test client light executor.
|
||||
pub type LightExecutor = sc_client::light::call_executor::GenesisCallExecutor<
|
||||
pub type LightExecutor = GenesisCallExecutor<
|
||||
LightBackend,
|
||||
sc_client::LocalCallExecutor<
|
||||
sc_client::light::backend::Backend<
|
||||
LocalCallExecutor<
|
||||
light_backend::Backend<
|
||||
sc_client_db::light::LightStorage<polkadot_test_runtime::Block>,
|
||||
HashFor<polkadot_test_runtime::Block>
|
||||
>,
|
||||
@@ -120,7 +123,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters {
|
||||
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
storage.top.clone().into_iter().chain(child_roots).collect()
|
||||
);
|
||||
let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root);
|
||||
let block: runtime::Block = genesis::construct_genesis_block(state_root);
|
||||
storage.top.extend(additional_storage_with_genesis(&block));
|
||||
|
||||
storage
|
||||
@@ -136,9 +139,9 @@ pub type TestClientBuilder<E, B> = substrate_test_client::TestClientBuilder<
|
||||
>;
|
||||
|
||||
/// Test client type with `LocalExecutor` and generic Backend.
|
||||
pub type Client<B> = sc_client::Client<
|
||||
pub type Client<B> = SubstrateClient<
|
||||
B,
|
||||
sc_client::LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
LocalCallExecutor<B, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
polkadot_test_runtime::Block,
|
||||
polkadot_test_runtime::RuntimeApi,
|
||||
>;
|
||||
@@ -212,21 +215,21 @@ pub trait TestClientBuilderExt<B>: Sized {
|
||||
}
|
||||
|
||||
/// Build the test client and longest chain selector.
|
||||
fn build_with_longest_chain(self) -> (Client<B>, sc_client::LongestChain<B, polkadot_test_runtime::Block>);
|
||||
fn build_with_longest_chain(self) -> (Client<B>, LongestChain<B, polkadot_test_runtime::Block>);
|
||||
|
||||
/// Build the test client and the backend.
|
||||
fn build_with_backend(self) -> (Client<B>, Arc<B>);
|
||||
}
|
||||
|
||||
impl TestClientBuilderExt<Backend> for TestClientBuilder<
|
||||
sc_client::LocalCallExecutor<Backend, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
LocalCallExecutor<Backend, sc_executor::NativeExecutor<LocalExecutor>>,
|
||||
Backend
|
||||
> {
|
||||
fn genesis_init_mut(&mut self) -> &mut GenesisParameters {
|
||||
Self::genesis_init_mut(self)
|
||||
}
|
||||
|
||||
fn build_with_longest_chain(self) -> (Client<Backend>, sc_client::LongestChain<Backend, polkadot_test_runtime::Block>) {
|
||||
fn build_with_longest_chain(self) -> (Client<Backend>, LongestChain<Backend, polkadot_test_runtime::Block>) {
|
||||
self.build_with_native_executor(None)
|
||||
}
|
||||
|
||||
@@ -277,15 +280,25 @@ pub fn new() -> Client<Backend> {
|
||||
|
||||
/// Creates new light client instance used for tests.
|
||||
pub fn new_light() -> (
|
||||
sc_client::Client<LightBackend, LightExecutor, polkadot_test_runtime::Block, polkadot_test_runtime::RuntimeApi>,
|
||||
SubstrateClient<
|
||||
LightBackend,
|
||||
LightExecutor,
|
||||
polkadot_test_runtime::Block,
|
||||
polkadot_test_runtime::RuntimeApi
|
||||
>,
|
||||
Arc<LightBackend>,
|
||||
) {
|
||||
|
||||
let storage = sc_client_db::light::LightStorage::new_test();
|
||||
let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage));
|
||||
let backend = Arc::new(LightBackend::new(blockchain.clone()));
|
||||
let blockchain =new_light_blockchain(storage);
|
||||
let backend = new_light_backend(blockchain.clone());
|
||||
let executor = new_native_executor();
|
||||
let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default(),);
|
||||
let local_call_executor = LocalCallExecutor::new(
|
||||
backend.clone(),
|
||||
executor,
|
||||
sp_core::tasks::executor(),
|
||||
Default::default()
|
||||
);
|
||||
let call_executor = LightExecutor::new(
|
||||
backend.clone(),
|
||||
local_call_executor,
|
||||
|
||||
@@ -25,11 +25,11 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-client-db = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
@@ -37,6 +37,7 @@ grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.co
|
||||
inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
service = { package = "sc-service", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
telemetry = { package = "sc-telemetry", git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -48,9 +48,9 @@ const DEFAULT_PROTOCOL_ID: &str = "dot";
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Extensions {
|
||||
/// Block numbers with known hashes.
|
||||
pub fork_blocks: sc_client::ForkBlocks<polkadot_primitives::Block>,
|
||||
pub fork_blocks: sc_client_api::ForkBlocks<polkadot_primitives::Block>,
|
||||
/// Known bad block hashes.
|
||||
pub bad_blocks: sc_client::BadBlocks<polkadot_primitives::Block>,
|
||||
pub bad_blocks: sc_client_api::BadBlocks<polkadot_primitives::Block>,
|
||||
}
|
||||
|
||||
/// The `ChainSpec parametrised for polkadot runtime`.
|
||||
|
||||
+408
-456
@@ -19,7 +19,6 @@
|
||||
pub mod chain_spec;
|
||||
mod grandpa_support;
|
||||
|
||||
use sc_client::LongestChain;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use polkadot_primitives::{parachain, Hash, BlockId, AccountId, Nonce, Balance};
|
||||
@@ -27,21 +26,20 @@ use polkadot_primitives::{parachain, Hash, BlockId, AccountId, Nonce, Balance};
|
||||
use polkadot_network::{legacy::gossip::Known, protocol as network_protocol};
|
||||
use service::{error::Error as ServiceError, ServiceBuilder};
|
||||
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
|
||||
use inherents::InherentDataProviders;
|
||||
use sc_executor::native_executor_instance;
|
||||
use log::info;
|
||||
pub use service::{
|
||||
AbstractService, Role, PruningMode, TransactionPoolOptions, Error, RuntimeGenesis,
|
||||
TFullClient, TLightClient, TFullBackend, TLightBackend, TFullCallExecutor, TLightCallExecutor,
|
||||
Configuration, ChainSpec, ServiceBuilderCommand,
|
||||
Configuration, ChainSpec, ServiceBuilderCommand, ClientProvider,
|
||||
};
|
||||
pub use service::config::{DatabaseConfig, PrometheusConfig};
|
||||
pub use sc_executor::NativeExecutionDispatch;
|
||||
pub use sc_client::{ExecutionStrategy, CallExecutor, Client};
|
||||
pub use sc_client_api::backend::Backend;
|
||||
pub use sc_client_api::{Backend, ExecutionStrategy, CallExecutor};
|
||||
pub use sc_consensus::LongestChain;
|
||||
pub use sp_api::{Core as CoreApi, ConstructRuntimeApi, ProvideRuntimeApi, StateBackend};
|
||||
pub use sp_runtime::traits::{HashFor, NumberFor};
|
||||
pub use consensus_common::SelectChain;
|
||||
pub use consensus_common::{SelectChain, BlockImport, block_validation::Chain};
|
||||
pub use polkadot_primitives::parachain::{CollatorId, ParachainHost};
|
||||
pub use polkadot_primitives::Block;
|
||||
pub use sp_runtime::traits::{Block as BlockT, self as runtime_traits, BlakeTwo256};
|
||||
@@ -76,7 +74,7 @@ native_executor_instance!(
|
||||
);
|
||||
|
||||
/// A set of APIs that polkadot-like runtimes must implement.
|
||||
pub trait RuntimeApiCollection<Extrinsic: codec::Codec + Send + Sync + 'static> :
|
||||
pub trait RuntimeApiCollection<Extrinsic: codec::Codec + Send + Sync + 'static>:
|
||||
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
|
||||
+ sp_api::ApiExt<Block, Error = sp_blockchain::Error>
|
||||
+ babe_primitives::BabeApi<Block>
|
||||
@@ -156,7 +154,7 @@ macro_rules! new_full_start {
|
||||
Block, $runtime, $executor
|
||||
>($config)?
|
||||
.with_select_chain(|_, backend| {
|
||||
Ok(sc_client::LongestChain::new(backend.clone()))
|
||||
Ok(sc_consensus::LongestChain::new(backend.clone()))
|
||||
})?
|
||||
.with_transaction_pool(|config, client, _fetcher, prometheus_registry| {
|
||||
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
|
||||
@@ -209,6 +207,352 @@ macro_rules! new_full_start {
|
||||
}}
|
||||
}
|
||||
|
||||
/// Builds a new service for a full client.
|
||||
#[macro_export]
|
||||
macro_rules! new_full {
|
||||
(
|
||||
$config:expr,
|
||||
$collating_for:expr,
|
||||
$max_block_data_size:expr,
|
||||
$authority_discovery_enabled:expr,
|
||||
$slot_duration:expr,
|
||||
$grandpa_pause:expr,
|
||||
$runtime:ty,
|
||||
$dispatch:ty
|
||||
) => {{
|
||||
use sc_network::Event;
|
||||
use sc_client_api::ExecutorProvider;
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
let is_collator = $collating_for.is_some();
|
||||
let role = $config.role.clone();
|
||||
let is_authority = role.is_authority() && !is_collator;
|
||||
let force_authoring = $config.force_authoring;
|
||||
let max_block_data_size = $max_block_data_size;
|
||||
let db_path = match $config.database.path() {
|
||||
Some(path) => std::path::PathBuf::from(path),
|
||||
None => return Err("Starting a Polkadot service with a custom database isn't supported".to_string().into()),
|
||||
};
|
||||
let disable_grandpa = $config.disable_grandpa;
|
||||
let name = $config.network.node_name.clone();
|
||||
let authority_discovery_enabled = $authority_discovery_enabled;
|
||||
let slot_duration = $slot_duration;
|
||||
|
||||
let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config, $runtime, $dispatch);
|
||||
|
||||
let backend = builder.backend().clone();
|
||||
|
||||
let service = builder
|
||||
.with_finality_proof_provider(|client, backend| {
|
||||
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
|
||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||
})?
|
||||
.build()?;
|
||||
|
||||
let (block_import, link_half, babe_link) = import_setup.take()
|
||||
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
|
||||
|
||||
let client = service.client();
|
||||
let known_oracle = client.clone();
|
||||
|
||||
let mut handles = FullNodeHandles::default();
|
||||
let select_chain = if let Some(select_chain) = service.select_chain() {
|
||||
select_chain
|
||||
} else {
|
||||
info!("The node cannot start as an authority because it can't select chain.");
|
||||
return Ok((service, client, handles));
|
||||
};
|
||||
let gossip_validator_select_chain = select_chain.clone();
|
||||
|
||||
let is_known = move |block_hash: &Hash| {
|
||||
use consensus_common::BlockStatus;
|
||||
|
||||
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 gossip_validator_select_chain.leaves() {
|
||||
Err(_) => None,
|
||||
Ok(leaves) => if leaves.contains(block_hash) {
|
||||
Some(Known::Leaf)
|
||||
} else {
|
||||
Some(Known::Old)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let polkadot_network_service = network_protocol::start(
|
||||
service.network(),
|
||||
network_protocol::Config {
|
||||
collating_for: $collating_for,
|
||||
},
|
||||
(is_known, client.clone()),
|
||||
client.clone(),
|
||||
service.spawn_task_handle(),
|
||||
).map_err(|e| format!("Could not spawn network worker: {:?}", e))?;
|
||||
|
||||
let authority_handles = if is_collator || role.is_authority() {
|
||||
let availability_store = {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let mut path = PathBuf::from(db_path);
|
||||
path.push("availability");
|
||||
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
{
|
||||
av_store::Store::new(
|
||||
::av_store::Config {
|
||||
cache_size: None,
|
||||
path,
|
||||
},
|
||||
polkadot_network_service.clone(),
|
||||
)?
|
||||
}
|
||||
|
||||
#[cfg(target_os = "unknown")]
|
||||
av_store::Store::new_in_memory(gossip)
|
||||
};
|
||||
|
||||
polkadot_network_service.register_availability_store(availability_store.clone());
|
||||
|
||||
let (validation_service_handle, validation_service) = consensus::ServiceBuilder {
|
||||
client: client.clone(),
|
||||
network: polkadot_network_service.clone(),
|
||||
collators: polkadot_network_service.clone(),
|
||||
spawner: service.spawn_task_handle(),
|
||||
availability_store: availability_store.clone(),
|
||||
select_chain: select_chain.clone(),
|
||||
keystore: service.keystore(),
|
||||
max_block_data_size,
|
||||
}.build();
|
||||
|
||||
service.spawn_essential_task("validation-service", Box::pin(validation_service));
|
||||
|
||||
handles.validation_service_handle = Some(validation_service_handle.clone());
|
||||
|
||||
Some((validation_service_handle, availability_store))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if role.is_authority() {
|
||||
let (validation_service_handle, availability_store) = authority_handles
|
||||
.clone()
|
||||
.expect("Authority handles are set for authority nodes; qed");
|
||||
|
||||
let proposer = consensus::ProposerFactory::new(
|
||||
client.clone(),
|
||||
service.transaction_pool(),
|
||||
validation_service_handle,
|
||||
slot_duration,
|
||||
backend,
|
||||
);
|
||||
|
||||
let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
|
||||
let can_author_with =
|
||||
consensus_common::CanAuthorWithNativeVersion::new(client.executor().clone());
|
||||
|
||||
let block_import = availability_store.block_import(
|
||||
block_import,
|
||||
client.clone(),
|
||||
service.spawn_task_handle(),
|
||||
service.keystore(),
|
||||
)?;
|
||||
|
||||
let babe_config = babe::BabeParams {
|
||||
keystore: service.keystore(),
|
||||
client: client.clone(),
|
||||
select_chain,
|
||||
block_import,
|
||||
env: proposer,
|
||||
sync_oracle: service.network(),
|
||||
inherent_data_providers: inherent_data_providers.clone(),
|
||||
force_authoring,
|
||||
babe_link,
|
||||
can_author_with,
|
||||
};
|
||||
|
||||
let babe = babe::start_babe(babe_config)?;
|
||||
service.spawn_essential_task("babe", babe);
|
||||
}
|
||||
|
||||
if matches!(role, Role::Authority{..} | Role::Sentry{..}) {
|
||||
if authority_discovery_enabled {
|
||||
let (sentries, authority_discovery_role) = match role {
|
||||
Role::Authority { ref sentry_nodes } => (
|
||||
sentry_nodes.clone(),
|
||||
authority_discovery::Role::Authority (
|
||||
service.keystore(),
|
||||
),
|
||||
),
|
||||
Role::Sentry {..} => (
|
||||
vec![],
|
||||
authority_discovery::Role::Sentry,
|
||||
),
|
||||
_ => unreachable!("Due to outer matches! constraint; qed."),
|
||||
};
|
||||
|
||||
let network = service.network();
|
||||
let network_event_stream = network.event_stream("authority-discovery");
|
||||
let dht_event_stream = network_event_stream.filter_map(|e| async move { match e {
|
||||
Event::Dht(e) => Some(e),
|
||||
_ => None,
|
||||
}}).boxed();
|
||||
let authority_discovery = authority_discovery::AuthorityDiscovery::new(
|
||||
service.client(),
|
||||
network,
|
||||
sentries,
|
||||
dht_event_stream,
|
||||
authority_discovery_role,
|
||||
service.prometheus_registry(),
|
||||
);
|
||||
|
||||
service.spawn_task("authority-discovery", authority_discovery);
|
||||
}
|
||||
}
|
||||
|
||||
// if the node isn't actively participating in consensus then it doesn't
|
||||
// need a keystore, regardless of which protocol we use below.
|
||||
let keystore = if is_authority {
|
||||
Some(service.keystore())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let config = grandpa::Config {
|
||||
// FIXME substrate#1578 make this available through chainspec
|
||||
gossip_duration: Duration::from_millis(1000),
|
||||
justification_period: 512,
|
||||
name: Some(name),
|
||||
observer_enabled: false,
|
||||
keystore,
|
||||
is_authority: role.is_network_authority(),
|
||||
};
|
||||
|
||||
let enable_grandpa = !disable_grandpa;
|
||||
if enable_grandpa {
|
||||
// start the full GRANDPA voter
|
||||
// NOTE: unlike in substrate we are currently running the full
|
||||
// GRANDPA voter protocol for all full nodes (regardless of whether
|
||||
// they're validators or not). at this point the full voter should
|
||||
// provide better guarantees of block and vote data availability than
|
||||
// the observer.
|
||||
|
||||
// add a custom voting rule to temporarily stop voting for new blocks
|
||||
// after the given pause block is finalized and restarting after the
|
||||
// given delay.
|
||||
let voting_rule = match $grandpa_pause {
|
||||
Some((block, delay)) => {
|
||||
info!("GRANDPA scheduled voting pause set for block #{} with a duration of {} blocks.",
|
||||
block,
|
||||
delay,
|
||||
);
|
||||
|
||||
grandpa::VotingRulesBuilder::default()
|
||||
.add(grandpa_support::PauseAfterBlockFor(block, delay))
|
||||
.build()
|
||||
},
|
||||
None =>
|
||||
grandpa::VotingRulesBuilder::default()
|
||||
.build(),
|
||||
};
|
||||
|
||||
let grandpa_config = grandpa::GrandpaParams {
|
||||
config,
|
||||
link: link_half,
|
||||
network: service.network(),
|
||||
inherent_data_providers: inherent_data_providers.clone(),
|
||||
telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
|
||||
voting_rule,
|
||||
prometheus_registry: service.prometheus_registry(),
|
||||
};
|
||||
|
||||
service.spawn_essential_task(
|
||||
"grandpa-voter",
|
||||
grandpa::run_grandpa_voter(grandpa_config)?
|
||||
);
|
||||
} else {
|
||||
grandpa::setup_disabled_grandpa(
|
||||
client.clone(),
|
||||
&inherent_data_providers,
|
||||
service.network(),
|
||||
)?;
|
||||
}
|
||||
|
||||
handles.polkadot_network = Some(polkadot_network_service);
|
||||
(service, client, handles)
|
||||
}}
|
||||
}
|
||||
|
||||
/// Builds a new service for a light client.
|
||||
#[macro_export]
|
||||
macro_rules! new_light {
|
||||
($config:expr, $runtime:ty, $dispatch:ty) => {{
|
||||
crate::set_prometheus_registry(&mut $config)?;
|
||||
let inherent_data_providers = inherents::InherentDataProviders::new();
|
||||
|
||||
ServiceBuilder::new_light::<Block, $runtime, $dispatch>($config)?
|
||||
.with_select_chain(|_, backend| {
|
||||
Ok(sc_consensus::LongestChain::new(backend.clone()))
|
||||
})?
|
||||
.with_transaction_pool(|config, client, fetcher, prometheus_registry| {
|
||||
let fetcher = fetcher
|
||||
.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
|
||||
let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
|
||||
let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
|
||||
config, Arc::new(pool_api), prometheus_registry, sc_transaction_pool::RevalidationType::Light,
|
||||
);
|
||||
Ok(pool)
|
||||
})?
|
||||
.with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _| {
|
||||
let fetch_checker = fetcher
|
||||
.map(|fetcher| fetcher.checker().clone())
|
||||
.ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
|
||||
let grandpa_block_import = grandpa::light_block_import(
|
||||
client.clone(), backend, &(client.clone() as Arc<_>), Arc::new(fetch_checker)
|
||||
)?;
|
||||
|
||||
let finality_proof_import = grandpa_block_import.clone();
|
||||
let finality_proof_request_builder =
|
||||
finality_proof_import.create_finality_proof_request_builder();
|
||||
|
||||
let (babe_block_import, babe_link) = babe::block_import(
|
||||
babe::Config::get_or_compute(&*client)?,
|
||||
grandpa_block_import,
|
||||
client.clone(),
|
||||
)?;
|
||||
|
||||
// FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
|
||||
let import_queue = babe::import_queue(
|
||||
babe_link,
|
||||
babe_block_import,
|
||||
None,
|
||||
Some(Box::new(finality_proof_import)),
|
||||
client,
|
||||
inherent_data_providers.clone(),
|
||||
)?;
|
||||
|
||||
Ok((import_queue, finality_proof_request_builder))
|
||||
})?
|
||||
.with_finality_proof_provider(|client, backend| {
|
||||
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
|
||||
Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _)
|
||||
})?
|
||||
.with_rpc_extensions(|builder|
|
||||
-> Result<polkadot_rpc::RpcExtension, _> {
|
||||
let fetcher = builder.fetcher()
|
||||
.ok_or_else(|| "Trying to start node RPC without active fetcher")?;
|
||||
let remote_blockchain = builder.remote_backend()
|
||||
.ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
|
||||
|
||||
Ok(polkadot_rpc::create_light(builder.client().clone(), remote_blockchain, fetcher, builder.pool()))
|
||||
})?
|
||||
.build()
|
||||
}}
|
||||
}
|
||||
|
||||
/// Builds a new object suitable for chain operations.
|
||||
pub fn new_chain_ops<Runtime, Dispatch, Extrinsic>(mut config: Configuration)
|
||||
-> Result<impl ServiceBuilderCommand<Block=Block>, ServiceError>
|
||||
@@ -227,7 +571,7 @@ where
|
||||
/// Create a new Polkadot service for a full node.
|
||||
#[cfg(feature = "full-node")]
|
||||
pub fn polkadot_new_full(
|
||||
config: Configuration,
|
||||
mut config: Configuration,
|
||||
collating_for: Option<(CollatorId, parachain::Id)>,
|
||||
max_block_data_size: Option<u64>,
|
||||
authority_discovery_enabled: bool,
|
||||
@@ -235,61 +579,69 @@ pub fn polkadot_new_full(
|
||||
grandpa_pause: Option<(u32, u32)>,
|
||||
)
|
||||
-> Result<(
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = polkadot_runtime::RuntimeApi,
|
||||
Backend = TFullBackend<Block>,
|
||||
SelectChain = LongestChain<TFullBackend<Block>, Block>,
|
||||
CallExecutor = TFullCallExecutor<Block, PolkadotExecutor>,
|
||||
>,
|
||||
impl AbstractService,
|
||||
Arc<impl ClientProvider<
|
||||
Block,
|
||||
TFullBackend<Block>,
|
||||
TFullCallExecutor<Block, PolkadotExecutor>,
|
||||
polkadot_runtime::RuntimeApi
|
||||
>>,
|
||||
FullNodeHandles,
|
||||
), ServiceError>
|
||||
{
|
||||
new_full(
|
||||
let (service, client, handles) = new_full!(
|
||||
config,
|
||||
collating_for,
|
||||
max_block_data_size,
|
||||
authority_discovery_enabled,
|
||||
slot_duration,
|
||||
grandpa_pause,
|
||||
)
|
||||
polkadot_runtime::RuntimeApi,
|
||||
PolkadotExecutor
|
||||
);
|
||||
|
||||
Ok((service, client, handles))
|
||||
}
|
||||
|
||||
/// Create a new Kusama service for a full node.
|
||||
#[cfg(feature = "full-node")]
|
||||
pub fn kusama_new_full(
|
||||
config: Configuration,
|
||||
mut config: Configuration,
|
||||
collating_for: Option<(CollatorId, parachain::Id)>,
|
||||
max_block_data_size: Option<u64>,
|
||||
authority_discovery_enabled: bool,
|
||||
slot_duration: u64,
|
||||
grandpa_pause: Option<(u32, u32)>,
|
||||
)
|
||||
-> Result<(
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = kusama_runtime::RuntimeApi,
|
||||
Backend = TFullBackend<Block>,
|
||||
SelectChain = LongestChain<TFullBackend<Block>, Block>,
|
||||
CallExecutor = TFullCallExecutor<Block, KusamaExecutor>,
|
||||
) -> Result<(
|
||||
impl AbstractService,
|
||||
Arc<impl ClientProvider<
|
||||
Block,
|
||||
TFullBackend<Block>,
|
||||
TFullCallExecutor<Block, KusamaExecutor>,
|
||||
kusama_runtime::RuntimeApi
|
||||
>
|
||||
>,
|
||||
FullNodeHandles,
|
||||
FullNodeHandles
|
||||
), ServiceError>
|
||||
{
|
||||
new_full(
|
||||
let (service, client, handles) = new_full!(
|
||||
config,
|
||||
collating_for,
|
||||
max_block_data_size,
|
||||
authority_discovery_enabled,
|
||||
slot_duration,
|
||||
grandpa_pause,
|
||||
)
|
||||
kusama_runtime::RuntimeApi,
|
||||
KusamaExecutor
|
||||
);
|
||||
|
||||
Ok((service, client, handles))
|
||||
}
|
||||
|
||||
/// Create a new Kusama service for a full node.
|
||||
#[cfg(feature = "full-node")]
|
||||
pub fn westend_new_full(
|
||||
config: Configuration,
|
||||
mut config: Configuration,
|
||||
collating_for: Option<(CollatorId, parachain::Id)>,
|
||||
max_block_data_size: Option<u64>,
|
||||
authority_discovery_enabled: bool,
|
||||
@@ -297,24 +649,28 @@ pub fn westend_new_full(
|
||||
grandpa_pause: Option<(u32, u32)>,
|
||||
)
|
||||
-> Result<(
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = westend_runtime::RuntimeApi,
|
||||
Backend = TFullBackend<Block>,
|
||||
SelectChain = LongestChain<TFullBackend<Block>, Block>,
|
||||
CallExecutor = TFullCallExecutor<Block, KusamaExecutor>,
|
||||
>,
|
||||
impl AbstractService,
|
||||
Arc<impl ClientProvider<
|
||||
Block,
|
||||
TFullBackend<Block>,
|
||||
TFullCallExecutor<Block, KusamaExecutor>,
|
||||
westend_runtime::RuntimeApi
|
||||
>>,
|
||||
FullNodeHandles,
|
||||
), ServiceError>
|
||||
{
|
||||
new_full(
|
||||
let (service, client, handles) = new_full!(
|
||||
config,
|
||||
collating_for,
|
||||
max_block_data_size,
|
||||
authority_discovery_enabled,
|
||||
slot_duration,
|
||||
grandpa_pause,
|
||||
)
|
||||
westend_runtime::RuntimeApi,
|
||||
KusamaExecutor
|
||||
);
|
||||
|
||||
Ok((service, client, handles))
|
||||
}
|
||||
|
||||
/// Handles to other sub-services that full nodes instantiate, which consumers
|
||||
@@ -328,305 +684,9 @@ pub struct FullNodeHandles {
|
||||
pub validation_service_handle: Option<consensus::ServiceHandle>,
|
||||
}
|
||||
|
||||
/// Builds a new service for a full client.
|
||||
#[cfg(feature = "full-node")]
|
||||
pub fn new_full<Runtime, Dispatch, Extrinsic>(
|
||||
mut config: Configuration,
|
||||
collating_for: Option<(CollatorId, parachain::Id)>,
|
||||
max_block_data_size: Option<u64>,
|
||||
authority_discovery_enabled: bool,
|
||||
slot_duration: u64,
|
||||
grandpa_pause: Option<(u32, u32)>,
|
||||
)
|
||||
-> Result<(
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = Runtime,
|
||||
Backend = TFullBackend<Block>,
|
||||
SelectChain = LongestChain<TFullBackend<Block>, Block>,
|
||||
CallExecutor = TFullCallExecutor<Block, Dispatch>,
|
||||
>,
|
||||
FullNodeHandles,
|
||||
), ServiceError>
|
||||
where
|
||||
Runtime: ConstructRuntimeApi<Block, service::TFullClient<Block, Runtime, Dispatch>> + Send + Sync + 'static,
|
||||
Runtime::RuntimeApi:
|
||||
RuntimeApiCollection<Extrinsic, StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>>,
|
||||
Dispatch: NativeExecutionDispatch + 'static,
|
||||
Extrinsic: RuntimeExtrinsic,
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/24159
|
||||
<Runtime::RuntimeApi as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
|
||||
{
|
||||
use sc_network::Event;
|
||||
use sc_client_api::ExecutorProvider;
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
let is_collator = collating_for.is_some();
|
||||
let role = config.role.clone();
|
||||
let is_authority = role.is_authority() && !is_collator;
|
||||
let force_authoring = config.force_authoring;
|
||||
let max_block_data_size = max_block_data_size;
|
||||
let db_path = match config.database.path() {
|
||||
Some(path) => std::path::PathBuf::from(path),
|
||||
None => return Err("Starting a Polkadot service with a custom database isn't supported".to_string().into()),
|
||||
};
|
||||
let disable_grandpa = config.disable_grandpa;
|
||||
let name = config.network.node_name.clone();
|
||||
let authority_discovery_enabled = authority_discovery_enabled;
|
||||
let slot_duration = slot_duration;
|
||||
|
||||
let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config, Runtime, Dispatch);
|
||||
|
||||
let backend = builder.backend().clone();
|
||||
|
||||
let service = builder
|
||||
.with_finality_proof_provider(|client, backend| {
|
||||
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
|
||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||
})?
|
||||
.build()?;
|
||||
|
||||
let (block_import, link_half, babe_link) = import_setup.take()
|
||||
.expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
|
||||
|
||||
let client = service.client();
|
||||
let known_oracle = client.clone();
|
||||
|
||||
let mut handles = FullNodeHandles::default();
|
||||
let select_chain = if let Some(select_chain) = service.select_chain() {
|
||||
select_chain
|
||||
} else {
|
||||
info!("The node cannot start as an authority because it can't select chain.");
|
||||
return Ok((service, handles));
|
||||
};
|
||||
let gossip_validator_select_chain = select_chain.clone();
|
||||
|
||||
let is_known = move |block_hash: &Hash| {
|
||||
use consensus_common::BlockStatus;
|
||||
|
||||
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 gossip_validator_select_chain.leaves() {
|
||||
Err(_) => None,
|
||||
Ok(leaves) => if leaves.contains(block_hash) {
|
||||
Some(Known::Leaf)
|
||||
} else {
|
||||
Some(Known::Old)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let polkadot_network_service = network_protocol::start(
|
||||
service.network(),
|
||||
network_protocol::Config {
|
||||
collating_for,
|
||||
},
|
||||
(is_known, client.clone()),
|
||||
client.clone(),
|
||||
service.spawn_task_handle(),
|
||||
).map_err(|e| format!("Could not spawn network worker: {:?}", e))?;
|
||||
|
||||
let authority_handles = if is_collator || role.is_authority() {
|
||||
let availability_store = {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let mut path = PathBuf::from(db_path);
|
||||
path.push("availability");
|
||||
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
{
|
||||
av_store::Store::new(
|
||||
::av_store::Config {
|
||||
cache_size: None,
|
||||
path,
|
||||
},
|
||||
polkadot_network_service.clone(),
|
||||
)?
|
||||
}
|
||||
|
||||
#[cfg(target_os = "unknown")]
|
||||
av_store::Store::new_in_memory(gossip)
|
||||
};
|
||||
|
||||
polkadot_network_service.register_availability_store(availability_store.clone());
|
||||
|
||||
let (validation_service_handle, validation_service) = consensus::ServiceBuilder {
|
||||
client: client.clone(),
|
||||
network: polkadot_network_service.clone(),
|
||||
collators: polkadot_network_service.clone(),
|
||||
spawner: service.spawn_task_handle(),
|
||||
availability_store: availability_store.clone(),
|
||||
select_chain: select_chain.clone(),
|
||||
keystore: service.keystore(),
|
||||
max_block_data_size,
|
||||
}.build();
|
||||
|
||||
service.spawn_essential_task("validation-service", Box::pin(validation_service));
|
||||
|
||||
handles.validation_service_handle = Some(validation_service_handle.clone());
|
||||
|
||||
Some((validation_service_handle, availability_store))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if role.is_authority() {
|
||||
let (validation_service_handle, availability_store) = authority_handles
|
||||
.clone()
|
||||
.expect("Authority handles are set for authority nodes; qed");
|
||||
|
||||
let proposer = consensus::ProposerFactory::new(
|
||||
client.clone(),
|
||||
service.transaction_pool(),
|
||||
validation_service_handle,
|
||||
slot_duration,
|
||||
backend,
|
||||
);
|
||||
|
||||
let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
|
||||
let can_author_with =
|
||||
consensus_common::CanAuthorWithNativeVersion::new(client.executor().clone());
|
||||
|
||||
let block_import = availability_store.block_import(
|
||||
block_import,
|
||||
client.clone(),
|
||||
service.spawn_task_handle(),
|
||||
service.keystore(),
|
||||
)?;
|
||||
|
||||
let babe_config = babe::BabeParams {
|
||||
keystore: service.keystore(),
|
||||
client,
|
||||
select_chain,
|
||||
block_import,
|
||||
env: proposer,
|
||||
sync_oracle: service.network(),
|
||||
inherent_data_providers: inherent_data_providers.clone(),
|
||||
force_authoring,
|
||||
babe_link,
|
||||
can_author_with,
|
||||
};
|
||||
|
||||
let babe = babe::start_babe(babe_config)?;
|
||||
service.spawn_essential_task("babe", babe);
|
||||
}
|
||||
|
||||
if matches!(role, Role::Authority{..} | Role::Sentry{..}) {
|
||||
if authority_discovery_enabled {
|
||||
let (sentries, authority_discovery_role) = match role {
|
||||
Role::Authority { ref sentry_nodes } => (
|
||||
sentry_nodes.clone(),
|
||||
authority_discovery::Role::Authority (
|
||||
service.keystore(),
|
||||
),
|
||||
),
|
||||
Role::Sentry {..} => (
|
||||
vec![],
|
||||
authority_discovery::Role::Sentry,
|
||||
),
|
||||
_ => unreachable!("Due to outer matches! constraint; qed."),
|
||||
};
|
||||
|
||||
let network = service.network();
|
||||
let network_event_stream = network.event_stream("authority-discovery");
|
||||
let dht_event_stream = network_event_stream.filter_map(|e| async move { match e {
|
||||
Event::Dht(e) => Some(e),
|
||||
_ => None,
|
||||
}}).boxed();
|
||||
let authority_discovery = authority_discovery::AuthorityDiscovery::new(
|
||||
service.client(),
|
||||
network,
|
||||
sentries,
|
||||
dht_event_stream,
|
||||
authority_discovery_role,
|
||||
service.prometheus_registry(),
|
||||
);
|
||||
|
||||
service.spawn_task("authority-discovery", authority_discovery);
|
||||
}
|
||||
}
|
||||
|
||||
// if the node isn't actively participating in consensus then it doesn't
|
||||
// need a keystore, regardless of which protocol we use below.
|
||||
let keystore = if is_authority {
|
||||
Some(service.keystore())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let config = grandpa::Config {
|
||||
// FIXME substrate#1578 make this available through chainspec
|
||||
gossip_duration: Duration::from_millis(1000),
|
||||
justification_period: 512,
|
||||
name: Some(name),
|
||||
observer_enabled: false,
|
||||
keystore,
|
||||
is_authority: role.is_network_authority(),
|
||||
};
|
||||
|
||||
let enable_grandpa = !disable_grandpa;
|
||||
if enable_grandpa {
|
||||
// start the full GRANDPA voter
|
||||
// NOTE: unlike in substrate we are currently running the full
|
||||
// GRANDPA voter protocol for all full nodes (regardless of whether
|
||||
// they're validators or not). at this point the full voter should
|
||||
// provide better guarantees of block and vote data availability than
|
||||
// the observer.
|
||||
|
||||
// add a custom voting rule to temporarily stop voting for new blocks
|
||||
// after the given pause block is finalized and restarting after the
|
||||
// given delay.
|
||||
let voting_rule = match grandpa_pause {
|
||||
Some((block, delay)) => {
|
||||
info!("GRANDPA scheduled voting pause set for block #{} with a duration of {} blocks.",
|
||||
block,
|
||||
delay,
|
||||
);
|
||||
|
||||
grandpa::VotingRulesBuilder::default()
|
||||
.add(grandpa_support::PauseAfterBlockFor(block, delay))
|
||||
.build()
|
||||
},
|
||||
None =>
|
||||
grandpa::VotingRulesBuilder::default()
|
||||
.build(),
|
||||
};
|
||||
|
||||
let grandpa_config = grandpa::GrandpaParams {
|
||||
config,
|
||||
link: link_half,
|
||||
network: service.network(),
|
||||
inherent_data_providers: inherent_data_providers.clone(),
|
||||
telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
|
||||
voting_rule,
|
||||
prometheus_registry: service.prometheus_registry(),
|
||||
};
|
||||
|
||||
service.spawn_essential_task(
|
||||
"grandpa-voter",
|
||||
grandpa::run_grandpa_voter(grandpa_config)?
|
||||
);
|
||||
} else {
|
||||
grandpa::setup_disabled_grandpa(
|
||||
service.client(),
|
||||
&inherent_data_providers,
|
||||
service.network(),
|
||||
)?;
|
||||
}
|
||||
|
||||
handles.polkadot_network = Some(polkadot_network_service);
|
||||
Ok((service, handles))
|
||||
}
|
||||
|
||||
/// Create a new Polkadot service for a light client.
|
||||
pub fn polkadot_new_light(
|
||||
config: Configuration,
|
||||
)
|
||||
-> Result<impl AbstractService<
|
||||
pub fn polkadot_new_light(mut config: Configuration) -> Result<
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = polkadot_runtime::RuntimeApi,
|
||||
Backend = TLightBackend<Block>,
|
||||
@@ -634,14 +694,12 @@ pub fn polkadot_new_light(
|
||||
CallExecutor = TLightCallExecutor<Block, PolkadotExecutor>,
|
||||
>, ServiceError>
|
||||
{
|
||||
new_light(config)
|
||||
new_light!(config, polkadot_runtime::RuntimeApi, PolkadotExecutor)
|
||||
}
|
||||
|
||||
/// Create a new Kusama service for a light client.
|
||||
pub fn kusama_new_light(
|
||||
config: Configuration,
|
||||
)
|
||||
-> Result<impl AbstractService<
|
||||
pub fn kusama_new_light(mut config: Configuration) -> Result<
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = kusama_runtime::RuntimeApi,
|
||||
Backend = TLightBackend<Block>,
|
||||
@@ -649,125 +707,19 @@ pub fn kusama_new_light(
|
||||
CallExecutor = TLightCallExecutor<Block, KusamaExecutor>,
|
||||
>, ServiceError>
|
||||
{
|
||||
new_light(config)
|
||||
new_light!(config, kusama_runtime::RuntimeApi, KusamaExecutor)
|
||||
}
|
||||
|
||||
/// Create a new Westend service for a light client.
|
||||
pub fn westend_new_light(
|
||||
config: Configuration,
|
||||
)
|
||||
-> Result<impl AbstractService<
|
||||
pub fn westend_new_light(mut config: Configuration, ) -> Result<
|
||||
impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = westend_runtime::RuntimeApi,
|
||||
Backend = TLightBackend<Block>,
|
||||
SelectChain = LongestChain<TLightBackend<Block>, Block>,
|
||||
CallExecutor = TLightCallExecutor<Block, KusamaExecutor>,
|
||||
>, ServiceError>
|
||||
CallExecutor = TLightCallExecutor<Block, KusamaExecutor>
|
||||
>,
|
||||
ServiceError>
|
||||
{
|
||||
new_light(config)
|
||||
}
|
||||
|
||||
// We can't use service::TLightClient due to
|
||||
// Rust bug: https://github.com/rust-lang/rust/issues/43580
|
||||
type TLocalLightClient<Runtime, Dispatch> = Client<
|
||||
sc_client::light::backend::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>,
|
||||
sc_client::light::call_executor::GenesisCallExecutor<
|
||||
sc_client::light::backend::Backend<sc_client_db::light::LightStorage<Block>, BlakeTwo256>,
|
||||
sc_client::LocalCallExecutor<
|
||||
sc_client::light::backend::Backend<
|
||||
sc_client_db::light::LightStorage<Block>,
|
||||
BlakeTwo256
|
||||
>,
|
||||
sc_executor::NativeExecutor<Dispatch>
|
||||
>
|
||||
>,
|
||||
Block,
|
||||
Runtime
|
||||
>;
|
||||
|
||||
/// Builds a new service for a light client.
|
||||
pub fn new_light<Runtime, Dispatch, Extrinsic>(
|
||||
mut config: Configuration,
|
||||
)
|
||||
-> Result<impl AbstractService<
|
||||
Block = Block,
|
||||
RuntimeApi = Runtime,
|
||||
Backend = TLightBackend<Block>,
|
||||
SelectChain = LongestChain<TLightBackend<Block>, Block>,
|
||||
CallExecutor = TLightCallExecutor<Block, Dispatch>,
|
||||
>, ServiceError>
|
||||
where
|
||||
Runtime: Send + Sync + 'static,
|
||||
Runtime::RuntimeApi: RuntimeApiCollection<
|
||||
Extrinsic,
|
||||
StateBackend = sc_client_api::StateBackendFor<TLightBackend<Block>, Block>
|
||||
>,
|
||||
Dispatch: NativeExecutionDispatch + 'static,
|
||||
Extrinsic: RuntimeExtrinsic,
|
||||
Runtime: sp_api::ConstructRuntimeApi<
|
||||
Block,
|
||||
TLocalLightClient<Runtime, Dispatch>,
|
||||
>,
|
||||
{
|
||||
set_prometheus_registry(&mut config)?;
|
||||
|
||||
let inherent_data_providers = InherentDataProviders::new();
|
||||
|
||||
ServiceBuilder::new_light::<Block, Runtime, Dispatch>(config)?
|
||||
.with_select_chain(|_, backend| {
|
||||
Ok(LongestChain::new(backend.clone()))
|
||||
})?
|
||||
.with_transaction_pool(|config, client, fetcher, prometheus_registry| {
|
||||
let fetcher = fetcher
|
||||
.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
|
||||
let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
|
||||
let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
|
||||
config, Arc::new(pool_api), prometheus_registry, sc_transaction_pool::RevalidationType::Light,
|
||||
);
|
||||
Ok(pool)
|
||||
})?
|
||||
.with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _| {
|
||||
let fetch_checker = fetcher
|
||||
.map(|fetcher| fetcher.checker().clone())
|
||||
.ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
|
||||
let grandpa_block_import = grandpa::light_block_import(
|
||||
client.clone(), backend, &(client.clone() as Arc<_>), Arc::new(fetch_checker)
|
||||
)?;
|
||||
|
||||
let finality_proof_import = grandpa_block_import.clone();
|
||||
let finality_proof_request_builder =
|
||||
finality_proof_import.create_finality_proof_request_builder();
|
||||
|
||||
let (babe_block_import, babe_link) = babe::block_import(
|
||||
babe::Config::get_or_compute(&*client)?,
|
||||
grandpa_block_import,
|
||||
client.clone(),
|
||||
)?;
|
||||
|
||||
// FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
|
||||
let import_queue = babe::import_queue(
|
||||
babe_link,
|
||||
babe_block_import,
|
||||
None,
|
||||
Some(Box::new(finality_proof_import)),
|
||||
client,
|
||||
inherent_data_providers.clone(),
|
||||
)?;
|
||||
|
||||
Ok((import_queue, finality_proof_request_builder))
|
||||
})?
|
||||
.with_finality_proof_provider(|client, backend| {
|
||||
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
|
||||
Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
|
||||
})?
|
||||
.with_rpc_extensions(|builder|
|
||||
-> Result<polkadot_rpc::RpcExtension, _> {
|
||||
let fetcher = builder.fetcher()
|
||||
.ok_or_else(|| "Trying to start node RPC without active fetcher")?;
|
||||
let remote_blockchain = builder.remote_backend()
|
||||
.ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
|
||||
|
||||
Ok(polkadot_rpc::create_light(builder.client().clone(), remote_blockchain, fetcher, builder.pool()))
|
||||
})?
|
||||
.build()
|
||||
new_light!(config, westend_runtime::RuntimeApi, KusamaExecutor)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user