From 1c104e05687ac8f8d8b7f6e8f4421acb0ab7ddc3 Mon Sep 17 00:00:00 2001 From: Simon Littlejohns <39836665+simonljs@users.noreply.github.com> Date: Mon, 17 Dec 2018 17:51:40 +0000 Subject: [PATCH] =?UTF-8?q?Consensus=20data=20added=20with=20generic=20use?= =?UTF-8?q?=20in=20service/src/consensus.rs.=20Th=E2=80=A6=20(#1274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Consensus data added with generic use in service/src/consensus.rs. This may need to change. * refactor consensus service a bit --- substrate/Cargo.lock | 1 + .../core/consensus/aura/primitives/src/lib.rs | 10 ++++ substrate/core/consensus/aura/src/lib.rs | 23 +++++---- substrate/core/consensus/common/src/lib.rs | 10 ++-- substrate/core/service/Cargo.toml | 1 + substrate/core/service/src/consensus.rs | 47 +++++++++++++++++-- substrate/core/service/src/lib.rs | 1 + 7 files changed, 76 insertions(+), 17 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index f7f3248a4b..0f64e18959 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -3646,6 +3646,7 @@ dependencies = [ "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-client-db 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", "substrate-keystore 0.1.0", diff --git a/substrate/core/consensus/aura/primitives/src/lib.rs b/substrate/core/consensus/aura/primitives/src/lib.rs index 8b8c494441..54e4149f52 100644 --- a/substrate/core/consensus/aura/primitives/src/lib.rs +++ b/substrate/core/consensus/aura/primitives/src/lib.rs @@ -33,6 +33,16 @@ pub mod id { pub const AURA_API: ApiId = *b"aura_api"; } +/// Aura consensus environmental data. Useful for block-proposing code. +pub struct AuraConsensusData { + /// The timestamp the block should be authored with. + pub timestamp: u64, + /// The slot number. + pub slot: u64, + /// The duration of the slot, in seconds. + pub slot_duration: u64, +} + /// Runtime-APIs pub mod api { use client::decl_runtime_apis; diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index dc6fd41fea..f22e20930c 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -72,6 +72,7 @@ use futures::{Stream, Future, IntoFuture, future::{self, Either}}; use tokio::timer::{Delay, Timeout}; use api::AuraApi; +pub use aura_primitives::AuraConsensusData; pub use consensus_common::SyncOracle; /// A handle to the network. This is generally implemented by providing some @@ -159,8 +160,8 @@ pub fn start_aura_thread( ) where B: Block + 'static, C: Authorities + ChainHead + Send + Sync + 'static, - E: Environment + Send + Sync + 'static, - E::Proposer: Proposer + 'static, + E: Environment + Send + Sync + 'static, + E::Proposer: Proposer + 'static, I: BlockImport + Send + Sync + 'static, Error: From + From + 'static, SO: SyncOracle + Send + Clone + 'static, @@ -202,8 +203,8 @@ pub fn start_aura( ) -> impl Future where B: Block, C: Authorities + ChainHead, - E: Environment, - E::Proposer: Proposer, + E: Environment, + E::Proposer: Proposer, I: BlockImport, Error: From + From, SO: SyncOracle + Send + Clone, @@ -287,10 +288,16 @@ pub fn start_aura( } }; + let consensus_data = AuraConsensusData { + timestamp, + slot: slot_num, + slot_duration, + }; + // deadline our production to approx. the end of the // slot Timeout::new( - proposer.propose().into_future(), + proposer.propose(consensus_data).into_future(), time_until_next(Duration::from_secs(timestamp), slot_duration), ) } else { @@ -634,7 +641,7 @@ mod tests { struct DummyFactory(Arc); struct DummyProposer(u64, Arc); - impl Environment for DummyFactory { + impl Environment for DummyFactory { type Proposer = DummyProposer; type Error = Error; @@ -645,11 +652,11 @@ mod tests { } } - impl Proposer for DummyProposer { + impl Proposer for DummyProposer { type Error = Error; type Create = Result; - fn propose(&self) -> Result { + fn propose(&self, _consensus_data: AuraConsensusData) -> Result { self.1.new_block().unwrap().bake().map_err(|e| e.into()) } } diff --git a/substrate/core/consensus/common/src/lib.rs b/substrate/core/consensus/common/src/lib.rs index fdba87b1c7..76c370effd 100644 --- a/substrate/core/consensus/common/src/lib.rs +++ b/substrate/core/consensus/common/src/lib.rs @@ -59,9 +59,9 @@ pub trait Authorities { } /// Environment producer for a Consensus instance. Creates proposer instance and communication streams. -pub trait Environment { +pub trait Environment { /// The proposer type this creates. - type Proposer: Proposer; + type Proposer: Proposer; /// Error which can occur upon creation. type Error: From; @@ -76,13 +76,15 @@ pub trait Environment { /// /// This will encapsulate creation and evaluation of proposals at a specific /// block. -pub trait Proposer { +/// +/// Proposers are generic over bits of "consensus data" which are engine-specific. +pub trait Proposer { /// Error type which can occur when proposing or evaluating. type Error: From + ::std::fmt::Debug + 'static; /// Future that resolves to a committed proposal. type Create: IntoFuture; /// Create a proposal. - fn propose(&self) -> Self::Create; + fn propose(&self, consensus_data: ConsensusData) -> Self::Create; } /// An oracle for when major synchronization work is being undertaken. diff --git a/substrate/core/service/Cargo.toml b/substrate/core/service/Cargo.toml index 8a1a8146af..ca8766c707 100644 --- a/substrate/core/service/Cargo.toml +++ b/substrate/core/service/Cargo.toml @@ -21,6 +21,7 @@ sr-io = { path = "../../core/sr-io" } sr-primitives = { path = "../../core/sr-primitives" } substrate-primitives = { path = "../../core/primitives" } substrate-consensus-common = { path = "../../core/consensus/common" } +substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives" } substrate-network = { path = "../../core/network" } substrate-client = { path = "../../core/client" } substrate-client-db = { path = "../../core/client/db" } diff --git a/substrate/core/service/src/consensus.rs b/substrate/core/service/src/consensus.rs index fd3c44ae07..5f8d189878 100644 --- a/substrate/core/service/src/consensus.rs +++ b/substrate/core/service/src/consensus.rs @@ -31,6 +31,7 @@ use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as Heade use runtime_primitives::generic::BlockId; use runtime_primitives::BasicInherentData; use transaction_pool::txpool::{self, Pool as TransactionPool}; +use aura_primitives::AuraConsensusData; type Timestamp = u64; @@ -111,11 +112,12 @@ pub struct ProposerFactory where A: txpool::ChainApi { pub transaction_pool: Arc>, } -impl consensus_common::Environment<::Block> for ProposerFactory where +impl consensus_common::Environment<::Block, ConsensusData> for ProposerFactory where C: AuthoringApi, ::Api: BlockBuilderApi<::Block, BasicInherentData>, A: txpool::ChainApi::Block>, - client::error::Error: From<::Error> + client::error::Error: From<::Error>, + Proposer<::Block, C, A>: consensus_common::Proposer<::Block, ConsensusData>, { type Proposer = Proposer<::Block, C, A>; type Error = error::Error; @@ -144,6 +146,10 @@ impl consensus_common::Environment<::Block> for Propose } } +struct ConsensusData { + timestamp: Option, +} + /// The proposer logic. pub struct Proposer { client: Arc, @@ -153,7 +159,7 @@ pub struct Proposer { transaction_pool: Arc>, } -impl consensus_common::Proposer<::Block> for Proposer where +impl consensus_common::Proposer<::Block, AuraConsensusData> for Proposer where Block: BlockT, C: AuthoringApi, ::Api: BlockBuilderApi, @@ -163,10 +169,41 @@ impl consensus_common::Proposer<::Block> for Pro type Create = Result<::Block, error::Error>; type Error = error::Error; - fn propose(&self) -> Result<::Block, error::Error> { + fn propose(&self, consensus_data: AuraConsensusData) + -> Result<::Block, error::Error> + { + self.propose_with(ConsensusData { timestamp: Some(consensus_data.timestamp) }) + } +} + +impl consensus_common::Proposer<::Block, ()> for Proposer where + Block: BlockT, + C: AuthoringApi, + ::Api: BlockBuilderApi, + A: txpool::ChainApi, + client::error::Error: From<::Error> +{ + type Create = Result<::Block, error::Error>; + type Error = error::Error; + + fn propose(&self, _consensus_data: ()) -> Result<::Block, error::Error> { + self.propose_with(ConsensusData { timestamp: None }) + } +} + +impl Proposer where + Block: BlockT, + C: AuthoringApi, + ::Api: BlockBuilderApi, + A: txpool::ChainApi, + client::error::Error: From<::Error>, +{ + fn propose_with(&self, consensus_data: ConsensusData) + -> Result<::Block, error::Error> + { use runtime_primitives::traits::BlakeTwo256; - let timestamp = current_timestamp(); + let timestamp = consensus_data.timestamp.unwrap_or_else(current_timestamp); let inherent_data = BasicInherentData::new(timestamp, 0); let block = self.client.build_block( diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 1d6a0f139b..9421fcb8d0 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -34,6 +34,7 @@ extern crate substrate_client as client; extern crate substrate_client_db as client_db; extern crate parity_codec as codec; extern crate substrate_transaction_pool as transaction_pool; +extern crate substrate_consensus_aura_primitives as aura_primitives; extern crate substrate_rpc_servers as rpc; extern crate target_info; extern crate tokio;