From 1d0ad42230e204e5242e6e9842f4f00266091468 Mon Sep 17 00:00:00 2001
From: Robert Habermeier <rphmeier@gmail.com>
Date: Fri, 16 Feb 2018 17:28:42 +0100
Subject: [PATCH] Verify header justification during import (#76)

* reshuffle consensus libraries

* polkadot-useful type definitions for statement table

* begin BftService

* primary selection logic

* bft service implementation without I/O

* extract out `BlockImport` trait

* allow bft primitives to compile on wasm

* Block builder (substrate)

* take polkadot-consensus down to the core.

* test for preemption

* fix test build

* Fix wasm build

* Bulid on any block

* Test for block builder.

* Block import tests for client.

* Tidy ups

* clean up block builder instantiation

* justification verification logic

* JustifiedHeader and import

* Propert block generation for tests

* Fixed rpc tests
---
 substrate/Cargo.lock                          |   4 +-
 substrate/polkadot/api/src/lib.rs             |   2 +-
 substrate/polkadot/primitives/src/block.rs    |   2 +
 substrate/substrate/bft/Cargo.toml            |   2 -
 substrate/substrate/bft/src/error.rs          |   2 +-
 .../substrate/bft/src/generic/accumulator.rs  |   7 +
 substrate/substrate/bft/src/lib.rs            | 247 +++++++++++++-----
 substrate/substrate/client/Cargo.toml         |   1 +
 substrate/substrate/client/src/backend.rs     |   8 +-
 .../substrate/client/src/block_builder.rs     |   4 +-
 substrate/substrate/client/src/blockchain.rs  |  23 +-
 substrate/substrate/client/src/error.rs       |   9 +-
 substrate/substrate/client/src/in_mem.rs      |  18 +-
 substrate/substrate/client/src/lib.rs         | 128 +++++++--
 substrate/substrate/ed25519/src/lib.rs        |  30 ++-
 substrate/substrate/network/Cargo.toml        |   1 +
 substrate/substrate/network/src/blocks.rs     |   1 +
 substrate/substrate/network/src/chain.rs      |  22 +-
 substrate/substrate/network/src/lib.rs        |   1 +
 substrate/substrate/network/src/message.rs    |   5 +
 substrate/substrate/network/src/protocol.rs   |   9 +-
 substrate/substrate/network/src/sync.rs       |  92 ++++---
 substrate/substrate/network/src/test/mod.rs   |  41 ++-
 substrate/substrate/network/src/test/sync.rs  |  16 +-
 substrate/substrate/primitives/src/bft.rs     |  32 +++
 substrate/substrate/primitives/src/block.rs   |  20 ++
 substrate/substrate/primitives/src/lib.rs     |   3 +
 substrate/substrate/rpc/src/chain/mod.rs      |   2 +-
 substrate/substrate/rpc/src/state/mod.rs      |   6 +-
 substrate/substrate/runtime-std/with_std.rs   |   1 +
 .../substrate/runtime-std/without_std.rs      |   1 +
 31 files changed, 549 insertions(+), 191 deletions(-)

diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index b12e79f9989..62e3721f8c6 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -1400,12 +1400,10 @@ dependencies = [
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "substrate-client 0.1.0",
  "substrate-codec 0.1.0",
  "substrate-executor 0.1.0",
  "substrate-keyring 0.1.0",
  "substrate-primitives 0.1.0",
- "substrate-state-machine 0.1.0",
  "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1419,6 +1417,7 @@ dependencies = [
  "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "substrate-bft 0.1.0",
  "substrate-codec 0.1.0",
  "substrate-executor 0.1.0",
  "substrate-keyring 0.1.0",
@@ -1482,6 +1481,7 @@ dependencies = [
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "substrate-bft 0.1.0",
  "substrate-client 0.1.0",
  "substrate-codec 0.1.0",
  "substrate-executor 0.1.0",
diff --git a/substrate/polkadot/api/src/lib.rs b/substrate/polkadot/api/src/lib.rs
index a16781eb69b..efe0f452200 100644
--- a/substrate/polkadot/api/src/lib.rs
+++ b/substrate/polkadot/api/src/lib.rs
@@ -28,12 +28,12 @@ extern crate substrate_state_machine as state_machine;
 extern crate error_chain;
 
 use client::backend::Backend;
-use client::blockchain::BlockId;
 use client::Client;
 use polkadot_runtime::runtime;
 use polkadot_executor::Executor as LocalDispatch;
 use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
 use primitives::{AccountId, SessionKey};
+use primitives::block::Id as BlockId;
 use primitives::parachain::DutyRoster;
 
 error_chain! {
diff --git a/substrate/polkadot/primitives/src/block.rs b/substrate/polkadot/primitives/src/block.rs
index d71fa82e1c2..987744baa61 100644
--- a/substrate/polkadot/primitives/src/block.rs
+++ b/substrate/polkadot/primitives/src/block.rs
@@ -23,6 +23,8 @@ use rstd::vec::Vec;
 use codec::{Input, Slicable};
 use transaction::UncheckedTransaction;
 
+pub use primitives::block::Id;
+
 /// Used to refer to a block number.
 pub type Number = u64;
 
diff --git a/substrate/substrate/bft/Cargo.toml b/substrate/substrate/bft/Cargo.toml
index f1af1cda411..5d9fa23c634 100644
--- a/substrate/substrate/bft/Cargo.toml
+++ b/substrate/substrate/bft/Cargo.toml
@@ -5,10 +5,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
 
 [dependencies]
 futures = "0.1.17"
-substrate-client = { path = "../client" }
 substrate-codec = { path = "../codec" }
 substrate-primitives = { path = "../primitives" }
-substrate-state-machine = { path = "../state-machine" }
 ed25519 = { path = "../ed25519" }
 tokio-timer = "0.1.2"
 parking_lot = "0.4"
diff --git a/substrate/substrate/bft/src/error.rs b/substrate/substrate/bft/src/error.rs
index 1f5286f5e66..38f560c2cc7 100644
--- a/substrate/substrate/bft/src/error.rs
+++ b/substrate/substrate/bft/src/error.rs
@@ -19,7 +19,7 @@
 error_chain! {
 	errors {
 		/// Missing state at block with given Id.
-		StateUnavailable(b: ::client::BlockId) {
+		StateUnavailable(b: ::primitives::block::Id) {
 			description("State missing at given block."),
 			display("State unavailable at block {:?}", b),
 		}
diff --git a/substrate/substrate/bft/src/generic/accumulator.rs b/substrate/substrate/bft/src/generic/accumulator.rs
index 273fc658478..a7b2076bba5 100644
--- a/substrate/substrate/bft/src/generic/accumulator.rs
+++ b/substrate/substrate/bft/src/generic/accumulator.rs
@@ -83,6 +83,13 @@ impl<D, S> UncheckedJustification<D, S> {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Justification<D,S>(UncheckedJustification<D,S>);
 
+impl<D, S> Justification<D, S> {
+	/// Convert this justification back to unchecked.
+	pub fn uncheck(self) -> UncheckedJustification<D, S> {
+		self.0
+	}
+}
+
 impl<D, S> ::std::ops::Deref for Justification<D, S> {
 	type Target = UncheckedJustification<D, S>;
 
diff --git a/substrate/substrate/bft/src/lib.rs b/substrate/substrate/bft/src/lib.rs
index f4b1f72a011..1f81b23cac0 100644
--- a/substrate/substrate/bft/src/lib.rs
+++ b/substrate/substrate/bft/src/lib.rs
@@ -20,9 +20,7 @@ pub mod error;
 pub mod generic;
 
 extern crate substrate_codec as codec;
-extern crate substrate_client as client;
 extern crate substrate_primitives as primitives;
-extern crate substrate_state_machine as state_machine;
 extern crate ed25519;
 extern crate tokio_timer;
 extern crate parking_lot;
@@ -37,13 +35,11 @@ use std::collections::HashMap;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicBool, Ordering};
 
-use client::{BlockId, Client};
-use client::backend::Backend;
 use codec::Slicable;
-use ed25519::Signature;
-use primitives::block::{Block, Header, HeaderHash};
+use ed25519::LocalizedSignature;
+use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction, Justification as PrimitiveJustification};
+use primitives::block::{Block, Id as BlockId, Header, HeaderHash};
 use primitives::AuthorityId;
-use state_machine::CodeExecutor;
 
 use futures::{stream, task, Async, Sink, Future, IntoFuture};
 use futures::future::Executor;
@@ -63,20 +59,46 @@ pub type LocalizedMessage = generic::LocalizedMessage<
 	Block,
 	HeaderHash,
 	AuthorityId,
-	Signature
+	LocalizedSignature
 >;
 
 /// Justification of some hash.
-pub type Justification = generic::Justification<HeaderHash, Signature>;
+pub type Justification = generic::Justification<HeaderHash, LocalizedSignature>;
 
 /// Justification of a prepare message.
-pub type PrepareJustification = generic::PrepareJustification<HeaderHash, Signature>;
+pub type PrepareJustification = generic::PrepareJustification<HeaderHash, LocalizedSignature>;
+
+/// Unchecked justification.
+pub type UncheckedJustification = generic::UncheckedJustification<HeaderHash, LocalizedSignature>;
+
+impl From<PrimitiveJustification> for UncheckedJustification {
+	fn from(just: PrimitiveJustification) -> Self {
+		UncheckedJustification {
+			round_number: just.round_number as usize,
+			digest: just.hash,
+			signatures: just.signatures.into_iter().map(|(from, sig)| LocalizedSignature {
+				signer: ed25519::Public(from),
+				signature: sig,
+			}).collect(),
+		}
+	}
+}
+
+impl From<UncheckedJustification> for PrimitiveJustification {
+	fn from(just: UncheckedJustification) -> Self {
+		PrimitiveJustification {
+			round_number: just.round_number as u32,
+			hash: just.digest,
+			signatures: just.signatures.into_iter().map(|s| (s.signer.into(), s.signature)).collect(),
+		}
+	}
+}
 
 /// Result of a committed round of BFT
-pub type Committed = generic::Committed<Block, HeaderHash, Signature>;
+pub type Committed = generic::Committed<Block, HeaderHash, LocalizedSignature>;
 
 /// Communication between BFT participants.
-pub type Communication = generic::Communication<Block, HeaderHash, AuthorityId, Signature>;
+pub type Communication = generic::Communication<Block, HeaderHash, AuthorityId, LocalizedSignature>;
 
 /// Logic for a proposer.
 ///
@@ -108,30 +130,6 @@ pub trait Authorities {
 	fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, Error>;
 }
 
-impl<B, E> BlockImport for Client<B, E>
-	where
-		B: Backend,
-		E: CodeExecutor,
-		client::error::Error: From<<B::State as state_machine::backend::Backend>::Error>
-{
-	fn import_block(&self, block: Block, _justification: Justification) {
-		// TODO: use justification.
-		let _ = self.import_block(block.header, Some(block.transactions));
-	}
-}
-
-impl<B, E> Authorities for Client<B, E>
-	where
-		B: Backend,
-		E: CodeExecutor,
-		client::error::Error: From<<B::State as state_machine::backend::Backend>::Error>
-{
-	fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, Error> {
-		self.authorities_at(at).map_err(|_| ErrorKind::StateUnavailable(*at).into())
-	}
-}
-
-
 /// Instance of BFT agreement.
 struct BftInstance<P> {
 	key: Arc<ed25519::Pair>,
@@ -145,7 +143,7 @@ struct BftInstance<P> {
 impl<P: Proposer> generic::Context for BftInstance<P> {
 	type AuthorityId = AuthorityId;
 	type Digest = HeaderHash;
-	type Signature = Signature;
+	type Signature = LocalizedSignature;
 	type Candidate = Block;
 	type RoundTimeout = Box<Future<Item=(),Error=Error> + Send>;
 	type CreateProposal = <P::CreateProposal as IntoFuture>::Future;
@@ -163,28 +161,7 @@ impl<P: Proposer> generic::Context for BftInstance<P> {
 	}
 
 	fn sign_local(&self, message: Message) -> LocalizedMessage {
-		use primitives::bft::{Message as PrimitiveMessage, Action as PrimitiveAction};
-
-		let action = match message.clone() {
-			::generic::Message::Propose(r, p) => PrimitiveAction::Propose(r as u32, p),
-			::generic::Message::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
-			::generic::Message::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
-			::generic::Message::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
-		};
-
-		let primitive = PrimitiveMessage {
-			parent: self.parent_hash,
-			action,
-		};
-
-		let to_sign = Slicable::encode(&primitive);
-		let signature = self.key.sign(&to_sign);
-
-		LocalizedMessage {
-			message,
-			signature,
-			sender: self.key.public().0
-		}
+		sign_message(message, &*self.key, self.parent_hash.clone())
 	}
 
 	fn round_proposer(&self, round: usize) -> AuthorityId {
@@ -327,7 +304,7 @@ impl<P, E, I> BftService<P, E, I>
 		// TODO: check key is one of the authorities.
 		let authorities = self.client.authorities(&BlockId::Hash(hash))?;
 		let n = authorities.len();
-		let max_faulty = n.saturating_sub(1) / 3;
+		let max_faulty = max_faulty_of(n);
 
 		let bft_instance = BftInstance {
 			proposer,
@@ -372,6 +349,84 @@ impl<P, E, I> BftService<P, E, I>
 	}
 }
 
+/// Given a total number of authorities, yield the maximum faulty that would be allowed.
+/// This will always be under 1/3.
+pub fn max_faulty_of(n: usize) -> usize {
+	n.saturating_sub(1) / 3
+}
+
+fn check_justification_signed_message(authorities: &[AuthorityId], message: &[u8], just: UncheckedJustification)
+	-> Result<Justification, UncheckedJustification>
+{
+	just.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| {
+		let auth_id = sig.signer.0;
+		if !authorities.contains(&auth_id) { return None }
+
+		if ed25519::verify_strong(&sig.signature, message, &sig.signer) {
+			Some(sig.signer.0)
+		} else {
+			None
+		}
+	})
+}
+
+/// Check a full justification for a header hash.
+/// Provide all valid authorities.
+///
+/// On failure, returns the justification back.
+pub fn check_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
+	-> Result<Justification, UncheckedJustification>
+{
+	let message = Slicable::encode(&PrimitiveMessage {
+		parent,
+		action: PrimitiveAction::Commit(just.round_number as u32, just.digest),
+	});
+
+	check_justification_signed_message(authorities, &message[..], just)
+}
+
+/// Check a prepare justification for a header hash.
+/// Provide all valid authorities.
+///
+/// On failure, returns the justification back.
+pub fn check_prepare_justification(authorities: &[AuthorityId], parent: HeaderHash, just: UncheckedJustification)
+	-> Result<PrepareJustification, UncheckedJustification>
+{
+	let message = Slicable::encode(&PrimitiveMessage {
+		parent,
+		action: PrimitiveAction::Prepare(just.round_number as u32, just.digest),
+	});
+
+	check_justification_signed_message(authorities, &message[..], just)
+}
+
+/// Sign a BFT message with the given key.
+pub fn sign_message(message: Message, key: &ed25519::Pair, parent_hash: HeaderHash) -> LocalizedMessage {
+	let action = match message.clone() {
+		::generic::Message::Propose(r, p) => PrimitiveAction::Propose(r as u32, p),
+		::generic::Message::Prepare(r, h) => PrimitiveAction::Prepare(r as u32, h),
+		::generic::Message::Commit(r, h) => PrimitiveAction::Commit(r as u32, h),
+		::generic::Message::AdvanceRound(r) => PrimitiveAction::AdvanceRound(r as u32),
+	};
+
+	let primitive = PrimitiveMessage {
+		parent: parent_hash,
+		action,
+	};
+
+	let to_sign = Slicable::encode(&primitive);
+	let signature = LocalizedSignature {
+		signer: key.public(),
+		signature: key.sign(&to_sign),
+	};
+
+	LocalizedMessage {
+		message,
+		signature,
+		sender: key.public().0
+	}
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
@@ -470,4 +525,76 @@ mod tests {
 
 		core.turn(Some(::std::time::Duration::from_millis(100)));
 	}
+
+	#[test]
+	fn max_faulty() {
+		assert_eq!(max_faulty_of(3), 0);
+		assert_eq!(max_faulty_of(4), 1);
+		assert_eq!(max_faulty_of(100), 33);
+		assert_eq!(max_faulty_of(0), 0);
+		assert_eq!(max_faulty_of(11), 3);
+		assert_eq!(max_faulty_of(99), 32);
+	}
+
+	#[test]
+	fn justification_check_works() {
+		let parent_hash = Default::default();
+		let hash = [0xff; 32].into();
+
+		let authorities = vec![
+			Keyring::One.to_raw_public(),
+			Keyring::Two.to_raw_public(),
+			Keyring::Alice.to_raw_public(),
+			Keyring::Eve.to_raw_public(),
+		];
+
+		let authorities_keys = vec![
+			Keyring::One.into(),
+			Keyring::Two.into(),
+			Keyring::Alice.into(),
+			Keyring::Eve.into(),
+		];
+
+		let unchecked = UncheckedJustification {
+			digest: hash,
+			round_number: 1,
+			signatures: authorities_keys.iter().take(3).map(|key| {
+				sign_message(generic::Message::Commit(1, hash), key, parent_hash).signature
+			}).collect(),
+		};
+
+		assert!(check_justification(&authorities, parent_hash, unchecked).is_ok());
+
+		let unchecked = UncheckedJustification {
+			digest: hash,
+			round_number: 0, // wrong round number (vs. the signatures)
+			signatures: authorities_keys.iter().take(3).map(|key| {
+				sign_message(generic::Message::Commit(1, hash), key, parent_hash).signature
+			}).collect(),
+		};
+
+		assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
+
+		// not enough signatures.
+		let unchecked = UncheckedJustification {
+			digest: hash,
+			round_number: 1,
+			signatures: authorities_keys.iter().take(2).map(|key| {
+				sign_message(generic::Message::Commit(1, hash), key, parent_hash).signature
+			}).collect(),
+		};
+
+		assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
+
+		// wrong hash.
+		let unchecked = UncheckedJustification {
+			digest: [0xfe; 32].into(),
+			round_number: 1,
+			signatures: authorities_keys.iter().take(3).map(|key| {
+				sign_message(generic::Message::Commit(1, hash), key, parent_hash).signature
+			}).collect(),
+		};
+
+		assert!(check_justification(&authorities, parent_hash, unchecked).is_err());
+	}
 }
diff --git a/substrate/substrate/client/Cargo.toml b/substrate/substrate/client/Cargo.toml
index ad9fa2d2ad1..879e05e3c94 100644
--- a/substrate/substrate/client/Cargo.toml
+++ b/substrate/substrate/client/Cargo.toml
@@ -10,6 +10,7 @@ parking_lot = "0.4"
 triehash = "0.1"
 hex-literal = "0.1"
 ed25519 = { path = "../ed25519" }
+substrate-bft = { path = "../bft" }
 substrate-codec = { path = "../codec" }
 substrate-executor = { path = "../executor" }
 substrate-primitives = { path = "../primitives" }
diff --git a/substrate/substrate/client/src/backend.rs b/substrate/substrate/client/src/backend.rs
index 4421c82b374..eef90467917 100644
--- a/substrate/substrate/client/src/backend.rs
+++ b/substrate/substrate/client/src/backend.rs
@@ -18,8 +18,8 @@
 
 use state_machine;
 use error;
-use primitives::block;
-use blockchain::{self, BlockId};
+use primitives::block::{self, Id as BlockId};
+use primitives;
 
 /// Block insertion operation. Keeps hold if the inserted block state and data.
 pub trait BlockImportOperation {
@@ -29,7 +29,7 @@ pub trait BlockImportOperation {
 	/// Returns pending state.
 	fn state(&self) -> error::Result<&Self::State>;
 	/// Append block data to the transaction.
-	fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, is_new_best: bool) -> error::Result<()>;
+	fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()>;
 	/// Inject storage data into the database.
 	fn set_storage<I: Iterator<Item=(Vec<u8>, Vec<u8>)>>(&mut self, iter: I) -> error::Result<()>;
 	/// Inject storage data into the database.
@@ -41,7 +41,7 @@ pub trait Backend {
 	/// Associated block insertion operation type.
 	type BlockImportOperation: BlockImportOperation;
 	/// Associated blockchain backend type.
-	type Blockchain: blockchain::Backend;
+	type Blockchain: ::blockchain::Backend;
 	/// Associated state backend type.
 	type State: state_machine::backend::Backend;
 
diff --git a/substrate/substrate/client/src/block_builder.rs b/substrate/substrate/client/src/block_builder.rs
index 323fb61c29f..54fcd8df7eb 100644
--- a/substrate/substrate/client/src/block_builder.rs
+++ b/substrate/substrate/client/src/block_builder.rs
@@ -20,8 +20,8 @@ use std::vec::Vec;
 use codec::{Joiner, Slicable};
 use state_machine::{self, CodeExecutor};
 use primitives::{Header, Block};
-use primitives::block::Transaction;
-use {backend, error, BlockId, Client};
+use primitives::block::{Id as BlockId, Transaction};
+use {backend, error, Client};
 use triehash::ordered_trie_root;
 
 /// Utility for building new (valid) blocks from a stream of transactions.
diff --git a/substrate/substrate/client/src/blockchain.rs b/substrate/substrate/client/src/blockchain.rs
index 6eb9061eb7d..095cbe3cbee 100644
--- a/substrate/substrate/client/src/blockchain.rs
+++ b/substrate/substrate/client/src/blockchain.rs
@@ -16,27 +16,10 @@
 
 //! Polkadot blockchain trait
 
-use std::fmt::{Display, Formatter, Error as FmtError};
-use primitives::block;
+use primitives::block::{self, Id as BlockId};
+use primitives;
 use error::Result;
 
-/// Block indentification.
-#[derive(Debug, Clone, Copy)]
-pub enum BlockId {
-	/// Identify by block header hash.
-	Hash(block::HeaderHash),
-	/// Identify by block number.
-	Number(block::Number),
-}
-
-impl Display for BlockId {
-	fn fmt(&self, f: &mut Formatter) -> ::std::result::Result<(), FmtError> {
-		match *self {
-			BlockId::Hash(h) => h.fmt(f),
-			BlockId::Number(n) => n.fmt(f),
-		}
-	}
-}
 
 /// Blockchain database backend. Does not perform any validation.
 pub trait Backend: Send + Sync {
@@ -44,6 +27,8 @@ pub trait Backend: Send + Sync {
 	fn header(&self, id: BlockId) -> Result<Option<block::Header>>;
 	/// Get block body. Returns `None` if block is not found.
 	fn body(&self, id: BlockId) -> Result<Option<block::Body>>;
+	/// Get block justification. Returns `None` if justification does not exist.
+	fn justification(&self, id: BlockId) -> Result<Option<primitives::bft::Justification>>;
 	/// Get blockchain info.
 	fn info(&self) -> Result<Info>;
 	/// Get block status.
diff --git a/substrate/substrate/client/src/error.rs b/substrate/substrate/client/src/error.rs
index 1c97387e817..2ae07c870c5 100644
--- a/substrate/substrate/client/src/error.rs
+++ b/substrate/substrate/client/src/error.rs
@@ -18,7 +18,6 @@
 
 use std;
 use state_machine;
-use blockchain;
 
 error_chain! {
 	errors {
@@ -29,7 +28,7 @@ error_chain! {
 		}
 
 		/// Unknown block.
-		UnknownBlock(h: blockchain::BlockId) {
+		UnknownBlock(h: ::primitives::block::Id) {
 			description("unknown block"),
 			display("UnknownBlock: {}", h),
 		}
@@ -46,6 +45,12 @@ error_chain! {
 			display("Blockchain: {}", e),
 		}
 
+		/// Bad justification for header.
+		BadJustification(h: ::primitives::block::Id) {
+			description("bad justification for header"),
+			display("bad justification for header: {}", h),
+		}
+
 		/// Invalid state data.
 		AuthLen {
 			description("authority count state error"),
diff --git a/substrate/substrate/client/src/in_mem.rs b/substrate/substrate/client/src/in_mem.rs
index 6097d12e519..62ef3b97155 100644
--- a/substrate/substrate/client/src/in_mem.rs
+++ b/substrate/substrate/client/src/in_mem.rs
@@ -22,8 +22,9 @@ use state_machine;
 use error;
 use backend;
 use runtime_support::Hashable;
-use primitives::block::{self, HeaderHash};
-use blockchain::{self, BlockId, BlockStatus};
+use primitives;
+use primitives::block::{self, Id as BlockId, HeaderHash};
+use blockchain::{self, BlockStatus};
 use state_machine::backend::Backend as StateBackend;
 
 fn header_hash(header: &block::Header) -> block::HeaderHash {
@@ -38,6 +39,7 @@ struct PendingBlock {
 #[derive(PartialEq, Eq, Clone)]
 struct Block {
 	header: block::Header,
+	justification: Option<primitives::bft::Justification>,
 	body: Option<block::Body>,
 }
 
@@ -90,12 +92,13 @@ impl Blockchain {
 		}
 	}
 
-	fn insert(&self, hash: HeaderHash, header: block::Header, body: Option<block::Body>, is_new_best: bool) {
+	fn insert(&self, hash: HeaderHash, header: block::Header, justification: Option<primitives::bft::Justification>, body: Option<block::Body>, is_new_best: bool) {
 		let number = header.number;
 		let mut storage = self.storage.write();
 		storage.blocks.insert(hash, Block {
 			header: header,
 			body: body,
+			justification: justification,
 		});
 		storage.hashes.insert(number, hash);
 		if is_new_best {
@@ -132,6 +135,10 @@ impl blockchain::Backend for Blockchain {
 		Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.body.clone())))
 	}
 
+	fn justification(&self, id: BlockId) -> error::Result<Option<primitives::bft::Justification>> {
+		Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| b.justification.clone())))
+	}
+
 	fn info(&self) -> error::Result<blockchain::Info> {
 		let storage = self.storage.read();
 		Ok(blockchain::Info {
@@ -160,12 +167,13 @@ impl backend::BlockImportOperation for BlockImportOperation {
 		Ok(&self.pending_state)
 	}
 
-	fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, is_new_best: bool) -> error::Result<()> {
+	fn set_block_data(&mut self, header: block::Header, body: Option<block::Body>, justification: Option<primitives::bft::Justification>, is_new_best: bool) -> error::Result<()> {
 		assert!(self.pending_block.is_none(), "Only one block per operation is allowed");
 		self.pending_block = Some(PendingBlock {
 			block: Block {
 				header: header,
 				body: body,
+				justification: justification,
 			},
 			is_best: is_new_best,
 		});
@@ -220,7 +228,7 @@ impl backend::Backend for Backend {
 		if let Some(pending_block) = operation.pending_block {
 			let hash = header_hash(&pending_block.block.header);
 			self.states.write().insert(hash, operation.pending_state);
-			self.blockchain.insert(hash, pending_block.block.header, pending_block.block.body, pending_block.is_best);
+			self.blockchain.insert(hash, pending_block.block.header, pending_block.block.justification, pending_block.block.body, pending_block.is_best);
 		}
 		Ok(())
 	}
diff --git a/substrate/substrate/client/src/lib.rs b/substrate/substrate/client/src/lib.rs
index 54f93405e1b..c86c06afef9 100644
--- a/substrate/substrate/client/src/lib.rs
+++ b/substrate/substrate/client/src/lib.rs
@@ -18,6 +18,7 @@
 
 #![warn(missing_docs)]
 
+extern crate substrate_bft as bft;
 extern crate substrate_runtime_support as runtime_support;
 extern crate substrate_runtime_io as runtime_io;
 extern crate substrate_primitives as primitives;
@@ -42,9 +43,9 @@ pub mod genesis;
 pub mod block_builder;
 
 pub use blockchain::Info as ChainInfo;
-pub use blockchain::BlockId;
 
 use primitives::{block, AuthorityId};
+use primitives::block::Id as BlockId;
 use primitives::storage::{StorageKey, StorageData};
 use codec::{KeyedVec, Slicable};
 
@@ -109,6 +110,20 @@ pub enum BlockStatus {
 	Unknown,
 }
 
+/// A header paired with a justification which has already been checked.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct JustifiedHeader {
+	header: block::Header,
+	justification: bft::Justification,
+}
+
+impl JustifiedHeader {
+	/// Deconstruct the justified header into parts.
+	pub fn into_inner(self) -> (block::Header, bft::Justification) {
+		(self.header, self.justification)
+	}
+}
+
 /// Create an instance of in-memory client.
 pub fn new_in_mem<E, F>(
 	executor: E,
@@ -140,7 +155,7 @@ impl<B, E> Client<B, E> where
 			let (genesis_header, genesis_store) = build_genesis();
 			let mut op = backend.begin_operation(BlockId::Hash(block::HeaderHash::default()))?;
 			op.reset_storage(genesis_store.into_iter())?;
-			op.set_block_data(genesis_header, Some(vec![]), true)?;
+			op.set_block_data(genesis_header, Some(vec![]), None, true)?;
 			backend.commit_operation(op)?;
 		}
 		Ok(Client {
@@ -229,10 +244,31 @@ impl<B, E> Client<B, E> where
 		block_builder::BlockBuilder::at_block(parent, &self)
 	}
 
+	/// Check a header's justification.
+	pub fn check_justification(
+		&self,
+		header: block::Header,
+		justification: bft::UncheckedJustification,
+	) -> error::Result<JustifiedHeader> {
+		let authorities = self.authorities_at(&BlockId::Hash(header.parent_hash))?;
+		let just = bft::check_justification(&authorities[..], header.parent_hash, justification)
+			.map_err(|_| error::ErrorKind::BadJustification(BlockId::Hash(header.hash())))?;
+		Ok(JustifiedHeader {
+			header,
+			justification: just,
+		})
+	}
+
 	/// Queue a block for import.
-	pub fn import_block(&self, header: block::Header, body: Option<block::Body>) -> error::Result<ImportResult> {
+	pub fn import_block(
+		&self,
+		header: JustifiedHeader,
+		body: Option<block::Body>,
+	) -> error::Result<ImportResult> {
 		// TODO: import lock
 		// TODO: validate block
+		// TODO: import justification.
+		let (header, justification) = header.into_inner();
 		match self.backend.blockchain().status(BlockId::Hash(header.parent_hash))? {
 			blockchain::BlockStatus::InChain => (),
 			blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
@@ -251,7 +287,7 @@ impl<B, E> Client<B, E> where
 
 		let is_new_best = header.number == self.backend.blockchain().info()?.best_number + 1;
 		trace!("Imported {}, (#{}), best={}", block::HeaderHash::from(header.blake2_256()), header.number, is_new_best);
-		transaction.set_block_data(header, body, is_new_best)?;
+		transaction.set_block_data(header, body, Some(justification.uncheck().into()), is_new_best)?;
 		transaction.set_storage(overlay.drain())?;
 		self.backend.commit_operation(transaction)?;
 		Ok(ImportResult::Queued)
@@ -306,6 +342,38 @@ impl<B, E> Client<B, E> where
 	pub fn body(&self, id: &BlockId) -> error::Result<Option<block::Body>> {
 		self.backend.blockchain().body(*id)
 	}
+
+	/// Get block justification set by id.
+	pub fn justification(&self, id: &BlockId) -> error::Result<Option<primitives::bft::Justification>> {
+		self.backend.blockchain().justification(*id)
+	}
+}
+
+impl<B, E> bft::BlockImport for Client<B, E>
+	where
+		B: backend::Backend,
+		E: state_machine::CodeExecutor,
+		error::Error: From<<B::State as state_machine::backend::Backend>::Error>
+{
+	fn import_block(&self, block: block::Block, justification: bft::Justification) {
+		let justified_header = JustifiedHeader {
+			header: block.header,
+			justification,
+		};
+
+		let _ = self.import_block(justified_header, Some(block.transactions));
+	}
+}
+
+impl<B, E> bft::Authorities for Client<B, E>
+	where
+		B: backend::Backend,
+		E: state_machine::CodeExecutor,
+		error::Error: From<<B::State as state_machine::backend::Backend>::Error>
+{
+	fn authorities(&self, at: &BlockId) -> Result<Vec<AuthorityId>, bft::Error> {
+		self.authorities_at(at).map_err(|_| bft::ErrorKind::StateUnavailable(*at).into())
+	}
 }
 
 #[cfg(test)]
@@ -335,6 +403,31 @@ mod tests {
 		(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
 	}
 
+	// since we are in the client module we can create falsely justified
+	// headers.
+	// TODO: remove this in favor of custom verification pipelines for the
+	// client
+	fn justify(header: &block::Header) -> bft::UncheckedJustification {
+		let hash = header.hash();
+		let authorities = vec![
+			Keyring::Alice.into(),
+			Keyring::Bob.into(),
+			Keyring::Charlie.into(),
+		];
+
+		bft::UncheckedJustification {
+			digest: hash,
+			signatures: authorities.iter().map(|key| {
+				bft::sign_message(
+					bft::generic::Message::Commit(1, hash),
+					key,
+					header.parent_hash
+				).signature
+			}).collect(),
+			round_number: 1,
+		}
+	}
+
 	#[test]
 	fn client_initialises_from_genesis_ok() {
 		let client = new_in_mem(Executor::new(), prepare_genesis).unwrap();
@@ -347,11 +440,7 @@ mod tests {
 
 	#[test]
 	fn authorities_call_works() {
-		let genesis_config = GenesisConfig::new_simple(vec![
-			Keyring::Alice.to_raw_public(),
-			Keyring::Bob.to_raw_public(),
-			Keyring::Charlie.to_raw_public()
-		], 1000);
+		let genesis_config = genesis_config();
 
 		let prepare_genesis = || {
 			let mut storage = genesis_config.genesis_map();
@@ -371,11 +460,7 @@ mod tests {
 
 	#[test]
 	fn block_builder_works_with_no_transactions() {
-		let genesis_config = GenesisConfig::new_simple(vec![
-			Keyring::Alice.to_raw_public(),
-			Keyring::Bob.to_raw_public(),
-			Keyring::Charlie.to_raw_public()
-		], 1000);
+		let genesis_config = genesis_config();
 
 		let prepare_genesis = || {
 			let mut storage = genesis_config.genesis_map();
@@ -388,7 +473,9 @@ mod tests {
 		let builder = client.new_block().unwrap();
 		let block = builder.bake().unwrap();
 
-		client.import_block(block.header, Some(block.transactions)).unwrap();
+		let justification = justify(&block.header);
+		let justified = client.check_justification(block.header, justification).unwrap();
+		client.import_block(justified, Some(block.transactions)).unwrap();
 
 		assert_eq!(client.info().unwrap().chain.best_number, 1);
 		assert_eq!(client.using_environment(|| test_runtime::system::latest_block_hash()).unwrap(), client.block_hash(1).unwrap().unwrap());
@@ -406,11 +493,7 @@ mod tests {
 
 	#[test]
 	fn block_builder_works_with_transactions() {
-		let genesis_config = GenesisConfig::new_simple(vec![
-			Keyring::Alice.to_raw_public(),
-			Keyring::Bob.to_raw_public(),
-			Keyring::Charlie.to_raw_public()
-		], 1000);
+		let genesis_config = genesis_config();
 
 		let prepare_genesis = || {
 			let mut storage = genesis_config.genesis_map();
@@ -429,7 +512,10 @@ mod tests {
 			nonce: 0
 		}.signed()).unwrap();
 		let block = builder.bake().unwrap();
-		client.import_block(block.header, Some(block.transactions)).unwrap();
+
+		let justification = justify(&block.header);
+		let justified = client.check_justification(block.header, justification).unwrap();
+		client.import_block(justified, Some(block.transactions)).unwrap();
 
 		assert_eq!(client.info().unwrap().chain.best_number, 1);
 		assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap());
diff --git a/substrate/substrate/ed25519/src/lib.rs b/substrate/substrate/ed25519/src/lib.rs
index 30496adefff..4d8117186bc 100644
--- a/substrate/substrate/ed25519/src/lib.rs
+++ b/substrate/substrate/ed25519/src/lib.rs
@@ -24,9 +24,18 @@ extern crate untrusted;
 use ring::{rand, signature};
 use primitives::hash::H512;
 
-/// Alias to 520-bit hash when used in the context of a signature on the relay chain.
+/// Alias to 512-bit hash when used in the context of a signature on the relay chain.
 pub type Signature = H512;
 
+/// A localized signature also contains sender information.
+#[derive(PartialEq, Eq, Clone, Debug)]
+pub struct LocalizedSignature {
+	/// The signer of the signature.
+	pub signer: Public,
+	/// The signature itself.
+	pub signature: Signature,
+}
+
 /// Verify a message without type checking the parameters' types for the right size.
 pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool {
 	let public_key = untrusted::Input::from(public);
@@ -40,7 +49,7 @@ pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool {
 }
 
 /// A public key.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Eq, Clone, Debug)]
 pub struct Public(pub [u8; 32]);
 
 /// A key pair.
@@ -89,6 +98,12 @@ impl AsRef<[u8]> for Public {
 	}
 }
 
+impl Into<[u8; 32]> for Public {
+	fn into(self) -> [u8; 32] {
+		self.0
+	}
+}
+
 impl Pair {
 	/// Generate new secure (random) key pair.
 	pub fn new() -> Pair {
@@ -152,10 +167,21 @@ impl Verifiable for Signature {
 	}
 }
 
+impl Verifiable for LocalizedSignature {
+	fn verify(&self, message: &[u8], pubkey: &Public) -> bool {
+		pubkey == &self.signer && self.signature.verify(message, pubkey)
+	}
+}
+
 #[cfg(test)]
 mod test {
 	use super::*;
 
+	fn _test_primitives_signature_and_local_the_same() {
+		fn takes_two<T>(_: T, _: T) { }
+		takes_two(Signature::default(), primitives::Signature::default())
+	}
+
 	#[test]
 	fn test_vector_should_work() {
 		let pair: Pair = Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"));
diff --git a/substrate/substrate/network/Cargo.toml b/substrate/substrate/network/Cargo.toml
index 5e3314e7b7b..2c079340526 100644
--- a/substrate/substrate/network/Cargo.toml
+++ b/substrate/substrate/network/Cargo.toml
@@ -29,4 +29,5 @@ substrate-test-runtime = { path = "../test-runtime" }
 substrate-executor = { path = "../../substrate/executor" }
 substrate-keyring = { path = "../../substrate/keyring" }
 substrate-codec = { path = "../../substrate/codec" }
+substrate-bft = { path = "../bft" }
 env_logger = "0.4"
diff --git a/substrate/substrate/network/src/blocks.rs b/substrate/substrate/network/src/blocks.rs
index 7cb472ec549..f111d431049 100644
--- a/substrate/substrate/network/src/blocks.rs
+++ b/substrate/substrate/network/src/blocks.rs
@@ -205,6 +205,7 @@ mod test {
 			body: None,
 			message_queue: None,
 			receipt: None,
+			justification: None,
 		}).collect()
 	}
 
diff --git a/substrate/substrate/network/src/chain.rs b/substrate/substrate/network/src/chain.rs
index 709a988060c..1a51797f10b 100644
--- a/substrate/substrate/network/src/chain.rs
+++ b/substrate/substrate/network/src/chain.rs
@@ -16,14 +16,15 @@
 
 //! Blockchain access trait
 
-use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus, BlockId};
+use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus};
 use client::error::Error;
 use state_machine;
-use primitives::block;
+use primitives::block::{self, Id as BlockId};
+use primitives::bft::Justification;
 
-pub trait Client : Send + Sync {
+pub trait Client: Send + Sync {
 	/// Given a hash return a header
-	fn import(&self, header: block::Header, body: Option<block::Body>) -> Result<ImportResult, Error>;
+	fn import(&self, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error>;
 
 	/// Get blockchain info.
 	fn info(&self) -> Result<ClientInfo, Error>;
@@ -39,6 +40,9 @@ pub trait Client : Send + Sync {
 
 	/// Get block body.
 	fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error>;
+
+	/// Get block justification.
+	fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error>;
 }
 
 impl<B, E> Client for PolkadotClient<B, E> where
@@ -46,8 +50,10 @@ impl<B, E> Client for PolkadotClient<B, E> where
 	E: state_machine::CodeExecutor + Send + Sync + 'static,
 	Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>, {
 
-	fn import(&self, header: block::Header, body: Option<block::Body>) -> Result<ImportResult, Error> {
-		(self as &PolkadotClient<B, E>).import_block(header, body)
+	fn import(&self, header: block::Header, justification: Justification, body: Option<block::Body>) -> Result<ImportResult, Error> {
+		// TODO: defer justification check.
+		let justified_header = self.check_justification(header, justification.into())?;
+		(self as &PolkadotClient<B, E>).import_block(justified_header, body)
 	}
 
 	fn info(&self) -> Result<ClientInfo, Error> {
@@ -69,4 +75,8 @@ impl<B, E> Client for PolkadotClient<B, E> where
 	fn body(&self, id: &BlockId) -> Result<Option<block::Body>, Error> {
 		(self as &PolkadotClient<B, E>).body(id)
 	}
+
+	fn justification(&self, id: &BlockId) -> Result<Option<Justification>, Error> {
+		(self as &PolkadotClient<B, E>).justification(id)
+	}
 }
diff --git a/substrate/substrate/network/src/lib.rs b/substrate/substrate/network/src/lib.rs
index bc2ebe71965..71e6ab755f2 100644
--- a/substrate/substrate/network/src/lib.rs
+++ b/substrate/substrate/network/src/lib.rs
@@ -40,6 +40,7 @@ extern crate serde_json;
 #[cfg(test)] extern crate substrate_keyring as keyring;
 #[cfg(test)] #[macro_use] extern crate substrate_executor as executor;
 #[cfg(test)] extern crate substrate_codec as codec;
+#[cfg(test)] extern crate substrate_bft as bft;
 
 mod service;
 mod sync;
diff --git a/substrate/substrate/network/src/message.rs b/substrate/substrate/network/src/message.rs
index 63c4691cfe7..793daa444f7 100644
--- a/substrate/substrate/network/src/message.rs
+++ b/substrate/substrate/network/src/message.rs
@@ -19,6 +19,7 @@
 use std::borrow::Borrow;
 use primitives::AuthorityId;
 use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body};
+use primitives::bft::Justification;
 use service::Role as RoleFlags;
 
 pub type RequestId = u64;
@@ -85,6 +86,8 @@ pub enum BlockAttribute {
 	Receipt,
 	/// Include block message queue.
 	MessageQueue,
+	/// Include a justification for the block.
+	Justification,
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
@@ -100,6 +103,8 @@ pub struct BlockData {
 	pub receipt: Option<Bytes>,
 	/// Block message queue if requested.
 	pub message_queue: Option<Bytes>,
+	/// Justification if requested.
+	pub justification: Option<Justification>,
 }
 
 #[serde(untagged)]
diff --git a/substrate/substrate/network/src/protocol.rs b/substrate/substrate/network/src/protocol.rs
index 006ed39c3cc..980bf441f5c 100644
--- a/substrate/substrate/network/src/protocol.rs
+++ b/substrate/substrate/network/src/protocol.rs
@@ -17,10 +17,10 @@
 use std::collections::{HashMap, HashSet, BTreeMap};
 use std::{mem, cmp};
 use std::sync::Arc;
+use std::time;
 use parking_lot::RwLock;
 use serde_json;
-use std::time;
-use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header};
+use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header, Id as BlockId};
 use network::{PeerId, NodeId};
 
 use message::{self, Message};
@@ -30,7 +30,6 @@ use config::ProtocolConfig;
 use chain::Client;
 use io::SyncIo;
 use error;
-use client::BlockId;
 use super::header_hash;
 
 const REQUEST_TIMEOUT_SEC: u64 = 15;
@@ -223,13 +222,14 @@ impl Protocol {
 		};
 		let max = cmp::min(request.max.unwrap_or(u32::max_value()), MAX_BLOCK_DATA_RESPONSE) as usize;
 		// TODO: receipts, etc.
-		let (mut get_header, mut get_body) = (false, false);
+		let (mut get_header, mut get_body, mut get_justification) = (false, false, false);
 		for a in request.fields {
 			match a {
 				message::BlockAttribute::Header => get_header = true,
 				message::BlockAttribute::Body => get_body = true,
 				message::BlockAttribute::Receipt => unimplemented!(),
 				message::BlockAttribute::MessageQueue => unimplemented!(),
+				message::BlockAttribute::Justification => get_justification = true,
 			}
 		}
 		while let Some(header) = self.chain.header(&id).unwrap_or(None) {
@@ -244,6 +244,7 @@ impl Protocol {
 				body: if get_body { self.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None },
 				receipt: None,
 				message_queue: None,
+				justification: if get_justification { self.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { None },
 			};
 			blocks.push(block_data);
 			match request.direction {
diff --git a/substrate/substrate/network/src/sync.rs b/substrate/substrate/network/src/sync.rs
index 465bffcc316..c952bd5f2e4 100644
--- a/substrate/substrate/network/src/sync.rs
+++ b/substrate/substrate/network/src/sync.rs
@@ -18,8 +18,8 @@ use std::collections::HashMap;
 use io::SyncIo;
 use protocol::Protocol;
 use network::PeerId;
-use client::{ImportResult, BlockStatus, ClientInfo, BlockId};
-use primitives::block::{HeaderHash, Number as BlockNumber, Header};
+use client::{ImportResult, BlockStatus, ClientInfo};
+use primitives::block::{HeaderHash, Number as BlockNumber, Header, Id as BlockId};
 use blocks::{self, BlockCollection};
 use message::{self, Message};
 use super::header_hash;
@@ -80,7 +80,7 @@ impl ChainSync {
 			blocks: BlockCollection::new(),
 			best_queued_hash: info.best_queued_hash.unwrap_or(info.chain.best_hash),
 			best_queued_number: info.best_queued_number.unwrap_or(info.chain.best_number),
-			required_block_attributes: vec![message::BlockAttribute::Header, message::BlockAttribute::Body],
+			required_block_attributes: vec![message::BlockAttribute::Header, message::BlockAttribute::Body, message::BlockAttribute::Justification],
 		}
 	}
 
@@ -215,41 +215,57 @@ impl ChainSync {
 		for block in new_blocks {
 			let origin = block.origin;
 			let block = block.block;
-			if let Some(header) = block.header {
-				let number = header.number;
-				let hash = header_hash(&header);
-				let parent = header.parent_hash;
-				let result = protocol.chain().import(header, block.body);
-				match result {
-					Ok(ImportResult::AlreadyInChain) => {
-						trace!(target: "sync", "Block already in chain {}: {:?}", number, hash);
-						self.block_imported(&hash, number);
-					},
-					Ok(ImportResult::AlreadyQueued) => {
-						trace!(target: "sync", "Block already queued {}: {:?}", number, hash);
-						self.block_imported(&hash, number);
-					},
-					Ok(ImportResult::Queued) => {
-						trace!(target: "sync", "Block queued {}: {:?}", number, hash);
-						self.block_imported(&hash, number);
-						imported = imported + 1;
-					},
-					Ok(ImportResult::UnknownParent) => {
-						debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent);
-						self.restart(io, protocol);
-						return;
-					},
-					Ok(ImportResult::KnownBad) => {
-						debug!(target: "sync", "Bad block {}: {:?}", number, hash);
-						io.disable_peer(origin); //TODO: use persistent ID
-						self.restart(io, protocol);
-						return;
-					}
-					Err(e) => {
-						debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e);
-						self.restart(io, protocol);
-						return;
+			match (block.header, block.justification) {
+				(Some(header), Some(justification)) => {
+					let number = header.number;
+					let hash = header_hash(&header);
+					let parent = header.parent_hash;
+					let result = protocol.chain().import(
+						header,
+						justification,
+						block.body
+					);
+					match result {
+						Ok(ImportResult::AlreadyInChain) => {
+							trace!(target: "sync", "Block already in chain {}: {:?}", number, hash);
+							self.block_imported(&hash, number);
+						},
+						Ok(ImportResult::AlreadyQueued) => {
+							trace!(target: "sync", "Block already queued {}: {:?}", number, hash);
+							self.block_imported(&hash, number);
+						},
+						Ok(ImportResult::Queued) => {
+							trace!(target: "sync", "Block queued {}: {:?}", number, hash);
+							self.block_imported(&hash, number);
+							imported = imported + 1;
+						},
+						Ok(ImportResult::UnknownParent) => {
+							debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent);
+							self.restart(io, protocol);
+							return;
+						},
+						Ok(ImportResult::KnownBad) => {
+							debug!(target: "sync", "Bad block {}: {:?}", number, hash);
+							io.disable_peer(origin); //TODO: use persistent ID
+							self.restart(io, protocol);
+							return;
+						}
+						Err(e) => {
+							debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e);
+							self.restart(io, protocol);
+							return;
+						}
 					}
+				},
+				(None, _) => {
+					debug!(target: "sync", "Header {} was not provided by {} ", block.hash, origin);
+					io.disable_peer(origin); //TODO: use persistent ID
+					return;
+				},
+				(_, None) => {
+					debug!(target: "sync", "Justification set for block {} was not provided by {} ", block.hash, origin);
+					io.disable_peer(origin); //TODO: use persistent ID
+					return;
 				}
 			}
 		}
@@ -398,7 +414,7 @@ impl ChainSync {
 	fn request_ancestry(io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, block: BlockNumber) {
 		let request = message::BlockRequest {
 			id: 0,
-			fields: vec![message::BlockAttribute::Header],
+			fields: vec![message::BlockAttribute::Header, message::BlockAttribute::Justification],
 			from: message::FromBlock::Number(block),
 			to: None,
 			direction: message::Direction::Ascending,
diff --git a/substrate/substrate/network/src/test/mod.rs b/substrate/substrate/network/src/test/mod.rs
index 86c8cd91bdf..4cddc1bf8af 100644
--- a/substrate/substrate/network/src/test/mod.rs
+++ b/substrate/substrate/network/src/test/mod.rs
@@ -19,8 +19,9 @@ mod sync;
 use std::collections::{VecDeque, HashSet, HashMap};
 use std::sync::Arc;
 use parking_lot::RwLock;
-use client::{self, BlockId, genesis};
+use client::{self, genesis};
 use client::block_builder::BlockBuilder;
+use primitives::block::Id as BlockId;
 use primitives;
 use executor;
 use io::SyncIo;
@@ -32,6 +33,7 @@ use runtime_support::Hashable;
 use test_runtime;
 use keyring::Keyring;
 use codec::Slicable;
+use bft;
 
 native_executor_instance!(Executor, test_runtime::api::dispatch, include_bytes!("../../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
 
@@ -100,7 +102,7 @@ pub struct TestPacket {
 }
 
 pub struct Peer {
-	chain: Arc<client::Client<client::in_mem::Backend, executor::NativeExecutor<Executor>>>,
+	client: Arc<client::Client<client::in_mem::Backend, executor::NativeExecutor<Executor>>>,
 	pub sync: Protocol,
 	pub queue: RwLock<VecDeque<TestPacket>>,
 }
@@ -108,9 +110,9 @@ pub struct Peer {
 impl Peer {
 	/// Called after blockchain has been populated to updated current state.
 	fn start(&self) {
-		// Update the sync state to the lates chain state.
-		let info = self.chain.info().expect("In-mem chain does not fail");
-		let header = self.chain.header(&BlockId::Hash(info.chain.best_hash)).unwrap().unwrap();
+		// Update the sync state to the latest chain state.
+		let info = self.client.info().expect("In-mem client does not fail");
+		let header = self.client.header(&BlockId::Hash(info.chain.best_hash)).unwrap().unwrap();
 		self.sync.on_block_imported(&header);
 	}
 
@@ -158,13 +160,32 @@ impl Peer {
 	fn flush(&self) {
 	}
 
+	fn justify(header: &primitives::block::Header) -> bft::UncheckedJustification {
+		let hash = header.hash();
+		let authorities = vec![ Keyring::Alice.into() ];
+
+		bft::UncheckedJustification {
+			digest: hash,
+			signatures: authorities.iter().map(|key| {
+				bft::sign_message(
+					bft::generic::Message::Commit(1, hash),
+					key,
+					header.parent_hash
+				).signature
+			}).collect(),
+			round_number: 1,
+		}
+	}
+
 	fn generate_blocks<F>(&self, count: usize, mut edit_block: F) where F: FnMut(&mut BlockBuilder<client::in_mem::Backend, executor::NativeExecutor<Executor>>) {
 		for _ in 0 .. count {
-			let mut builder = self.chain.new_block().unwrap();
+			let mut builder = self.client.new_block().unwrap();
 			edit_block(&mut builder);
 			let block = builder.bake().unwrap();
 			trace!("Generating {}, (#{})", primitives::block::HeaderHash::from(block.header.blake2_256()), block.header.number);
-			self.chain.import_block(block.header, Some(block.transactions)).unwrap();
+			let justification = Self::justify(&block.header);
+			let justified = self.client.check_justification(block.header, justification).unwrap();
+			self.client.import_block(justified, Some(block.transactions)).unwrap();
 		}
 	}
 
@@ -221,11 +242,11 @@ impl TestNet {
 		};
 
 		for _ in 0..n {
-			let chain = Arc::new(client::new_in_mem(Executor::new(), Self::prepare_genesis).unwrap());
-			let sync = Protocol::new(config.clone(), chain.clone()).unwrap();
+			let client = Arc::new(client::new_in_mem(Executor::new(), Self::prepare_genesis).unwrap());
+			let sync = Protocol::new(config.clone(), client.clone()).unwrap();
 			net.peers.push(Arc::new(Peer {
 				sync: sync,
-				chain: chain,
+				client: client,
 				queue: RwLock::new(VecDeque::new()),
 			}));
 		}
diff --git a/substrate/substrate/network/src/test/sync.rs b/substrate/substrate/network/src/test/sync.rs
index 3e77c01c75f..e5cc1ebfad0 100644
--- a/substrate/substrate/network/src/test/sync.rs
+++ b/substrate/substrate/network/src/test/sync.rs
@@ -25,7 +25,7 @@ fn sync_from_two_peers_works() {
 	net.peer(1).push_blocks(100, false);
 	net.peer(2).push_blocks(100, false);
 	net.sync();
-	assert!(net.peer(0).chain.backend().blockchain().equals_to(net.peer(1).chain.backend().blockchain()));
+	assert!(net.peer(0).client.backend().blockchain().equals_to(net.peer(1).client.backend().blockchain()));
 	let status = net.peer(0).sync.status();
 	assert_eq!(status.sync.state, SyncState::Idle);
 }
@@ -39,7 +39,7 @@ fn sync_from_two_peers_with_ancestry_search_works() {
 	net.peer(2).push_blocks(100, false);
 	net.restart_peer(0);
 	net.sync();
-	assert!(net.peer(0).chain.backend().blockchain().canon_equals_to(net.peer(1).chain.backend().blockchain()));
+	assert!(net.peer(0).client.backend().blockchain().canon_equals_to(net.peer(1).client.backend().blockchain()));
 }
 
 #[test]
@@ -49,7 +49,7 @@ fn sync_long_chain_works() {
 	net.sync_steps(3);
 	assert_eq!(net.peer(0).sync.status().sync.state, SyncState::Downloading);
 	net.sync();
-	assert!(net.peer(0).chain.backend().blockchain().equals_to(net.peer(1).chain.backend().blockchain()));
+	assert!(net.peer(0).client.backend().blockchain().equals_to(net.peer(1).client.backend().blockchain()));
 }
 
 #[test]
@@ -59,7 +59,7 @@ fn sync_no_common_longer_chain_fails() {
 	net.peer(0).push_blocks(20, true);
 	net.peer(1).push_blocks(20, false);
 	net.sync();
-	assert!(!net.peer(0).chain.backend().blockchain().canon_equals_to(net.peer(1).chain.backend().blockchain()));
+	assert!(!net.peer(0).client.backend().blockchain().canon_equals_to(net.peer(1).client.backend().blockchain()));
 }
 
 #[test]
@@ -78,10 +78,10 @@ fn sync_after_fork_works() {
 	net.peer(2).push_blocks(1, false);
 
 	// peer 1 has the best chain
-	let peer1_chain = net.peer(1).chain.backend().blockchain().clone();
+	let peer1_chain = net.peer(1).client.backend().blockchain().clone();
 	net.sync();
-	assert!(net.peer(0).chain.backend().blockchain().canon_equals_to(&peer1_chain));
-	assert!(net.peer(1).chain.backend().blockchain().canon_equals_to(&peer1_chain));
-	assert!(net.peer(2).chain.backend().blockchain().canon_equals_to(&peer1_chain));
+	assert!(net.peer(0).client.backend().blockchain().canon_equals_to(&peer1_chain));
+	assert!(net.peer(1).client.backend().blockchain().canon_equals_to(&peer1_chain));
+	assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer1_chain));
 }
 
diff --git a/substrate/substrate/primitives/src/bft.rs b/substrate/substrate/primitives/src/bft.rs
index f6be42e2490..49e14075285 100644
--- a/substrate/substrate/primitives/src/bft.rs
+++ b/substrate/substrate/primitives/src/bft.rs
@@ -120,3 +120,35 @@ impl Slicable for Message {
 		})
 	}
 }
+
+/// Justification of a block.
+#[derive(Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
+pub struct Justification {
+	/// The round consensus was reached in.
+	pub round_number: u32,
+	/// The hash of the header justified.
+	pub hash: HeaderHash,
+	/// The signatures and signers of the hash.
+	pub signatures: Vec<(::AuthorityId, ::Signature)>
+}
+
+impl Slicable for Justification {
+	fn encode(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+
+		self.round_number.using_encoded(|s| v.extend(s));
+		self.hash.using_encoded(|s| v.extend(s));
+		self.signatures.using_encoded(|s| v.extend(s));
+
+		v
+	}
+
+	fn decode<I: Input>(value: &mut I) -> Option<Self> {
+		Some(Justification {
+			round_number: try_opt!(Slicable::decode(value)),
+			hash: try_opt!(Slicable::decode(value)),
+			signatures: try_opt!(Slicable::decode(value)),
+		})
+	}
+}
diff --git a/substrate/substrate/primitives/src/block.rs b/substrate/substrate/primitives/src/block.rs
index c1799ef5519..36640873ba3 100644
--- a/substrate/substrate/primitives/src/block.rs
+++ b/substrate/substrate/primitives/src/block.rs
@@ -16,6 +16,7 @@
 
 //! Block and header type definitions.
 
+use rstd::fmt;
 use rstd::vec::Vec;
 #[cfg(feature = "std")]
 use bytes;
@@ -177,6 +178,25 @@ impl Slicable for Header {
 	}
 }
 
+/// Block indentification.
+#[derive(Clone, Copy)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub enum Id {
+	/// Identify by block header hash.
+	Hash(HeaderHash),
+	/// Identify by block number.
+	Number(Number),
+}
+
+impl fmt::Display for Id {
+	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+		match *self {
+			Id::Hash(h) => h.fmt(f),
+			Id::Number(n) => n.fmt(f),
+		}
+	}
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
diff --git a/substrate/substrate/primitives/src/lib.rs b/substrate/substrate/primitives/src/lib.rs
index fe42a997ca3..ecf187cf910 100644
--- a/substrate/substrate/primitives/src/lib.rs
+++ b/substrate/substrate/primitives/src/lib.rs
@@ -98,3 +98,6 @@ pub type Hash = H256;
 
 /// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
 pub type AuthorityId = [u8; 32];
+
+/// A 512-bit value interpreted as a signature.
+pub type Signature = hash::H512;
diff --git a/substrate/substrate/rpc/src/chain/mod.rs b/substrate/substrate/rpc/src/chain/mod.rs
index ef827696145..2d668826c40 100644
--- a/substrate/substrate/rpc/src/chain/mod.rs
+++ b/substrate/substrate/rpc/src/chain/mod.rs
@@ -42,6 +42,6 @@ impl<B, E> ChainApi for client::Client<B, E> where
 	client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
 {
 	fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> {
-		client::Client::header(self, &client::BlockId::Hash(hash)).chain_err(|| "Blockchain error")
+		client::Client::header(self, &block::Id::Hash(hash)).chain_err(|| "Blockchain error")
 	}
 }
diff --git a/substrate/substrate/rpc/src/state/mod.rs b/substrate/substrate/rpc/src/state/mod.rs
index de643de7c72..b8977f30859 100644
--- a/substrate/substrate/rpc/src/state/mod.rs
+++ b/substrate/substrate/rpc/src/state/mod.rs
@@ -21,7 +21,7 @@ mod error;
 #[cfg(test)]
 mod tests;
 
-use client::{self, Client, BlockId};
+use client::{self, Client};
 use primitives::block;
 use primitives::storage::{StorageKey, StorageData};
 use state_machine;
@@ -47,10 +47,10 @@ impl<B, E> StateApi for Client<B, E> where
 	client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
 {
 	fn storage(&self, key: StorageKey, block: block::HeaderHash) -> Result<StorageData> {
-		Ok(self.storage(&BlockId::Hash(block), &key)?)
+		Ok(self.storage(&block::Id::Hash(block), &key)?)
 	}
 
 	fn call(&self, method: String, data: Vec<u8>, block: block::HeaderHash) -> Result<Vec<u8>> {
-		Ok(self.call(&BlockId::Hash(block), &method, &data)?.return_data)
+		Ok(self.call(&block::Id::Hash(block), &method, &data)?.return_data)
 	}
 }
diff --git a/substrate/substrate/runtime-std/with_std.rs b/substrate/substrate/runtime-std/with_std.rs
index 960871665e2..32124b04c80 100644
--- a/substrate/substrate/runtime-std/with_std.rs
+++ b/substrate/substrate/runtime-std/with_std.rs
@@ -17,6 +17,7 @@
 pub use std::boxed;
 pub use std::cell;
 pub use std::cmp;
+pub use std::fmt;
 pub use std::iter;
 pub use std::mem;
 pub use std::ops;
diff --git a/substrate/substrate/runtime-std/without_std.rs b/substrate/substrate/runtime-std/without_std.rs
index b27db9bc7d2..b3e50eb2adf 100644
--- a/substrate/substrate/runtime-std/without_std.rs
+++ b/substrate/substrate/runtime-std/without_std.rs
@@ -33,3 +33,4 @@ pub use core::mem;
 pub use core::ops;
 pub use core::ptr;
 pub use core::slice;
+pub use core::fmt;
-- 
GitLab