Plumb polkadot backend into cumulus-collator (#269)

* The problem in the nutshell

* Make it compile

* make tests pass

* Update the parachain-upgrade module

* Fix collator tests

Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
Sergei Shulepov
2020-12-21 20:27:54 +01:00
committed by GitHub
parent bfad1abe8b
commit f0315a16d3
11 changed files with 95 additions and 26 deletions
+3
View File
@@ -1140,6 +1140,7 @@ dependencies = [
"sp-inherents",
"sp-io",
"sp-runtime",
"sp-state-machine",
"sp-std",
"sp-version",
"substrate-test-runtime-client",
@@ -1159,6 +1160,7 @@ dependencies = [
"sp-inherents",
"sp-runtime",
"sp-std",
"sp-trie",
]
[[package]]
@@ -1232,6 +1234,7 @@ dependencies = [
"sp-inherents",
"sp-keyring",
"sp-runtime",
"sp-state-machine",
"sp-test-primitives",
"sp-timestamp",
"substrate-test-client",
+37 -12
View File
@@ -61,7 +61,7 @@ type TransactionFor<E, Block> =
<<E as Environment<Block>>::Proposer as Proposer<Block>>::Transaction;
/// The implementation of the Cumulus `Collator`.
pub struct Collator<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient> {
pub struct Collator<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient, PBackend2> {
para_id: ParaId,
proposer_factory: Arc<Mutex<PF>>,
_phantom: PhantomData<(Block, PBackend)>,
@@ -71,10 +71,11 @@ pub struct Collator<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient> {
wait_to_announce: Arc<Mutex<WaitToAnnounce<Block>>>,
backend: Arc<Backend>,
polkadot_client: Arc<PClient>,
polkadot_backend: Arc<PBackend2>,
}
impl<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient> Clone
for Collator<Block, PF, BI, BS, Backend, PBackend, PClient>
impl<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient, PBackend2> Clone
for Collator<Block, PF, BI, BS, Backend, PBackend, PClient, PBackend2>
{
fn clone(&self) -> Self {
Self {
@@ -87,12 +88,13 @@ impl<Block: BlockT, PF, BI, BS, Backend, PBackend, PClient> Clone
wait_to_announce: self.wait_to_announce.clone(),
backend: self.backend.clone(),
polkadot_client: self.polkadot_client.clone(),
polkadot_backend: self.polkadot_backend.clone(),
}
}
}
impl<Block, PF, BI, BS, Backend, PBackend, PApi, PClient>
Collator<Block, PF, BI, BS, Backend, PBackend, PClient>
impl<Block, PF, BI, BS, Backend, PBackend, PApi, PClient, PBackend2>
Collator<Block, PF, BI, BS, Backend, PBackend, PClient, PBackend2>
where
Block: BlockT,
PF: Environment<Block> + 'static + Send,
@@ -110,6 +112,8 @@ where
PBackend::State: StateBackend<BlakeTwo256>,
PApi: RuntimeApiCollection<StateBackend = PBackend::State>,
PClient: polkadot_service::AbstractClient<PBlock, PBackend, Api = PApi> + 'static,
PBackend2: sc_client_api::Backend<PBlock> + 'static,
PBackend2::State: StateBackend<BlakeTwo256>,
{
/// Create a new instance.
fn new(
@@ -123,6 +127,7 @@ where
announce_block: Arc<dyn Fn(Block::Hash, Vec<u8>) + Send + Sync>,
backend: Arc<Backend>,
polkadot_client: Arc<PClient>,
polkadot_backend: Arc<PBackend2>,
) -> Self {
let wait_to_announce = Arc::new(Mutex::new(WaitToAnnounce::new(
spawner,
@@ -140,6 +145,7 @@ where
wait_to_announce,
backend,
polkadot_client,
polkadot_backend,
}
}
@@ -208,8 +214,17 @@ where
})
.ok()?;
let validation_data = {
// TODO: Actual proof is to be created in the upcoming PRs.
let relay_chain_state = sp_state_machine::StorageProof::empty();
inherents::ValidationDataType {
validation_data: validation_data.clone(),
relay_chain_state,
}
};
inherent_data
.put_data(VALIDATION_DATA_IDENTIFIER, validation_data)
.put_data(VALIDATION_DATA_IDENTIFIER, &validation_data)
.map_err(|e| {
error!(
target: "cumulus-collator",
@@ -507,7 +522,7 @@ where
}
/// Parameters for [`start_collator`].
pub struct StartCollatorParams<Block: BlockT, PF, BI, Backend, Client, BS, Spawner, PClient> {
pub struct StartCollatorParams<Block: BlockT, PF, BI, Backend, Client, BS, Spawner, PClient, PBackend> {
pub proposer_factory: PF,
pub inherent_data_providers: InherentDataProviders,
pub backend: Arc<Backend>,
@@ -520,6 +535,7 @@ pub struct StartCollatorParams<Block: BlockT, PF, BI, Backend, Client, BS, Spawn
pub para_id: ParaId,
pub key: CollatorPair,
pub polkadot_client: Arc<PClient>,
pub polkadot_backend: Arc<PBackend>,
}
pub async fn start_collator<
@@ -532,6 +548,7 @@ pub async fn start_collator<
Spawner,
PClient,
PBackend,
PBackend2,
PApi,
>(
StartCollatorParams {
@@ -547,7 +564,8 @@ pub async fn start_collator<
para_id,
key,
polkadot_client,
}: StartCollatorParams<Block, PF, BI, Backend, Client, BS, Spawner, PClient>,
polkadot_backend,
}: StartCollatorParams<Block, PF, BI, Backend, Client, BS, Spawner, PClient, PBackend2>,
) -> Result<(), String>
where
PF: Environment<Block> + Send + 'static,
@@ -570,6 +588,8 @@ where
PBackend::State: StateBackend<BlakeTwo256>,
PApi: RuntimeApiCollection<StateBackend = PBackend::State>,
PClient: polkadot_service::AbstractClient<PBlock, PBackend, Api = PApi> + 'static,
PBackend2: sc_client_api::Backend<PBlock> + 'static,
PBackend2::State: StateBackend<BlakeTwo256>,
{
let follow = match cumulus_consensus::follow_polkadot(
para_id,
@@ -594,6 +614,7 @@ where
announce_block,
backend,
polkadot_client,
polkadot_backend,
);
let config = CollationGenerationConfig {
@@ -725,24 +746,27 @@ mod tests {
spawner.spawn("overseer", overseer.run().then(|_| async { () }).boxed());
let (polkadot_client, relay_parent) = {
let (polkadot_client, polkadot_backend, relay_parent) = {
// Create a polkadot client with a block imported.
use polkadot_test_client::{
ClientBlockImportExt as _, DefaultTestClientBuilderExt as _,
InitPolkadotBlockBuilder as _, TestClientBuilderExt as _,
};
let mut client = polkadot_test_client::TestClientBuilder::new().build();
let client_builder = polkadot_test_client::TestClientBuilder::new();
let polkadot_backend = client_builder.backend();
let mut client = client_builder.build();
let block_builder = client.init_polkadot_block_builder();
let block = block_builder.build().expect("Finalizes the block").block;
let hash = block.header().hash();
client
.import_as_best(BlockOrigin::Own, block)
.expect("Imports the block");
(client, hash)
(client, polkadot_backend, hash)
};
let collator_start =
start_collator::<_, _, _, _, _, _, _, _, polkadot_service::FullBackend, _>(
start_collator::<_, _, _, _, _, _, _, _, polkadot_service::FullBackend, _, _>(
StartCollatorParams {
proposer_factory: DummyFactory(client.clone()),
inherent_data_providers: Default::default(),
@@ -756,6 +780,7 @@ mod tests {
para_id,
key: CollatorPair::generate().0,
polkadot_client: Arc::new(polkadot_client),
polkadot_backend,
},
);
block_on(collator_start).expect("Should start collator");
+2
View File
@@ -23,6 +23,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Other Dependencies
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"]}
@@ -45,6 +46,7 @@ std = [
'sp-runtime/std',
'sp-io/std',
'sp-std/std',
'sp-state-machine/std',
'frame-system/std',
'cumulus-primitives/std',
]
+16 -4
View File
@@ -30,7 +30,7 @@
//! Users must ensure that they register this pallet as an inherent provider.
use cumulus_primitives::{
inherents::VALIDATION_DATA_IDENTIFIER as INHERENT_IDENTIFIER,
inherents::{ValidationDataType, VALIDATION_DATA_IDENTIFIER as INHERENT_IDENTIFIER},
well_known_keys::{NEW_VALIDATION_CODE, VALIDATION_DATA},
OnValidationData, ValidationData,
};
@@ -106,10 +106,15 @@ decl_module! {
/// As a side effect, this function upgrades the current validation function
/// if the appropriate time has come.
#[weight = (0, DispatchClass::Mandatory)]
fn set_validation_data(origin, vfp: ValidationData) {
fn set_validation_data(origin, data: ValidationDataType) {
ensure_none(origin)?;
assert!(!DidUpdateValidationData::exists(), "ValidationData must be updated only once in a block");
let ValidationDataType {
validation_data: vfp,
relay_chain_state,
} = data;
// initialization logic: we know that this runs exactly once every block,
// which means we can put the initialization logic here to remove the
// sequencing problem.
@@ -123,6 +128,10 @@ decl_module! {
storage::unhashed::put(VALIDATION_DATA, &vfp);
DidUpdateValidationData::put(true);
// TODO: here we should extract the key value pairs out of the storage proof.
drop(relay_chain_state);
<T::OnValidationData as OnValidationData>::on_validation_data(vfp);
}
@@ -219,7 +228,7 @@ impl<T: Config> ProvideInherent for Module<T> {
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let data: ValidationData = data
let data: ValidationDataType = data
.get_data(&INHERENT_IDENTIFIER)
.ok()
.flatten()
@@ -489,7 +498,10 @@ mod tests {
let inherent_data = {
let mut inherent_data = InherentData::default();
inherent_data
.put_data(INHERENT_IDENTIFIER, &vfp)
.put_data(INHERENT_IDENTIFIER, &ValidationDataType {
validation_data: vfp.clone(),
relay_chain_state: sp_state_machine::StorageProof::empty(),
})
.expect("failed to put VFP inherent");
inherent_data
};
+2
View File
@@ -11,6 +11,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sc-chain-spec = { git = "https://github.com/paritytech/substrate", optional = true, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Polkadot dependencies
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
@@ -35,4 +36,5 @@ std = [
"polkadot-core-primitives/std",
"sp-runtime/std",
"sp-core/std",
"sp-trie/std",
]
+8 -1
View File
@@ -57,7 +57,14 @@ pub mod inherents {
/// The identifier for the `set_validation_data` inherent.
pub const VALIDATION_DATA_IDENTIFIER: InherentIdentifier = *b"valfunp0";
/// The type of the inherent.
pub type ValidationDataType = crate::ValidationData;
#[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq)]
pub struct ValidationDataType {
pub validation_data: crate::ValidationData,
/// A storage proof of a predefined set of keys from the relay-chain.
///
/// The set of keys is TBD
pub relay_chain_state: sp_trie::StorageProof,
}
}
/// Well known keys for values in the storage.
+3
View File
@@ -187,6 +187,8 @@ where
);
let spawner = task_manager.spawn_handle();
let polkadot_backend = polkadot_full_node.backend.clone();
let params = StartCollatorParams {
para_id: id,
block_import: client.clone(),
@@ -200,6 +202,7 @@ where
polkadot_full_node,
spawner,
backend,
polkadot_backend,
};
start_collator(params).await?;
+16 -7
View File
@@ -23,7 +23,7 @@ use futures::{Future, FutureExt};
use polkadot_overseer::OverseerHandler;
use polkadot_primitives::v1::{Block as PBlock, CollatorId, CollatorPair};
use polkadot_service::{AbstractClient, Client as PClient, ClientHandle, RuntimeApiCollection};
use sc_client_api::{Backend as BackendT, BlockBackend, Finalizer, UsageProvider};
use sc_client_api::{Backend as BackendT, BlockBackend, Finalizer, UsageProvider, StateBackend};
use sc_service::{error::Result as ServiceResult, Configuration, Role, TaskManager};
use sp_blockchain::HeaderBackend;
use sp_consensus::{BlockImport, Environment, Error as ConsensusError, Proposer};
@@ -36,7 +36,7 @@ use std::{marker::PhantomData, sync::Arc};
type PFullNode<C> = polkadot_service::NewFull<C>;
/// Parameters given to [`start_collator`].
pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, Spawner, PClient> {
pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend> {
pub proposer_factory: PF,
pub inherent_data_providers: InherentDataProviders,
pub backend: Arc<Backend>,
@@ -49,6 +49,7 @@ pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, S
pub collator_key: CollatorPair,
pub polkadot_full_node: PFullNode<PClient>,
pub task_manager: &'a mut TaskManager,
pub polkadot_backend: Arc<PBackend>,
}
/// Start a collator node for a parachain.
@@ -56,7 +57,7 @@ pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, S
/// A collator is similar to a validator in a normal blockchain.
/// It is responsible for producing blocks and sending the blocks to a
/// parachain validator for validation and inclusion into the relay chain.
pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient>(
pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend>(
StartCollatorParams {
proposer_factory,
inherent_data_providers,
@@ -70,7 +71,8 @@ pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PCl
collator_key,
polkadot_full_node,
task_manager,
}: StartCollatorParams<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient>,
polkadot_backend,
}: StartCollatorParams<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend>,
) -> sc_service::error::Result<()>
where
Block: BlockT,
@@ -94,6 +96,8 @@ where
Backend: BackendT<Block> + 'static,
Spawner: SpawnNamed + Clone + Send + Sync + 'static,
PClient: ClientHandle,
PBackend: BackendT<PBlock> + 'static,
PBackend::State: StateBackend<BlakeTwo256>,
{
polkadot_full_node
.client
@@ -111,6 +115,7 @@ where
collator_key,
block_import,
block_status,
polkadot_backend,
})
.await?;
@@ -119,7 +124,7 @@ where
Ok(())
}
struct StartCollator<Block: BlockT, Client, Backend, PF, BI, BS, Spawner> {
struct StartCollator<Block: BlockT, Client, Backend, PF, BI, BS, Spawner, PBackend> {
proposer_factory: PF,
inherent_data_providers: InherentDataProviders,
backend: Arc<Backend>,
@@ -131,10 +136,11 @@ struct StartCollator<Block: BlockT, Client, Backend, PF, BI, BS, Spawner> {
spawner: Spawner,
para_id: ParaId,
collator_key: CollatorPair,
polkadot_backend: Arc<PBackend>,
}
impl<Block, Client, Backend, PF, BI, BS, Spawner> polkadot_service::ExecuteWithClient
for StartCollator<Block, Client, Backend, PF, BI, BS, Spawner>
impl<Block, Client, Backend, PF, BI, BS, Spawner, PBackend2> polkadot_service::ExecuteWithClient
for StartCollator<Block, Client, Backend, PF, BI, BS, Spawner, PBackend2>
where
Block: BlockT,
PF: Environment<Block> + Send + 'static,
@@ -156,6 +162,8 @@ where
for<'b> &'b Client: BlockImport<Block>,
Backend: BackendT<Block> + 'static,
Spawner: SpawnNamed + Clone + Send + Sync + 'static,
PBackend2: sc_client_api::Backend<PBlock> + 'static,
PBackend2::State: sp_api::StateBackend<BlakeTwo256>,
{
type Output = std::pin::Pin<Box<dyn Future<Output = ServiceResult<()>>>>;
@@ -181,6 +189,7 @@ where
para_id: self.para_id,
key: self.collator_key,
polkadot_client: client,
polkadot_backend: self.polkadot_backend,
})
.await
.map_err(Into::into)
+1
View File
@@ -17,6 +17,7 @@ sp-test-primitives = { git = "https://github.com/paritytech/substrate", branch =
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
+5 -2
View File
@@ -15,7 +15,7 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
use crate::Client;
use cumulus_primitives::{inherents::VALIDATION_DATA_IDENTIFIER, ValidationData};
use cumulus_primitives::{inherents::{VALIDATION_DATA_IDENTIFIER, ValidationDataType}, ValidationData};
use cumulus_test_runtime::GetLastTimestamp;
use polkadot_primitives::v1::BlockNumber as PBlockNumber;
use sc_block_builder::BlockBuilderApi;
@@ -47,7 +47,10 @@ pub fn generate_block_inherents(
inherent_data
.put_data(
VALIDATION_DATA_IDENTIFIER,
&validation_data.unwrap_or_default(),
&ValidationDataType {
validation_data: validation_data.unwrap_or_default(),
relay_chain_state: sp_state_machine::StorageProof::empty(),
},
)
.expect("Put validation function params failed");
+2
View File
@@ -223,6 +223,7 @@ where
prometheus_registry.as_ref(),
);
let polkadot_backend = polkadot_full_node.backend.clone();
let params = StartCollatorParams {
proposer_factory,
inherent_data_providers: params.inherent_data_providers,
@@ -236,6 +237,7 @@ where
para_id,
collator_key,
polkadot_full_node,
polkadot_backend,
};
start_collator(params).await?;