Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1180420
move SelectChain trait out of client
gnunicorn Apr 5, 2019
b204874
Extend SelectChain, move longest chain implementation into it
gnunicorn Apr 5, 2019
32c0c72
Bring SelectChain into service
gnunicorn Apr 9, 2019
1bfeb83
implement LongestChain SelectChain
gnunicorn Apr 9, 2019
a46acc6
implement longest chain for node
gnunicorn Apr 9, 2019
30bab5f
Merge remote-tracking branch 'origin/master' into ben-custom-chainsel…
gnunicorn Apr 9, 2019
30f5528
update Cargo.lock's
gnunicorn Apr 9, 2019
4cf2abf
in between erroring tests
gnunicorn Apr 12, 2019
5ff112a
deprecate ::backend and ::import_lock
gnunicorn Apr 12, 2019
a2b0dd1
Remove unneded space
bkchr Apr 12, 2019
2db6163
Remove unneded space
bkchr Apr 12, 2019
f1c4225
Fixes test compilation
bkchr Apr 12, 2019
d2f21a4
remove todo
gnunicorn Apr 12, 2019
097905a
re-enable client test
gnunicorn Apr 12, 2019
1c870e1
add doc
gnunicorn Apr 12, 2019
59fbf03
fixing tests
gnunicorn Apr 12, 2019
326a8c3
Clarify SelectChain Interface, intended implementation and usage
gnunicorn Apr 12, 2019
5fb7a09
minor components cleanups
gnunicorn Apr 12, 2019
e6f8ed2
minor cleanups
gnunicorn Apr 12, 2019
d92d542
Update lock files
gnunicorn Apr 12, 2019
f45a8b7
Merge branch 'master' into ben-custom-chainselection-strategy
gnunicorn May 6, 2019
f9c94a5
Implement cleaner interface for SelectChain
gnunicorn May 6, 2019
1de5c64
addressing comments
gnunicorn May 6, 2019
2b52445
Updating tests
gnunicorn May 6, 2019
38f8f65
bump node runtime impl version
gnunicorn May 6, 2019
c7bdc40
Merge branch 'master' into ben-custom-chainselection-strategy
gnunicorn May 7, 2019
a307363
Merge branch 'master' into ben-custom-chainselection-strategy
gavofyork May 9, 2019
09bb8a8
address grumbles
gnunicorn May 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
671 changes: 415 additions & 256 deletions core/client/src/client.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion core/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ pub use crate::client::{
new_with_backend,
new_in_mem,
BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents,
BlockImportNotification, Client, ClientInfo, ChainHead, ExecutionStrategies,
BlockImportNotification, Client, ClientInfo, ExecutionStrategies,
LongestChain
};
#[cfg(feature = "std")]
pub use crate::notifications::{StorageEventStream, StorageChangeSet};
Expand Down
29 changes: 18 additions & 11 deletions core/consensus/aura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@
//!
//! Blocks from future steps will be either deferred or rejected depending on how
//! far in the future they are.
#![deny(warnings)]
#![forbid(missing_docs, unsafe_code)]
use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug};

use parity_codec::{Encode, Decode};
use consensus_common::{self, Authorities, BlockImport, Environment, Proposer,
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
SelectChain, well_known_cache_keys
};
use consensus_common::well_known_cache_keys;
use consensus_common::import_queue::{Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport};
use client::{
ChainHead,
block_builder::api::BlockBuilder as BlockBuilderApi,
blockchain::ProvideCache,
runtime_api::{ApiExt, Core as CoreApi},
Expand Down Expand Up @@ -182,10 +180,11 @@ impl SlotCompatible for AuraSlotCompatible {

/// Start the aura worker in a separate thread.
#[deprecated(since = "1.1", note = "Please spawn a thread manually")]
pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>(
pub fn start_aura_thread<B, C, SC, E, I, P, SO, Error, OnExit>(
slot_duration: SlotDuration,
local_key: Arc<P>,
client: Arc<C>,
select_chain: SC,
block_import: Arc<I>,
env: Arc<E>,
sync_oracle: SO,
Expand All @@ -194,8 +193,9 @@ pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>(
force_authoring: bool,
) -> Result<(), consensus_common::Error> where
B: Block + 'static,
C: ChainHead<B> + ProvideRuntimeApi + ProvideCache<B> + Send + Sync + 'static,
C: ProvideRuntimeApi + ProvideCache<B> + Send + Sync + 'static,
C::Api: AuthoritiesApi<B>,
SC: SelectChain<B> + Clone + 'static,
E: Environment<B, Error=Error> + Send + Sync + 'static,
E::Proposer: Proposer<B, Error=Error> + Send + 'static,
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
Expand All @@ -222,7 +222,7 @@ pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>(
#[allow(deprecated)] // The function we are in is also deprecated.
slots::start_slot_worker_thread::<_, _, _, _, AuraSlotCompatible, u64, _>(
slot_duration.0,
client,
select_chain,
Arc::new(worker),
sync_oracle,
on_exit,
Expand All @@ -231,10 +231,11 @@ pub fn start_aura_thread<B, C, E, I, P, SO, Error, OnExit>(
}

/// Start the aura worker. The returned future should be run in a tokio runtime.
pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>(
pub fn start_aura<B, C, SC, E, I, P, SO, Error, OnExit>(
slot_duration: SlotDuration,
local_key: Arc<P>,
client: Arc<C>,
select_chain: SC,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately, this breaks API. We will have to find a way to do this that doesn't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this change will inevitably break the api - as it needs to be specified and at the service-intend-layer and somehow pushed down to the authoring and finalisation. Even if we tried to still have client facilitate this somehow, this would mean adding the same SC on every Where C: Client<...SC>, which would also break this same call.

I am afraid there is just no way around this breaking the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing we could do is have client implement the new trait as well and hard-code that to the LongestChain implementation and directly deprecate its usage. But then still, would the where clause later on have to change to the new trait and thus, this would still break the API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately, this breaks API. We will have to find a way to do this that doesn't.

There are hacky ways to do it by stuffing the information into mutable state, such as a thread-local variable. None of those are good, but we can avoid future breaking changes by switching to the builder pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently the blocker for me on this PR. I am not sure how we even can resolve this without creating a huge other mess elsewhere.

The only way I can currently think of is by having a compatibility layer, that is Client implements LongestChain SC, however in that case, a) the where clause still needs to be extended (and that is "breaking the API", as it now constrains more than it was before) and b) it would mean this function doesn't actually allow any other implementation and thus isn't really implementing the ticket (or solving our problem).

Not sure what to do about this?!?

block_import: Arc<I>,
env: Arc<E>,
sync_oracle: SO,
Expand All @@ -243,8 +244,9 @@ pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>(
force_authoring: bool,
) -> Result<impl Future<Item=(), Error=()>, consensus_common::Error> where
B: Block,
C: ChainHead<B> + ProvideRuntimeApi + ProvideCache<B>,
C: ProvideRuntimeApi + ProvideCache<B>,
C::Api: AuthoritiesApi<B>,
SC: SelectChain<B> + Clone,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
Expand All @@ -268,7 +270,7 @@ pub fn start_aura<B, C, E, I, P, SO, Error, OnExit>(
};
slots::start_slot_worker::<_, _, _, _, _, AuraSlotCompatible, _>(
slot_duration.0,
client,
select_chain,
Arc::new(worker),
sync_oracle,
on_exit,
Expand Down Expand Up @@ -804,7 +806,7 @@ mod tests {
use tokio::runtime::current_thread;
use keyring::sr25519::Keyring;
use primitives::sr25519;
use client::BlockchainEvents;
use client::{LongestChain, BlockchainEvents};
use test_client;

type Error = client::error::Error;
Expand Down Expand Up @@ -916,6 +918,10 @@ mod tests {
let mut runtime = current_thread::Runtime::new().unwrap();
for (peer_id, key) in peers {
let client = net.lock().peer(*peer_id).client().clone();
let select_chain = LongestChain::new(
client.backend().clone(),
client.import_lock().clone(),
);
let environ = Arc::new(DummyFactory(client.clone()));
import_notifications.push(
client.import_notification_stream()
Expand All @@ -931,10 +937,11 @@ mod tests {
&inherent_data_providers, slot_duration.get()
).expect("Registers aura inherent data provider");

let aura = start_aura::<_, _, _, _, sr25519::Pair, _, _, _>(
let aura = start_aura::<_, _, _, _, _, sr25519::Pair, _, _, _>(
slot_duration,
Arc::new(key.clone().into()),
client.clone(),
select_chain,
client,
environ.clone(),
DummyOracle,
Expand Down
24 changes: 16 additions & 8 deletions core/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ use srml_babe::{
BabeInherentData,
timestamp::{TimestampInherentData, InherentType as TimestampInherent}
};
use consensus_common::well_known_cache_keys;
use consensus_common::{SelectChain, well_known_cache_keys};
use consensus_common::import_queue::{Verifier, BasicQueue};
use client::{
ChainHead,
block_builder::api::BlockBuilder as BlockBuilderApi,
blockchain::ProvideCache,
runtime_api::ApiExt,
Expand Down Expand Up @@ -249,7 +248,7 @@ impl SlotCompatible for BabeSlotCompatible {
}

/// Parameters for BABE.
pub struct BabeParams<C, E, I, SO, OnExit> {
pub struct BabeParams<C, E, I, SO, SC, OnExit> {

/// The configuration for BABE. Includes the slot duration, threshold, and
/// other parameters.
Expand All @@ -261,6 +260,9 @@ pub struct BabeParams<C, E, I, SO, OnExit> {
/// The client to use
pub client: Arc<C>,

/// The SelectChain Strategy
pub select_chain: SC,

/// A block importer
pub block_import: Arc<I>,

Expand All @@ -281,28 +283,30 @@ pub struct BabeParams<C, E, I, SO, OnExit> {
}

/// Start the babe worker. The returned future should be run in a tokio runtime.
pub fn start_babe<B, C, E, I, SO, Error, OnExit>(BabeParams {
pub fn start_babe<B, C, E, I, SO, SC, Error, OnExit>(BabeParams {
config,
local_key,
client,
select_chain,
block_import,
env,
sync_oracle,
on_exit,
inherent_data_providers,
force_authoring,
}: BabeParams<C, E, I, SO, OnExit>) -> Result<
}: BabeParams<C, E, I, SO, SC, OnExit>) -> Result<
impl Future<Item=(), Error=()>,
consensus_common::Error,
> where
B: Block,
C: ChainHead<B> + ProvideRuntimeApi + ProvideCache<B>,
C: ProvideRuntimeApi + ProvideCache<B>,
C::Api: AuthoritiesApi<B>,
E: Environment<B, Error=Error>,
E::Proposer: Proposer<B, Error=Error>,
<<E::Proposer as Proposer<B>>::Create as IntoFuture>::Future: Send + 'static,
I: BlockImport<B> + Send + Sync + 'static,
SO: SyncOracle + Send + Sync + Clone,
SC: SelectChain<B>,
DigestItemFor<B>: CompatibleDigestItem + DigestItem<AuthorityId=Public>,
Error: ::std::error::Error + Send + From<::consensus_common::Error> + From<I::Error> + 'static,
OnExit: Future<Item=(), Error=()>,
Expand All @@ -319,7 +323,7 @@ pub fn start_babe<B, C, E, I, SO, Error, OnExit>(BabeParams {
};
slots::start_slot_worker::<_, _, _, _, _, BabeSlotCompatible, _>(
config.0,
client,
select_chain,
Arc::new(worker),
sync_oracle,
on_exit,
Expand Down Expand Up @@ -847,10 +851,13 @@ fn claim_slot(
}

#[cfg(test)]
#[allow(dead_code, unused_imports)]
#[allow(dead_code, unused_imports, deprecated)]
// FIXME #2532: need to allow deprecated until refactor is done https://github.com/paritytech/substrate/issues/2532

mod tests {
use super::*;

use client::LongestChain;
use consensus_common::NoNetwork as DummyOracle;
use network::test::*;
use network::test::{Block as TestBlock, PeersClient};
Expand Down Expand Up @@ -1014,6 +1021,7 @@ mod tests {
config,
local_key: Arc::new(key.clone().into()),
block_import: client.clone(),
select_chain: LongestChain::new(client.backend().clone(), client.import_lock().clone()),
client,
env: environ.clone(),
sync_oracle: DummyOracle,
Expand Down
6 changes: 6 additions & 0 deletions core/consensus/common/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,11 @@ error_chain! {
description("Import failed"),
display("Import failed: {}", reason),
}

/// Error from the client while importing
ChainLookup(reason: String) {
description("Looking up chain failed"),
display("Chain lookup failed: {}", reason),
}
}
}
2 changes: 2 additions & 0 deletions core/consensus/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub use inherents::InherentData;
pub mod offline_tracker;
pub mod error;
mod block_import;
mod select_chain;
pub mod import_queue;
pub mod evaluation;

Expand All @@ -50,6 +51,7 @@ pub use self::error::{Error, ErrorKind};
pub use block_import::{
BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, ImportBlock, ImportResult, JustificationImport,
};
pub use select_chain::SelectChain;

/// Trait for getting the authorities at a given block.
pub trait Authorities<B: Block> {
Expand Down
54 changes: 54 additions & 0 deletions core/consensus/common/src/select_chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate Consensus Common.

// Substrate Demo 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 Consensus Common 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 Substrate Consensus Common. If not, see <http://www.gnu.org/licenses/>.

use crate::error::Error;
use runtime_primitives::traits::{Block as BlockT, NumberFor};


/// The SelectChain trait defines the strategy upon which the head is chosen
/// if multiple forks are present for an opaque definition of "best" in the
/// specific chain build.
///
/// The Strategy can be customised for the two use cases of authoring new blocks
/// upon the best chain or which fork to finalise. Unless implemented differently
/// by default finalisation methods fall back to use authoring, so as a minimum
/// `_authoring`-functions must be implemented.
///
/// Any particular user must make explicit, however, whether they intend to finalise
/// or author through the using the right function call, as these might differ in
/// some implementations.
///
/// Non-deterministicly finalising chains may only use the `_authoring` functions.
pub trait SelectChain<Block: BlockT>: Sync + Send + Clone {

/// Get all leaves of the chain: block hashes that have no children currently.
/// Leaves that can never be finalized will not be returned.
fn leaves(&self) -> Result<Vec<<Block as BlockT>::Hash>, Error>;

/// Among those `leaves` deterministically pick one chain as the generally
/// best chain to author new blocks upon and probably finalize.
fn best_chain(&self) -> Result<<Block as BlockT>::Header, Error>;

/// Get the best ancestor of `target_hash` that we should attempt
/// to finalize next.
fn finality_target(
&self,
target_hash: <Block as BlockT>::Hash,
_maybe_max_number: Option<NumberFor<Block>>
) -> Result<Option<<Block as BlockT>::Hash>, Error> {
Ok(Some(target_hash))
}
}
10 changes: 5 additions & 5 deletions core/consensus/rhd/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::thread;
use std::time::{Duration, Instant};
use std::sync::Arc;

use client::{BlockchainEvents, ChainHead, BlockBody};
use client::{BlockchainEvents, BlockBody};
use futures::prelude::*;
use transaction_pool::txpool::{Pool as TransactionPool, ChainApi as PoolChainApi};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, BlockNumberToHash};
Expand All @@ -33,7 +33,7 @@ use tokio::runtime::current_thread::Runtime as LocalRuntime;
use tokio::timer::Interval;

use parking_lot::RwLock;
use consensus::offline_tracker::OfflineTracker;
use consensus::{self, offline_tracker::OfflineTracker};

use super::{Network, ProposerFactory, AuthoringApi};
use {consensus, primitives, ed25519, error, BftService, LocalProposer};
Expand Down Expand Up @@ -87,9 +87,9 @@ impl Service {
A: AuthoringApi + BlockNumberToHash + 'static,
P: PoolChainApi<Block = <A as AuthoringApi>::Block> + 'static,
C: BlockchainEvents<<A as AuthoringApi>::Block>
+ ChainHead<<A as AuthoringApi>::Block>
+ BlockBody<<A as AuthoringApi>::Block>,
C: consensus::BlockImport<<A as AuthoringApi>::Block>
+ BlockBody<<A as AuthoringApi>::Block>
+ consensus::SelectChain<<A as AuthoringApi>::Block>
+ consensus::BlockImport<<A as AuthoringApi>::Block>
+ consensus::Authorities<<A as AuthoringApi>::Block> + Send + Sync + 'static,
primitives::H256: From<<<A as AuthoringApi>::Block as BlockT>::Hash>,
<<A as AuthoringApi>::Block as BlockT>::Hash: PartialEq<primitives::H256> + PartialEq,
Expand Down
Loading