Make basic collation working

This commit is contained in:
Bastian Köcher
2019-10-18 14:16:32 +02:00
parent d9c6bc408c
commit b5bc9a21a3
12 changed files with 506 additions and 292 deletions
+6
View File
@@ -7,6 +7,9 @@ edition = "2018"
[dependencies]
# Substrate dependencies
sr-primitives = { package = "sr-primitives", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
substrate-primitives = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
substrate-client = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
substrate-service = { git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
consensus-common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
cli = { package = "substrate-cli", git = "https://github.com/paritytech/substrate", branch = "bkchr-cumulus-branch" }
@@ -15,6 +18,9 @@ cli = { package = "substrate-cli", git = "https://github.com/paritytech/substrat
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" }
# Cumulus dependencies
cumulus-consensus = { path = "../consensus" }
# other deps
log = "0.4.8"
codec = { package = "parity-scale-codec", version = "1.0.6", features = [ "derive" ] }
+91 -57
View File
@@ -19,12 +19,14 @@
use sr_primitives::traits::Block as BlockT;
use consensus_common::{Environment, Proposer};
use inherents::InherentDataProviders;
use substrate_primitives::Blake2Hasher;
use polkadot_collator::{
InvalidHead, ParachainContext, BuildParachainContext, Network as CollatorNetwork, VersionInfo,
TaskExecutor, PolkadotClient,
};
use polkadot_primitives::{
Hash,
Hash as PHash, Block as PBlock,
parachain::{
self, BlockData, Message, Id as ParaId, OutgoingMessages, Status as ParachainStatus,
CollatorPair,
@@ -33,12 +35,12 @@ use polkadot_primitives::{
use codec::{Decode, Encode};
use log::error;
use log::{error, trace};
use futures03::TryFutureExt;
use futures::{Future, future::IntoFuture};
use std::{sync::Arc, marker::PhantomData, time::Duration};
use std::{sync::Arc, marker::PhantomData, time::Duration, fmt::Debug};
use parking_lot::Mutex;
@@ -85,29 +87,30 @@ impl<Block, PF> Clone for Collator<Block, PF> {
impl<Block, PF> ParachainContext for Collator<Block, PF> where
Block: BlockT,
PF: Environment<Block> + 'static + Send + Sync,
PF::Error: std::fmt::Debug,
PF::Proposer: Send + Sync,
<PF::Proposer as Proposer<Block>>::Create: Unpin + Send + Sync,
PF: Environment<Block> + 'static + Send,
PF::Error: Debug,
<PF::Proposer as Proposer<Block>>::Create: Unpin + Send,
{
type ProduceCandidate = Box<
dyn Future<Item=(BlockData, parachain::HeadData, OutgoingMessages), Error=InvalidHead>
+ Send + Sync
+ Send
>;
fn produce_candidate<I: IntoIterator<Item=(ParaId, Message)>>(
&mut self,
_relay_chain_parent: Hash,
_relay_chain_parent: PHash,
status: ParachainStatus,
_: I,
) -> Self::ProduceCandidate {
trace!(target: "cumulus-collator", "Producing candidate");
let factory = self.proposer_factory.clone();
let inherent_providers = self.inherent_data_providers.clone();
let res = HeadData::<Block>::decode(&mut &status.head_data.0[..])
.map_err(|_| InvalidHead)
.into_future()
.and_then(move |last_head|
.and_then(move |last_head| {
factory.lock()
.init(&last_head.header)
.map_err(|e| {
@@ -115,34 +118,41 @@ impl<Block, PF> ParachainContext for Collator<Block, PF> where
error!("Could not create proposer: {:?}", e);
InvalidHead
})
)
.and_then(move |proposer|
inherent_providers.create_inherent_data()
.map(|id| (proposer, id))
.map_err(|e| {
error!("Failed to create inherent data: {:?}", e);
InvalidHead
.and_then(|mut proposer| {
error!("PROPOSING");
let inherent_data = inherent_providers.create_inherent_data()
.map_err(|e| {
error!("Failed to create inherent data: {:?}", e);
InvalidHead
})?;
let future = proposer.propose(
inherent_data,
Default::default(),
//TODO: Fix this.
Duration::from_secs(6),
)
.map_err(|e| {
error!("Proposing failed: {:?}", e);
InvalidHead
})
.compat();
Ok(future)
})
)
.and_then(|(mut proposer, inherent_data)| {
proposer.propose(
inherent_data,
Default::default(),
//TODO: Fix this.
Duration::from_secs(6),
)
.map_err(|e| {
error!("Proposing failed: {:?}", e);
InvalidHead
})
.compat()
})
.flatten()
.map(|b| {
error!("BUILDING BLOCKDATA");
let block_data = BlockData(b.encode());
let head_data = HeadData::<Block> { header: b.deconstruct().0 };
let messages = OutgoingMessages { outgoing_messages: Vec::new() };
(block_data, parachain::HeadData(head_data.encode()), messages)
})
.then(|r| {
trace!(target: "cumulus-collator", "Produced candidate: {:?}", r);
r
});
Box::new(res)
@@ -150,41 +160,66 @@ impl<Block, PF> ParachainContext for Collator<Block, PF> where
}
/// Implements `BuildParachainContext` to build a collator instance.
struct CollatorBuilder<Block, PF> {
inherent_data_providers: InherentDataProviders,
proposer_factory: PF,
_phantom: PhantomData<Block>,
struct CollatorBuilder<Block, SP> {
setup_parachain: SP,
_marker: PhantomData<Block>,
}
impl<Block, PF> CollatorBuilder<Block, PF> {
impl<Block, SP> CollatorBuilder<Block, SP> {
/// Create a new instance of self.
fn new(proposer_factory: PF, inherent_data_providers: InherentDataProviders) -> Self {
fn new(setup_parachain: SP) -> Self {
Self {
inherent_data_providers,
proposer_factory,
_phantom: Default::default(),
setup_parachain,
_marker: PhantomData,
}
}
}
impl<Block, PF> BuildParachainContext for CollatorBuilder<Block, PF> where
Block: BlockT,
PF: Environment<Block> + 'static + Send + Sync,
PF::Error: std::fmt::Debug,
PF::Proposer: Send + Sync,
<PF::Proposer as Proposer<Block>>::Create: Unpin + Send + Sync,
impl<Block: BlockT, SP: SetupParachain<Block>> BuildParachainContext for CollatorBuilder<Block, SP>
where
<<SP::ProposerFactory as Environment<Block>>::Proposer as Proposer<Block>>::Create: Send + Unpin,
<SP::ProposerFactory as Environment<Block>>::Error: Debug,
{
type ParachainContext = Collator<Block, PF>;
type ParachainContext = Collator<Block, SP::ProposerFactory>;
fn build(self, network: Arc<dyn CollatorNetwork>) -> Result<Self::ParachainContext, ()> {
Ok(Collator::new(self.proposer_factory, self.inherent_data_providers, network))
fn build<B, E>(
self,
client: Arc<PolkadotClient<B, E>>,
task_executor: TaskExecutor,
network: Arc<dyn CollatorNetwork>,
) -> Result<Self::ParachainContext, ()>
where
B: substrate_client::backend::Backend<PBlock, Blake2Hasher> + 'static,
E: substrate_client::CallExecutor<PBlock, Blake2Hasher> + Clone + Send + Sync + 'static
{
let (proposer_factory, inherent_data_providers) = self.setup_parachain
.setup_parachain(client, task_executor)
.map_err(|e| error!("Error setting up the parachain: {}", e))?;
Ok(Collator::new(proposer_factory, inherent_data_providers, network))
}
}
/// Something that can setup a parachain.
pub trait SetupParachain<Block: BlockT>: Send
where
<<Self::ProposerFactory as Environment<Block>>::Proposer as Proposer<Block>>::Create: Send + Unpin,
<Self::ProposerFactory as Environment<Block>>::Error: Debug,
{
/// The proposer factory of the parachain to build blocks.
type ProposerFactory: Environment<Block> + Send + 'static;
/// Setup the parachain.
fn setup_parachain<P: cumulus_consensus::PolkadotClient>(
self,
polkadot_client: P,
task_executor: TaskExecutor,
) -> Result<(Self::ProposerFactory, InherentDataProviders), String>;
}
/// Run a collator with the given proposer factory.
pub fn run_collator<Block, PF, E, I>(
proposer_factory: PF,
inherent_data_providers: InherentDataProviders,
pub fn run_collator<Block, SP, E>(
setup_parachain: SP,
para_id: ParaId,
exit: E,
key: Arc<CollatorPair>,
@@ -192,14 +227,13 @@ pub fn run_collator<Block, PF, E, I>(
) -> Result<(), cli::error::Error>
where
Block: BlockT,
PF: Environment<Block> + 'static + Send + Sync,
PF::Error: std::fmt::Debug,
PF::Proposer: Send + Sync,
<PF::Proposer as Proposer<Block>>::Create: Unpin + Send + Sync,
SP: SetupParachain<Block> + Send + 'static,
<<SP::ProposerFactory as Environment<Block>>::Proposer as Proposer<Block>>::Create: Send + Unpin,
<SP::ProposerFactory as Environment<Block>>::Error: Debug,
E: IntoFuture<Item=(), Error=()>,
E::Future: Send + Clone + Sync + 'static,
{
let builder = CollatorBuilder::new(proposer_factory, inherent_data_providers);
let builder = CollatorBuilder::new(setup_parachain);
polkadot_collator::run_collator(builder, para_id, exit, key, version)
}
@@ -273,7 +307,7 @@ mod tests {
unimplemented!("Not required in tests")
}
fn checked_statements(&self, _: Hash) ->
fn checked_statements(&self, _: PHash) ->
Box<dyn Stream<Item=SignedStatement, Error=()>>
{
unimplemented!("Not required in tests")