diff --git a/cumulus/Cargo.lock b/cumulus/Cargo.lock index 91e5863708..074888b192 100644 --- a/cumulus/Cargo.lock +++ b/cumulus/Cargo.lock @@ -528,15 +528,14 @@ dependencies = [ name = "cumulus-collator" version = "0.1.0" dependencies = [ + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-collator 0.1.0 (git+https://github.com/paritytech/polkadot?branch=bkchr-cumulus-branch)", "polkadot-primitives 0.1.0 (git+https://github.com/paritytech/polkadot?branch=bkchr-cumulus-branch)", "sr-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", - "substrate-client 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", "substrate-consensus-common 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", - "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", - "substrate-transaction-pool 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", + "substrate-inherents 2.0.0 (git+https://github.com/paritytech/substrate?branch=bkchr-cumulus-branch)", ] [[package]] diff --git a/cumulus/collator/Cargo.toml b/cumulus/collator/Cargo.toml new file mode 100644 index 0000000000..8a7ae282a6 --- /dev/null +++ b/cumulus/collator/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "cumulus-collator" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +# Substrate dependencies +runtime-primitives = { package = "sr-primitives", 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" } + +# Polkadot dependencies +polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "bkchr-cumulus-branch" } + +# other deps +log = "0.4.6" +codec = { package = "parity-codec", version = "3.5.1", features = [ "derive" ] } +futures = "0.1.27" \ No newline at end of file diff --git a/cumulus/collator/src/lib.rs b/cumulus/collator/src/lib.rs new file mode 100644 index 0000000000..19d49ee53e --- /dev/null +++ b/cumulus/collator/src/lib.rs @@ -0,0 +1,126 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Cumulus. If not, see . + +//! Cumulus Collator implementation for Substrate. + +use runtime_primitives::traits::Block as BlockT; +use consensus_common::{Environment, Proposer}; + +use polkadot_collator::{InvalidHead, ParachainContext}; +use polkadot_primitives::parachain::{self, BlockData, Message, Id as ParaId, Extrinsic}; + +use codec::{Decode, Encode}; +use log::error; +use futures::{Future, future::IntoFuture}; + +use std::{sync::Arc, marker::PhantomData, time::Duration}; + +/// The head data of the parachain, stored in the relay chain. +#[derive(Decode, Encode, Debug)] +struct HeadData { + header: Block::Header, +} + +/// The implementation of the Cumulus `Collator`. +pub struct Collator { + proposer_factory: Arc, + _phantom: PhantomData, + inherent_data_providers: inherents::InherentDataProviders, +} + +impl> Collator { + /// Create a new instance. + fn new( + proposer_factory: Arc, + inherent_data_providers: inherent_data::InherentDataProviders + ) -> Self { + Self { + proposer_factory, + inherent_data_providers, + _phantom: PhantomData, + } + } +} + +impl Clone for Collator { + fn clone(&self) -> Self { + Self { + proposer_factory: self.proposer_factory.clone(), + inherent_data_providers: self.inherent_data_providers.clone(), + _phantom: PhantomData, + } + } +} + +impl ParachainContext for Collator +where + Block: BlockT, + PF: Environment + 'static, + PF::Error: std::fmt::Debug, +{ + type ProduceCandidate = Box< + dyn Future + >; + + fn produce_candidate>( + &self, + last_head: parachain::HeadData, + _: I, + ) -> Self::ProduceCandidate { + let factory = self.proposer_factory.clone(); + let inherent_providers = self.inherent_data_providers.clone(); + + let res = HeadData::::decode(&mut &last_head.0[..]) + .ok_or_else(|| InvalidHead).into_future() + .and_then(move |last_head| + factory.init(&last_head.header).map_err(|e| { + //TODO: Do we want to return the real error? + 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(|(proposer, inherent_data)| { + proposer.propose( + inherent_data, + Default::default(), + //TODO: Fix this. + Duration::from_secs(6), + ) + .into_future() + .map_err(|e| { + error!("Proposing failed: {:?}", e); + InvalidHead + }) + }) + .map(|b| { + let block_data = BlockData(b.encode()); + let head_data = HeadData:: { header: b.deconstruct().0 }; + let extrinsic = Extrinsic { outgoing_messages: Vec::new() }; + + (block_data, parachain::HeadData(head_data.encode()), extrinsic) + }); + + Box::new(res) + } +} \ No newline at end of file