From b92dd8130064e08d901e3203074d97176bc4fac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 27 Jun 2019 23:55:40 +0200 Subject: [PATCH] Introduce `BuildParachainContext` trait (#302) * Introduce `BuildParachainContext` trait * Change the structure and hide the actual network implementation behind a trait * Add functions to collator `Network` trait --- polkadot/Cargo.lock | 1 + polkadot/collator/Cargo.toml | 1 + polkadot/collator/src/lib.rs | 99 ++++++++++++++----- polkadot/network/src/validation.rs | 2 + .../adder/collator/src/main.rs | 21 +++- 5 files changed, 93 insertions(+), 31 deletions(-) diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index 6c7d330107..f501c491f1 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -2308,6 +2308,7 @@ dependencies = [ "substrate-consensus-aura 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-consensus-common 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-keyring 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "substrate-network 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/polkadot/collator/Cargo.toml b/polkadot/collator/Cargo.toml index 822b326ec7..47c0ad2efa 100644 --- a/polkadot/collator/Cargo.toml +++ b/polkadot/collator/Cargo.toml @@ -10,6 +10,7 @@ futures = "0.1.17" client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } parity-codec = "3.0" primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } +substrate-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } consensus_common = { package = "substrate-consensus-common", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } aura = { package = "substrate-consensus-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } polkadot-runtime = { path = "../runtime", version = "0.1" } diff --git a/polkadot/collator/src/lib.rs b/polkadot/collator/src/lib.rs index 20c254b348..d898a86fbc 100644 --- a/polkadot/collator/src/lib.rs +++ b/polkadot/collator/src/lib.rs @@ -53,14 +53,18 @@ use futures::{future, Stream, Future, IntoFuture}; use log::{info, warn}; use client::BlockchainEvents; use primitives::{ed25519, Pair}; -use polkadot_primitives::{BlockId, SessionKey, Hash, Block}; -use polkadot_primitives::parachain::{ - self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, Extrinsic, - PoVBlock, Status as ParachainStatus, +use polkadot_primitives::{ + BlockId, SessionKey, Hash, Block, + parachain::{ + self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, Extrinsic, + PoVBlock, Status as ParachainStatus, + } }; -use polkadot_cli::{PolkadotService, CustomConfiguration, ParachainHost}; -use polkadot_cli::{Worker, IntoExit, ProvideRuntimeApi, TaskExecutor}; -use polkadot_network::validation::{ValidationNetwork, SessionParams}; +use polkadot_cli::{ + Worker, IntoExit, ProvideRuntimeApi, TaskExecutor, PolkadotService, CustomConfiguration, + ParachainHost, +}; +use polkadot_network::validation::{SessionParams, ValidationNetwork}; use polkadot_network::NetworkService; use tokio::timer::Timeout; use consensus_common::SelectChain; @@ -68,9 +72,41 @@ use aura::AuraApi; pub use polkadot_cli::VersionInfo; pub use polkadot_network::validation::Incoming; +pub use polkadot_validation::SignedStatement; +pub use polkadot_primitives::parachain::CollatorId; +pub use substrate_network::PeerId; const COLLATION_TIMEOUT: Duration = Duration::from_secs(30); +/// An abstraction over the `Network` with useful functions for a `Collator`. +pub trait Network { + /// Convert the given `CollatorId` to a `PeerId`. + fn collator_id_to_peer_id(&self, collator_id: CollatorId) -> + Box, Error=()> + Send>; + + /// Create a `Stream` of checked statements for the given `relay_parent`. + /// + /// The returned stream will not terminate, so it is required to make sure that the stream is + /// dropped when it is not required anymore. Otherwise, it will stick around in memory + /// infinitely. + fn checked_statements(&self, relay_parent: Hash) -> Box>; +} + +impl Network for ValidationNetwork where + P: 'static, + E: 'static, +{ + fn collator_id_to_peer_id(&self, collator_id: CollatorId) -> + Box, Error=()> + Send> + { + Box::new(Self::collator_id_to_peer_id(self, collator_id)) + } + + fn checked_statements(&self, relay_parent: Hash) -> Box> { + Box::new(Self::checked_statements(self, relay_parent)) + } +} + /// Error to return when the head data was invalid. #[derive(Clone, Copy, Debug)] pub struct InvalidHead; @@ -93,6 +129,15 @@ impl fmt::Display for Error { } } +/// 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(self, network: Arc) -> Result; +} + /// Parachain context needed for collation. /// /// This can be implemented through an externally attached service or a stub. @@ -114,7 +159,7 @@ pub trait ParachainContext: Clone { /// This encapsulates a network and local database which may store /// some of the input. pub trait RelayChainContext { - type Error: ::std::fmt::Debug; + type Error: std::fmt::Debug; /// Future that resolves to the un-routed egress queues of a parachain. /// The first item is the oldest. @@ -182,7 +227,7 @@ pub fn collate<'a, R, P>( /// Polkadot-api context. struct ApiContext { - network: ValidationNetwork, + network: Arc>, parent_hash: Hash, authorities: Vec, } @@ -210,14 +255,13 @@ impl RelayChainContext for ApiContext where } struct CollationNode { - parachain_context: P, + build_parachain_context: P, exit: E, para_id: ParaId, key: Arc, } impl IntoExit for CollationNode where - P: ParachainContext + Send + 'static, E: Future + Send + 'static { type Exit = E; @@ -227,11 +271,12 @@ impl IntoExit for CollationNode where } impl Worker for CollationNode where - P: ParachainContext + Send + 'static, - E: Future + Clone + Send + Sync + 'static, - ::Future: Send + 'static, + P: BuildParachainContext + Send + 'static, + P::ParachainContext: Send + 'static, + <::ProduceCandidate as IntoFuture>::Future: Send + 'static, + E: Future + Clone + Send + Sync + 'static, { - type Work = Box + Send>; + type Work = Box + Send>; fn configuration(&self) -> CustomConfiguration { let mut config = CustomConfiguration::default(); @@ -242,10 +287,10 @@ impl Worker for CollationNode where config } - fn work(self, service: &S, task_executor: TaskExecutor) -> Self::Work - where S: PolkadotService, + fn work(self, service: &S, task_executor: TaskExecutor) -> Self::Work where + S: PolkadotService, { - let CollationNode { parachain_context, exit, para_id, key } = self; + let CollationNode { build_parachain_context, exit, para_id, key } = self; let client = service.client(); let network = service.network(); let known_oracle = client.clone(); @@ -278,14 +323,15 @@ impl Worker for CollationNode where }, ); - let validation_network = ValidationNetwork::new( + let validation_network = Arc::new(ValidationNetwork::new( network.clone(), exit.clone(), message_validator, client.clone(), task_executor, - ); + )); + let parachain_context = build_parachain_context.build(validation_network.clone()).unwrap(); let inner_exit = exit.clone(); let work = client.import_notification_stream() .for_each(move |notification| { @@ -376,27 +422,28 @@ fn compute_targets(para_id: ParaId, session_keys: &[SessionKey], roster: DutyRos .collect() } -/// Run a collator node with the given `RelayChainContext` and `ParachainContext` and -/// arguments to the underlying polkadot node. +/// Run a collator node with the given `RelayChainContext` and `ParachainContext` +/// build by the given `BuildParachainContext` and arguments to the underlying polkadot node. /// /// Provide a future which resolves when the node should exit. /// This function blocks until done. pub fn run_collator( - parachain_context: P, + build_parachain_context: P, para_id: ParaId, exit: E, key: Arc, args: I, version: VersionInfo, ) -> polkadot_cli::error::Result<()> where - P: ParachainContext + Send + 'static, - ::Future: Send + 'static, + P: BuildParachainContext + Send + 'static, + P::ParachainContext: Send + 'static, + <::ProduceCandidate as IntoFuture>::Future: Send + 'static, E: IntoFuture, E::Future: Send + Clone + Sync + 'static, I: IntoIterator, ArgT: Into + Clone, { - let node_logic = CollationNode { parachain_context, exit: exit.into_future(), para_id, key }; + let node_logic = CollationNode { build_parachain_context, exit: exit.into_future(), para_id, key }; polkadot_cli::run(args, node_logic, version) } diff --git a/polkadot/network/src/validation.rs b/polkadot/network/src/validation.rs index 8150b34411..e0f7e04d1b 100644 --- a/polkadot/network/src/validation.rs +++ b/polkadot/network/src/validation.rs @@ -288,7 +288,9 @@ impl ValidationNetwork where rx } +} +impl ValidationNetwork where N: NetworkService { /// Convert the given `CollatorId` to a `PeerId`. pub fn collator_id_to_peer_id(&self, collator_id: CollatorId) -> impl Future, Error=()> + Send diff --git a/polkadot/test-parachains/adder/collator/src/main.rs b/polkadot/test-parachains/adder/collator/src/main.rs index 2692ee2601..64c3de3860 100644 --- a/polkadot/test-parachains/adder/collator/src/main.rs +++ b/polkadot/test-parachains/adder/collator/src/main.rs @@ -23,17 +23,20 @@ use std::sync::Arc; use adder::{HeadData as AdderHead, BlockData as AdderBody}; use substrate_primitives::Pair; use parachain::codec::{Encode, Decode}; -use primitives::Hash; -use primitives::parachain::{ - HeadData, BlockData, Id as ParaId, Message, Extrinsic, Status as ParachainStatus, +use primitives::{ + Hash, + parachain::{HeadData, BlockData, Id as ParaId, Message, Extrinsic, Status as ParachainStatus}, }; -use collator::{InvalidHead, ParachainContext, VersionInfo}; +use collator::{InvalidHead, ParachainContext, VersionInfo, Network, BuildParachainContext}; use parking_lot::Mutex; const GENESIS: AdderHead = AdderHead { number: 0, parent_hash: [0; 32], - post_state: [1, 27, 77, 3, 221, 140, 1, 241, 4, 145, 67, 207, 156, 76, 129, 126, 75, 22, 127, 29, 27, 131, 229, 198, 240, 241, 13, 137, 186, 30, 123, 206], + post_state: [ + 1, 27, 77, 3, 221, 140, 1, 241, 4, 145, 67, 207, 156, 76, 129, 126, 75, + 22, 127, 29, 27, 131, 229, 198, 240, 241, 13, 137, 186, 30, 123, 206 + ], }; const GENESIS_BODY: AdderBody = AdderBody { @@ -93,6 +96,14 @@ impl ParachainContext for AdderContext { } } +impl BuildParachainContext for AdderContext { + type ParachainContext = Self; + + fn build(self, _: Arc) -> Result { + Ok(self) + } +} + fn main() { let key = Arc::new(Pair::from_seed(&[1; 32])); let id: ParaId = 100.into();