diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 7f8c81d5ab..b0dfb939d0 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 Client where authorities: Option>, finalized: bool, aux: Vec<(Vec, Option>)>, + fork_choice: ForkChoiceStrategy, ) -> error::Result where E: CallExecutor + Send + Sync + Clone, { @@ -608,7 +609,10 @@ impl Client 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 consensus::BlockImport for Client body, finalized, auxiliary, + fork_choice, } = import_block; assert!(justification.is_some() && finalized || justification.is_none()); @@ -1074,6 +1079,7 @@ impl consensus::BlockImport for Client 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 911ae6304a..b57dab030c 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( 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 Verifier for AuraVerifier { /// Origin of the Block @@ -83,6 +92,8 @@ pub struct ImportBlock { /// Contains a list of key-value pairs. If values are `None`, the keys /// will be deleted. pub auxiliary: Vec<(Vec, Option>)>, + /// Fork choice strategy of this import. + pub fork_choice: ForkChoiceStrategy, } impl ImportBlock { diff --git a/substrate/core/consensus/common/src/lib.rs b/substrate/core/consensus/common/src/lib.rs index 875f4c216a..e9b5d82951 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 { diff --git a/substrate/core/network/src/test/mod.rs b/substrate/core/network/src/test/mod.rs index b2beba05db..94518978bc 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 Verifier 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 a833472e44..f766f427cd 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 TestClient for Client body: Some(block.extrinsics), finalized: false, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ()) @@ -73,6 +74,7 @@ impl TestClient for Client body: Some(block.extrinsics), finalized: true, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ())