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(|_| ())