diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 7f8c81d5abea514d69ba7781597836f60a1160af..b0dfb939d07c1ef6d61c65774d5c88f2e1546d5a 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -25,7 +25,7 @@ use runtime_primitives::{ Justification, generic::{BlockId, SignedBlock}, }; -use consensus::{Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, BlockOrigin}; +use consensus::{Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, BlockOrigin, ForkChoiceStrategy}; use runtime_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem, @@ -544,6 +544,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where authorities: Option<Vec<AuthorityId>>, finalized: bool, aux: Vec<(Vec<u8>, Option<Vec<u8>>)>, + fork_choice: ForkChoiceStrategy, ) -> error::Result<ImportResult> where E: CallExecutor<Block, Blake2Hasher> + Send + Sync + Clone, { @@ -608,7 +609,10 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where }; // TODO: non longest-chain rule. - let is_new_best = finalized || import_headers.post().number() > &last_best_number; + let is_new_best = finalized || match fork_choice { + ForkChoiceStrategy::LongestChain => import_headers.post().number() > &last_best_number, + ForkChoiceStrategy::Custom(v) => v, + }; let leaf_state = if finalized { ::backend::NewBlockState::Final } else if is_new_best { @@ -1038,6 +1042,7 @@ impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA> body, finalized, auxiliary, + fork_choice, } = import_block; assert!(justification.is_some() && finalized || justification.is_none()); @@ -1074,6 +1079,7 @@ impl<B, E, Block, RA> consensus::BlockImport<Block> for Client<B, E, Block, RA> new_authorities, finalized, auxiliary, + fork_choice, ); *self.importing_block.write() = None; diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index 911ae6304a320fae10a9ebfd084913fa32ff36b6..b57dab030c76fa401f4c046a770e71459a1acde4 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -61,7 +61,7 @@ use std::sync::Arc; use std::time::Duration; use codec::Encode; -use consensus_common::{Authorities, BlockImport, Environment, Error as ConsensusError, Proposer}; +use consensus_common::{Authorities, BlockImport, Environment, Error as ConsensusError, Proposer, ForkChoiceStrategy}; use consensus_common::import_queue::{Verifier, BasicQueue}; use client::ChainHead; use client::block_builder::api::BlockBuilder as BlockBuilderApi; @@ -324,6 +324,7 @@ pub fn start_aura<B, C, E, I, SO, Error>( body: Some(body), finalized: false, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; if let Err(e) = block_import.import_block(import_block, None) { @@ -524,6 +525,7 @@ impl<B: Block, C, E, MakeInherent, Inherent> Verifier<B> for AuraVerifier<C, E, finalized: false, justification, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; // FIXME: extract authorities - https://github.com/paritytech/substrate/issues/1019 diff --git a/substrate/core/consensus/common/src/block_import.rs b/substrate/core/consensus/common/src/block_import.rs index 1f7f814a8ea43b3ff64295081c2e242a482b1ce6..488112f0ebe024c99fc1208f1053829eceec94bd 100644 --- a/substrate/core/consensus/common/src/block_import.rs +++ b/substrate/core/consensus/common/src/block_import.rs @@ -53,6 +53,15 @@ pub enum BlockOrigin { File, } +/// Fork choice strategy. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum ForkChoiceStrategy { + /// Longest chain fork choice. + LongestChain, + /// Custom fork choice rule, where true indicates the new block should be the best block. + Custom(bool), +} + /// Data required to import a Block pub struct ImportBlock<Block: BlockT> { /// Origin of the Block @@ -83,6 +92,8 @@ pub struct ImportBlock<Block: BlockT> { /// Contains a list of key-value pairs. If values are `None`, the keys /// will be deleted. pub auxiliary: Vec<(Vec<u8>, Option<Vec<u8>>)>, + /// Fork choice strategy of this import. + pub fork_choice: ForkChoiceStrategy, } impl<Block: BlockT> ImportBlock<Block> { diff --git a/substrate/core/consensus/common/src/lib.rs b/substrate/core/consensus/common/src/lib.rs index 875f4c216aec44c03a6ab64ba5237e5fb5422f96..e9b5d82951f624f81cd5b7b01e3dcb73fc078fe1 100644 --- a/substrate/core/consensus/common/src/lib.rs +++ b/substrate/core/consensus/common/src/lib.rs @@ -55,7 +55,7 @@ pub mod evaluation; const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024; pub use self::error::{Error, ErrorKind}; -pub use block_import::{BlockImport, ImportBlock, BlockOrigin, ImportResult}; +pub use block_import::{BlockImport, ImportBlock, BlockOrigin, ImportResult, ForkChoiceStrategy}; /// Trait for getting the authorities at a given block. pub trait Authorities<B: Block> { diff --git a/substrate/core/network/src/test/mod.rs b/substrate/core/network/src/test/mod.rs index b2beba05db732fb2f2639de327b4e62ece10990b..94518978bc0915d11b05f0269f9c318ef6749129 100644 --- a/substrate/core/network/src/test/mod.rs +++ b/substrate/core/network/src/test/mod.rs @@ -38,7 +38,7 @@ use service::{NetworkLink, TransactionPool}; use network_libp2p::{NodeIndex, PeerId, Severity}; use keyring::Keyring; use codec::Encode; -use consensus::{BlockImport, BlockOrigin, ImportBlock}; +use consensus::{BlockImport, BlockOrigin, ImportBlock, ForkChoiceStrategy}; use consensus::Error as ConsensusError; use consensus::import_queue::{import_many_blocks, ImportQueue, ImportQueueStatus, IncomingBlock}; use consensus::import_queue::{Link, SharedBlockImport, Verifier}; @@ -101,6 +101,7 @@ impl<B: BlockT> Verifier<B> for PassThroughVerifier { justification, post_digests: vec![], auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }, None)) } } diff --git a/substrate/core/test-client/src/client_ext.rs b/substrate/core/test-client/src/client_ext.rs index a833472e445d8421eac20954321b58b82e5f2eb2..f766f427cd724494f7c34484977ce56af7bc4ddc 100644 --- a/substrate/core/test-client/src/client_ext.rs +++ b/substrate/core/test-client/src/client_ext.rs @@ -17,7 +17,7 @@ //! Client extension for tests. use client::{self, Client}; -use consensus::{ImportBlock, BlockImport, BlockOrigin, Error as ConsensusError}; +use consensus::{ImportBlock, BlockImport, BlockOrigin, Error as ConsensusError, ForkChoiceStrategy}; use runtime_primitives::Justification; use runtime_primitives::generic::BlockId; use primitives::Blake2Hasher; @@ -57,6 +57,7 @@ impl<B, E, RA> TestClient for Client<B, E, runtime::Block, RA> body: Some(block.extrinsics), finalized: false, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ()) @@ -73,6 +74,7 @@ impl<B, E, RA> TestClient for Client<B, E, runtime::Block, RA> body: Some(block.extrinsics), finalized: true, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ())