Unverified Commit 75cebe9b authored by Bastian Köcher's avatar Bastian Köcher Committed by GitHub
Browse files

Companion for Substrate#8526 (#2845)

* Update branch

* Make it compile

* Compile

* gate approval-checking logic (#2470)

* Fix build

* Updates

* Fix merge

* Adds missing crate

* Companion for Substrate#8386

https://github.com/paritytech/substrate/pull/8386



* Fix fix fix

* Fix

* Fix compilation

* Rewrite to `ParachainsInherentDataProvider`

* Make it compile

* Renamings

* Revert stuff

* Remove stale file

* Guide updates

* Update node/core/parachains-inherent/src/lib.rs
Co-authored-by: Andronik Ordian's avatarAndronik Ordian <write@reusable.software>

* Update node/core/parachains-inherent/src/lib.rs
Co-authored-by: Andronik Ordian's avatarAndronik Ordian <write@reusable.software>

* Apply suggestions from code review

* Reset accidental changes

* More

* Remove stale file

* update Substrate
Co-authored-by: asynchronous rob's avatarRobert Habermeier <rphmeier@gmail.com>
Co-authored-by: Andronik Ordian's avatarAndronik Ordian <write@reusable.software>
Co-authored-by: parity-processbot <>
parent cf1338c1
Pipeline #136659 canceled with stages
in 10 minutes and 17 seconds
This diff is collapsed.
......@@ -56,7 +56,7 @@ members = [
"node/core/candidate-selection",
"node/core/candidate-validation",
"node/core/chain-api",
"node/core/proposer",
"node/core/parachains-inherent",
"node/core/provisioner",
"node/core/pvf",
"node/core/runtime-api",
......
......@@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
polkadot-primitives = { package = "polkadot-primitives", path = "../primitives" }
polkadot-primitives = { path = "../primitives" }
polkadot-node-primitives = { package = "polkadot-node-primitives", path = "../node/primitives" }
novelpoly = { package = "reed-solomon-novelpoly", version = "1.0.0" }
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["std", "derive"] }
......
[package]
name = "polkadot-node-core-proposer"
name = "polkadot-node-core-parachains-inherent"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
......@@ -8,18 +8,11 @@ edition = "2018"
futures = "0.3.12"
futures-timer = "3.0.2"
tracing = "0.1.25"
thiserror = "1.0.23"
async-trait = "0.1.47"
polkadot-node-subsystem = { path = "../../subsystem" }
polkadot-overseer = { path = "../../overseer" }
polkadot-primitives = { path = "../../../primitives" }
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
prometheus-endpoint = { package = "substrate-prometheus-endpoint", git = "https://github.com/paritytech/substrate", branch = "master" }
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! The parachain inherent data provider
//!
//! Parachain backing and approval is an off-chain process, but the parachain needs to progress on chain as well. To
//! make it progress on chain a block producer needs to forward information about the state of a parachain to the
//! runtime. This information is forwarded through an inherent to the runtime. Here we provide the
//! [`ParachainInherentDataProvider`] that requests the relevant data from the provisioner subsystem and creates the
//! the inherent data that the runtime will use to create an inherent.
#![deny(unused_crate_dependencies, unused_results)]
use futures::{select, FutureExt};
use polkadot_node_subsystem::{
messages::{AllMessages, ProvisionerMessage}, SubsystemError,
};
use polkadot_overseer::OverseerHandler;
use polkadot_primitives::v1::{
Block, Hash, InherentData as ParachainsInherentData,
};
use sp_blockchain::HeaderBackend;
use sp_runtime::generic::BlockId;
use std::time;
/// How long to wait for the provisioner, before giving up.
const PROVISIONER_TIMEOUT: time::Duration = core::time::Duration::from_millis(2500);
/// Provides the parachains inherent data.
pub struct ParachainsInherentDataProvider {
inherent_data: ParachainsInherentData,
}
impl ParachainsInherentDataProvider {
/// Create a new instance of the [`ParachainsInherentDataProvider`].
pub async fn create<C: HeaderBackend<Block>>(
client: &C,
mut overseer: OverseerHandler,
parent: Hash,
) -> Result<Self, Error> {
let pid = async {
let (sender, receiver) = futures::channel::oneshot::channel();
overseer.wait_for_activation(parent, sender).await;
receiver.await.map_err(|_| Error::ClosedChannelAwaitingActivation)?.map_err(Error::Subsystem)?;
let (sender, receiver) = futures::channel::oneshot::channel();
overseer.send_msg(AllMessages::Provisioner(
ProvisionerMessage::RequestInherentData(parent, sender),
)).await;
receiver.await.map_err(|_| Error::ClosedChannelAwaitingInherentData)
};
let mut timeout = futures_timer::Delay::new(PROVISIONER_TIMEOUT).fuse();
let parent_header = match client.header(BlockId::Hash(parent)) {
Ok(Some(h)) => h,
Ok(None) => return Err(Error::ParentHeaderNotFound(parent)),
Err(err) => return Err(Error::Blockchain(err)),
};
let res = select! {
pid = pid.fuse() => pid,
_ = timeout => Err(Error::Timeout),
};
let inherent_data = match res {
Ok(pd) => ParachainsInherentData {
bitfields: pd.bitfields,
backed_candidates: pd.backed_candidates,
disputes: pd.disputes,
parent_header,
},
Err(err) => {
tracing::debug!(
?err,
"Could not get provisioner inherent data; injecting default data",
);
ParachainsInherentData {
bitfields: Vec::new(),
backed_candidates: Vec::new(),
disputes: Vec::new(),
parent_header,
}
}
};
Ok(Self { inherent_data })
}
}
#[async_trait::async_trait]
impl sp_inherents::InherentDataProvider for ParachainsInherentDataProvider {
fn provide_inherent_data(&self, inherent_data: &mut sp_inherents::InherentData) -> Result<(), sp_inherents::Error> {
inherent_data.put_data(
polkadot_primitives::v1::PARACHAINS_INHERENT_IDENTIFIER,
&self.inherent_data,
)
}
async fn try_handle_error(
&self,
_: &sp_inherents::InherentIdentifier,
_: &[u8],
) -> Option<Result<(), sp_inherents::Error>> {
// Inherent isn't checked and can not return any error
None
}
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Blockchain error")]
Blockchain(sp_blockchain::Error),
#[error("Timeout: provisioner did not return inherent data after {:?}", PROVISIONER_TIMEOUT)]
Timeout,
#[error("Could not find the parent header in the blockchain: {:?}", _0)]
ParentHeaderNotFound(Hash),
#[error("Closed channel from overseer when awaiting activation")]
ClosedChannelAwaitingActivation,
#[error("Closed channel from provisioner when awaiting inherent data")]
ClosedChannelAwaitingInherentData,
#[error("Subsystem failed")]
Subsystem(SubsystemError),
}
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! The proposer proposes new blocks to include
#![deny(unused_crate_dependencies, unused_results)]
use futures::prelude::*;
use futures::select;
use polkadot_node_subsystem::{
jaeger,
messages::{AllMessages, ProvisionerInherentData, ProvisionerMessage}, SubsystemError,
};
use polkadot_overseer::OverseerHandler;
use polkadot_primitives::v1::{
Block, Hash, Header, InherentData as ParachainsInherentData,
};
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
use sc_telemetry::TelemetryHandle;
use sp_core::traits::SpawnNamed;
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use sp_consensus::{Proposal, DisableProofRecording};
use sp_inherents::InherentData;
use sp_runtime::traits::{DigestFor, HashFor};
use sp_transaction_pool::TransactionPool;
use prometheus_endpoint::Registry as PrometheusRegistry;
use std::{fmt, pin::Pin, sync::Arc, time};
/// How long proposing can take, before we give up and err out. We need a relatively large timeout
/// here as long as we have large payload in statement distribution. Assuming we can reach most
/// nodes within two hops, we will take about 2 seconds for transferring statements (data transfer
/// only). If necessary, we could be able to reduce this to 3 seconds. To consider: The lower the
/// riskier that we will not be able to include a candidate.
const PROPOSE_TIMEOUT: core::time::Duration = core::time::Duration::from_millis(4000);
/// Custom Proposer factory for Polkadot
pub struct ProposerFactory<TxPool, Backend, Client> {
inner: sc_basic_authorship::ProposerFactory<TxPool, Backend, Client, DisableProofRecording>,
overseer: OverseerHandler,
}
impl<TxPool, Backend, Client> ProposerFactory<TxPool, Backend, Client> {
pub fn new(
spawn_handle: impl SpawnNamed + 'static,
client: Arc<Client>,
transaction_pool: Arc<TxPool>,
overseer: OverseerHandler,
prometheus: Option<&PrometheusRegistry>,
telemetry: Option<TelemetryHandle>,
) -> Self {
ProposerFactory {
inner: sc_basic_authorship::ProposerFactory::new(
spawn_handle,
client,
transaction_pool,
prometheus,
telemetry,
),
overseer,
}
}
}
impl<TxPool, Backend, Client> sp_consensus::Environment<Block>
for ProposerFactory<TxPool, Backend, Client>
where
TxPool: 'static + TransactionPool<Block = Block>,
Client: 'static
+ BlockBuilderProvider<Backend, Block, Client>
+ ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ Send
+ Sync,
Client::Api:
BlockBuilderApi<Block> + ApiExt<Block>,
Backend:
'static + sc_client_api::Backend<Block, State = sp_api::StateBackendFor<Client, Block>>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor<Client, Block>: sp_api::StateBackend<HashFor<Block>> + Send,
{
type CreateProposer = Pin<Box<
dyn Future<Output = Result<Self::Proposer, Self::Error>> + Send + 'static,
>>;
type Proposer = Proposer<TxPool, Backend, Client>;
type Error = Error;
fn init(&mut self, parent_header: &Header) -> Self::CreateProposer {
// create the inner proposer
let proposer = self.inner.init(parent_header).into_inner();
// data to be moved into the future
let overseer = self.overseer.clone();
let parent_header_hash = parent_header.hash();
let parent_header = parent_header.clone();
async move {
Ok(Proposer {
inner: proposer?,
overseer,
parent_header,
parent_header_hash,
})
}.boxed()
}
}
/// Custom Proposer for Polkadot.
///
/// This proposer gets the ProvisionerInherentData and injects it into the wrapped
/// proposer's inherent data, then delegates the actual proposal generation.
pub struct Proposer<TxPool: TransactionPool<Block = Block>, Backend, Client> {
inner: sc_basic_authorship::Proposer<Backend, Block, Client, TxPool, DisableProofRecording>,
overseer: OverseerHandler,
parent_header: Header,
parent_header_hash: Hash,
}
// This impl has the same generic bounds as the Proposer impl.
impl<TxPool, Backend, Client> Proposer<TxPool, Backend, Client>
where
TxPool: 'static + TransactionPool<Block = Block>,
Client: 'static
+ BlockBuilderProvider<Backend, Block, Client>
+ ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ Send
+ Sync,
Client::Api:
BlockBuilderApi<Block> + ApiExt<Block>,
Backend:
'static + sc_client_api::Backend<Block, State = sp_api::StateBackendFor<Client, Block>>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor<Client, Block>: sp_api::StateBackend<HashFor<Block>> + Send,
{
/// Get provisioner inherent data
///
/// This function has a constant timeout: `PROPOSE_TIMEOUT`.
async fn get_provisioner_data(&self) -> Result<ProvisionerInherentData, Error> {
// clone this (lightweight) data because we're going to move it into the future
let mut overseer = self.overseer.clone();
let parent_header_hash = self.parent_header_hash.clone();
let pid = async {
let (sender, receiver) = futures::channel::oneshot::channel();
overseer.wait_for_activation(parent_header_hash, sender).await;
receiver.await.map_err(|_| Error::ClosedChannelAwaitingActivation)??;
let (sender, receiver) = futures::channel::oneshot::channel();
overseer.send_msg(AllMessages::Provisioner(
ProvisionerMessage::RequestInherentData(parent_header_hash, sender),
)).await;
receiver.await.map_err(|_| Error::ClosedChannelAwaitingInherentData)
};
let mut timeout = futures_timer::Delay::new(PROPOSE_TIMEOUT).fuse();
select! {
pid = pid.fuse() => pid,
_ = timeout => Err(Error::Timeout),
}
}
}
impl<TxPool, Backend, Client> sp_consensus::Proposer<Block> for Proposer<TxPool, Backend, Client>
where
TxPool: 'static + TransactionPool<Block = Block>,
Client: 'static
+ BlockBuilderProvider<Backend, Block, Client>
+ ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ Send
+ Sync,
Client::Api:
BlockBuilderApi<Block> + ApiExt<Block>,
Backend:
'static + sc_client_api::Backend<Block, State = sp_api::StateBackendFor<Client, Block>>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor<Client, Block>: sp_api::StateBackend<HashFor<Block>> + Send,
{
type Transaction = sc_client_api::TransactionFor<Backend, Block>;
type Proposal = Pin<Box<
dyn Future<Output = Result<Proposal<Block, sp_api::TransactionFor<Client, Block>, ()>, Error>> + Send,
>>;
type Error = Error;
type ProofRecording = DisableProofRecording;
type Proof = ();
fn propose(
self,
mut inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
max_duration: time::Duration,
block_size_limit: Option<usize>,
) -> Self::Proposal {
async move {
let span = jaeger::Span::new(self.parent_header_hash, "propose");
let _span = span.child("get-provisioner");
let parachains_inherent_data = match self.get_provisioner_data().await {
Ok(pd) => ParachainsInherentData {
bitfields: pd.bitfields,
backed_candidates: pd.backed_candidates,
disputes: pd.disputes,
parent_header: self.parent_header,
},
Err(err) => {
tracing::warn!(err = ?err, "could not get provisioner inherent data; injecting default data");
ParachainsInherentData {
bitfields: Vec::new(),
backed_candidates: Vec::new(),
disputes: Vec::new(),
parent_header: self.parent_header,
}
}
};
drop(_span);
inherent_data.put_data(
polkadot_primitives::v1::PARACHAINS_INHERENT_IDENTIFIER,
&parachains_inherent_data,
)?;
let _span = span.child("authorship-propose");
self.inner
.propose(inherent_data, inherent_digests, max_duration, block_size_limit)
.await
.map_err(Into::into)
}
.boxed()
}
}
// It would have been more ergonomic to use thiserror to derive the
// From implementations, Display, and std::error::Error, but unfortunately
// one of the wrapped errors (sp_inherents::Error) also
// don't impl std::error::Error, which breaks the thiserror derive.
#[derive(Debug)]
pub enum Error {
Consensus(sp_consensus::Error),
Blockchain(sp_blockchain::Error),
Inherent(sp_inherents::Error),
Timeout,
ClosedChannelAwaitingActivation,
ClosedChannelAwaitingInherentData,
Subsystem(SubsystemError)
}
impl From<sp_consensus::Error> for Error {
fn from(e: sp_consensus::Error) -> Error {
Error::Consensus(e)
}
}
impl From<sp_blockchain::Error> for Error {
fn from(e: sp_blockchain::Error) -> Error {
Error::Blockchain(e)
}
}
impl From<sp_inherents::Error> for Error {
fn from(e: sp_inherents::Error) -> Error {
Error::Inherent(e)
}
}
impl From<SubsystemError> for Error {
fn from(e: SubsystemError) -> Error {
Error::Subsystem(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Consensus(err) => write!(f, "consensus error: {}", err),
Self::Blockchain(err) => write!(f, "blockchain error: {}", err),
Self::Inherent(err) => write!(f, "inherent error: {:?}", err),
Self::Timeout => write!(f, "timeout: provisioner did not return inherent data after {:?}", PROPOSE_TIMEOUT),
Self::ClosedChannelAwaitingActivation => write!(f, "closed channel from overseer when awaiting activation"),
Self::ClosedChannelAwaitingInherentData => write!(f, "closed channel from provisioner when awaiting inherent data"),
Self::Subsystem(err) => write!(f, "subsystem error: {:?}", err),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Consensus(err) => Some(err),
Self::Blockchain(err) => Some(err),
Self::Subsystem(err) => Some(err),
_ => None
}
}
}
......@@ -445,7 +445,6 @@ impl OverseerHandler {
}
/// Wait for a block with the given hash to be in the active-leaves set.
/// This method is used for external code like `Proposer` that doesn't subscribe to Overseer's signals.
///
/// The response channel responds if the hash was activated and is closed if the hash was deactivated.
/// Note that due the fact the overseer doesn't store the whole active-leaves set, only deltas,
......
......@@ -15,6 +15,7 @@ sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "
sc-chain-spec = { 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-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
......@@ -22,12 +23,12 @@ sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-basic-authorship = { 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" }
# Substrate Primitives
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master" }
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master" }
......@@ -43,6 +44,8 @@ sp-session = { git = "https://github.com/paritytech/substrate", branch = "master
sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
# Substrate Pallets
......@@ -67,7 +70,7 @@ kvdb = "0.9.0"
kvdb-rocksdb = { version = "0.11.0", optional = true }
# Polkadot
polkadot-node-core-proposer = { path = "../core/proposer" }
polkadot-node-core-parachains-inherent = { path = "../core/parachains-inherent" }
polkadot-overseer = { path = "../overseer" }
polkadot-parachain = { path = "../../parachain" }
polkadot-primitives = { path = "../../primitives" }
......
......@@ -18,7 +18,7 @@
use rococo::constants::size::MAX_CODE_SIZE;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use babe_primitives::AuthorityId as BabeId;
use sp_consensus_babe::AuthorityId as BabeId;
use beefy_primitives::ecdsa::AuthorityId as BeefyId;
use grandpa::AuthorityId as GrandpaId;
use hex_literal::hex;
......
......@@ -32,7 +32,7 @@ use consensus_common::BlockStatus;
pub trait RuntimeApiCollection:
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ babe_primitives::BabeApi<Block>
+ sp_consensus_babe::BabeApi<Block>
+ grandpa_primitives::GrandpaApi<Block>
+ ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
......@@ -52,7 +52,7 @@ impl<Api> RuntimeApiCollection for Api
where
Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ babe_primitives::BabeApi<Block>
+ sp_consensus_babe::BabeApi<Block>
+ grandpa_primitives::GrandpaApi<Block>
+ ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
......
......@@ -32,7 +32,6 @@ 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_proposer::ProposerFactory,
polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandler},
polkadot_primitives::v1::ParachainHost,
sc_authority_discovery::Service as AuthorityDiscoveryService,
......@@ -41,7 +40,7 @@ use {
sp_trie::PrefixedMemoryDB,
sc_client_api::{AuxStore, ExecutorProvider},
sc_keystore::LocalKeystore,
babe_primitives::BabeApi,
sp_consensus_babe::BabeApi,
grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider},
beefy_primitives::ecdsa::AuthoritySignature as BeefySignature,
sp_runtime::traits::Header as HeaderT,
......@@ -263,8 +262,6 @@ fn new_partial<RuntimeApi, Executor>(
set_prometheus_registry(config)?;