diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs
index fd6eba123a7ee061123f66e26178f2f07603820c..40576352d677d340f505b910a14168527171161c 100644
--- a/substrate/primitives/src/block.rs
+++ b/substrate/primitives/src/block.rs
@@ -16,25 +16,34 @@
 
 //! Block and header type definitions.
 
+use bytes;
 use hash::H256;
 use parachain;
 
 /// Hash used to refer to a block hash.
 pub type HeaderHash = H256;
 
+/// Execution log (event)
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Log(#[serde(with="bytes")] pub Vec<u8>);
+
 /// A relay chain block header.
+///
+/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 #[serde(deny_unknown_fields)]
 pub struct Header {
 	/// Block parent's hash.
 	pub parent_hash: HeaderHash,
-	/// State root after this transition.
-	pub state_root: H256,
-	/// Unix time at which this header was produced.
-	pub timestamp: u64,
 	/// Block number.
 	pub number: u64,
+	/// State root after this transition.
+	pub state_root: H256,
+	/// Parachain activity bitfield
+	pub parachain_activity: parachain::Activity,
+	/// Logs (generated by execution)
+	pub logs: Vec<Log>,
 }
 
 /// A relay chain block body.
@@ -46,7 +55,7 @@ pub struct Header {
 #[serde(deny_unknown_fields)]
 pub struct Body {
 	/// Parachain proposal blocks.
-	pub para_blocks: Vec<parachain::Proposal>,
+	pub candidates: Vec<parachain::Candidate>,
 }
 
 #[cfg(test)]
@@ -58,34 +67,17 @@ mod tests {
 	fn test_header_serialization() {
 		assert_eq!(ser::to_string_pretty(&Header {
 			parent_hash: 5.into(),
-			state_root: 3.into(),
-			timestamp: 10,
 			number: 67,
+			state_root: 3.into(),
+			parachain_activity: parachain::Activity(vec![0]),
+			logs: vec![Log(vec![1])],
 		}), r#"{
   "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005",
+  "number": 67,
   "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003",
-  "timestamp": 10,
-  "number": 67
-}"#);
-	}
-
-	#[test]
-	fn test_body_serialization() {
-		assert_eq!(ser::to_string_pretty(&Body {
-			para_blocks: vec![
-				parachain::Proposal {
-					parachain: 5.into(),
-					header: parachain::Header(vec![1, 2, 3, 4]),
-					proof_hash: 5.into(),
-				}
-			],
-		}), r#"{
-  "paraBlocks": [
-    {
-      "parachain": 5,
-      "header": "0x01020304",
-      "proofHash": "0x0000000000000000000000000000000000000000000000000000000000000005"
-    }
+  "parachainActivity": "0x00",
+  "logs": [
+    "0x01"
   ]
 }"#);
 	}
diff --git a/substrate/primitives/src/hash.rs b/substrate/primitives/src/hash.rs
index 10b32f37411d2b7ddb440af69ddf833fc1f26853..cef573f6f29b11cf7d432c8c6514e15b2089729f 100644
--- a/substrate/primitives/src/hash.rs
+++ b/substrate/primitives/src/hash.rs
@@ -41,6 +41,8 @@ impl_hash!(H160, 20);
 impl_serde!(H160, 20);
 impl_hash!(H256, 32);
 impl_serde!(H256, 32);
+impl_hash!(H520, 65);
+impl_serde!(H520, 65);
 
 #[cfg(test)]
 mod tests {
diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs
index c1e0b6aadf97e46a6e3c34f6bbada2d16af495ec..ca32f302f3e8fb639cbebb941fcae98bd5805d01 100644
--- a/substrate/primitives/src/lib.rs
+++ b/substrate/primitives/src/lib.rs
@@ -49,6 +49,9 @@ pub mod validator;
 
 /// Alias to 160-bit hash when used in the context of an account address.
 pub type Address = hash::H160;
+/// Alias to 520-bit hash when used in the context of a signature.
+pub type Signature = hash::H520;
+
 pub use self::hash::{H160, H256};
 pub use self::uint::{U256, U512};
 
diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs
index 5d80ffcf1f7d481bb480e403f7745b944aec1fad..7e931bed8434270290a19541f71ee24abfa45566 100644
--- a/substrate/primitives/src/parachain.rs
+++ b/substrate/primitives/src/parachain.rs
@@ -30,72 +30,85 @@ impl From<u64> for Id {
 	fn from(x: u64) -> Self { Id(x) }
 }
 
-/// A parachain block proposal.
-#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
+/// Candidate parachain block.
+///
+/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 #[serde(deny_unknown_fields)]
-pub struct Proposal {
+pub struct Candidate {
 	/// The ID of the parachain this is a proposal for.
-	pub parachain: Id,
-	/// Parachain block header bytes.
-	pub header: Header,
-	/// Hash of data necessary to prove validity of the header.
-	pub proof_hash: ProofHash,
+	pub parachain_index: Id,
+	/// Collator's signature
+	pub collator_signature: ::Signature,
+	/// Unprocessed ingress queue.
+	///
+	/// Ordered by parachain ID and block number.
+	pub unprocessed_ingress: Vec<(u64, Vec<Message>)>,
+	/// Block data
+	pub block: BlockData,
 }
 
-/// Parachain header raw bytes wrapper type.
-#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct Header(#[serde(with="bytes")] pub Vec<u8>);
+/// Parachain ingress queue message.
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
+pub struct Message(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Hash used to refer to proof of block header.
-pub type ProofHash = ::hash::H256;
+/// Parachain block data.
+///
+/// contains everything required to validate para-block, may contain block and witness data
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
+pub struct BlockData(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Raw proof data.
+/// Parachain header raw bytes wrapper type.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct RawProof(#[serde(with="bytes")] pub Vec<u8>);
-
-impl RawProof {
-	/// Compute and store the hash of the proof.
-	pub fn into_proof(self) -> Proof {
-		let hash = ::hash(&self.0);
-		Proof(self, hash)
-	}
-}
+pub struct Header(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Parachain proof data.
+/// Parachain head data included in the chain.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct Proof(RawProof, ProofHash);
-
-impl Proof {
-	/// Get raw proof data.
-	pub fn raw(&self) -> &RawProof { &self.0 }
-
-	/// Get hash of proof data.
-	pub fn hash(&self) -> &ProofHash { &self.1 }
-
-	/// Decompose the proof back into raw data and hash.
-	pub fn into_inner(self) -> (RawProof, ProofHash) {
-		(self.0, self.1)
-	}
-}
+pub struct HeadData(#[serde(with="bytes")] pub Vec<u8>);
 
 /// Parachain validation code.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 pub struct ValidationCode(#[serde(with="bytes")] pub Vec<u8>);
 
+/// Activitiy bit field
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Activity(#[serde(with="bytes")] pub Vec<u8>);
+
 #[cfg(test)]
 mod tests {
 	use super::*;
 	use polkadot_serializer as ser;
 
 	#[test]
-	fn test_proof_serialization() {
-		assert_eq!(
-			ser::to_string_pretty(&Proof(RawProof(vec![1,2,3]), 5.into())),
-			r#"[
-  "0x010203",
-  "0x0000000000000000000000000000000000000000000000000000000000000005"
-]"#
-		)
+	fn test_candidate() {
+		assert_eq!(ser::to_string_pretty(&Candidate {
+			parachain_index: 5.into(),
+			collator_signature: 10.into(),
+			unprocessed_ingress: vec![
+				(1, vec![Message(vec![2])]),
+				(2, vec![Message(vec![2]), Message(vec![3])]),
+			],
+			block: BlockData(vec![1, 2, 3]),
+    }), r#"{
+  "parachainIndex": 5,
+  "collatorSignature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a",
+  "unprocessedIngress": [
+    [
+      1,
+      [
+        "0x02"
+      ]
+    ],
+    [
+      2,
+      [
+        "0x02",
+        "0x03"
+      ]
+    ]
+  ],
+  "block": "0x010203"
+}"#);
 	}
 }
diff --git a/substrate/primitives/src/validator.rs b/substrate/primitives/src/validator.rs
index afdff7e20f31e888a0dd159d7770fde48d742015..b6de301cb492e1f674fb467fd697724310af59f0 100644
--- a/substrate/primitives/src/validator.rs
+++ b/substrate/primitives/src/validator.rs
@@ -17,49 +17,31 @@
 //! Validator primitives.
 
 use bytes;
+use parachain;
 
-/// Parachain incoming messages.
+/// Parachain outgoing message.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct IngressPosts(#[serde(with="bytes")] pub Vec<u8>);
+pub struct EgressPost(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Parachain incoming messages delta.
+/// Balance upload.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct IngressPostsDelta(#[serde(with="bytes")] pub Vec<u8>);
+pub struct BalanceUpload(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Parachain outgoing messages.
+/// Balance download.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct EgressPosts(#[serde(with="bytes")] pub Vec<u8>);
+pub struct BalanceDownload(#[serde(with="bytes")] pub Vec<u8>);
 
-/// Validity result of particular proof and ingress queue.
+/// The result of parachain validation.
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(tag="type", content="data")]
 #[serde(rename_all = "camelCase")]
 #[serde(deny_unknown_fields)]
-pub enum ProofValidity {
-	/// The proof is invalid.
-	Invalid,
-	/// The proof is processed and new egress queue is created.
-	/// Also includes current ingress queue delta.
-	Valid(IngressPostsDelta, EgressPosts),
-}
-
-impl ProofValidity {
-	/// The proof is valid.
-	pub fn is_valid(&self) -> bool {
-		match *self {
-			ProofValidity::Invalid => false,
-			ProofValidity::Valid(..) => true,
-		}
-	}
-}
-
-impl From<Option<(IngressPostsDelta, EgressPosts)>> for ProofValidity {
-	fn from(posts: Option<(IngressPostsDelta, EgressPosts)>) -> Self {
-		match posts {
-			Some((delta, posts)) => ProofValidity::Valid(delta, posts),
-			None => ProofValidity::Invalid,
-		}
-	}
+pub struct ValidationResult {
+	/// New head data that should be included in the relay chain state.
+	pub head_data: parachain::HeadData,
+	/// Outgoing messages (a vec for each parachain).
+	pub egress_queues: Vec<Vec<EgressPost>>,
+	/// Balance uploads
+	pub balance_uploads: Vec<BalanceUpload>,
 }
 
 // TODO [ToDr] This shouldn't be here!
@@ -73,10 +55,13 @@ pub trait Validator {
 	/// In case of success produces egress posts.
 	fn validate(
 		&self,
-		messages: &IngressPosts,
-		proof: &::parachain::Proof,
 		code: &[u8],
-	) -> Result<ProofValidity, Self::Error>;
+		// TODO [ToDr] actually consolidate
+		consolidated_ingress: &[(u64, Vec<parachain::Message>)],
+		balance_downloads: &[BalanceDownload],
+		block_data: &parachain::BlockData,
+		previous_head_data: &parachain::HeadData,
+	) -> Result<ValidationResult, Self::Error>;
 }
 
 #[cfg(test)]
@@ -85,19 +70,20 @@ mod tests {
 	use polkadot_serializer as ser;
 
 	#[test]
-	fn test_proof_validity_serialization() {
-		assert_eq!(
-			ser::to_string_pretty(&ProofValidity::Invalid),
-			r#"{
-  "type": "invalid"
-}"#);
-		assert_eq!(
-			ser::to_string_pretty(&ProofValidity::Valid(IngressPostsDelta(vec![1]), EgressPosts(vec![1, 2, 3]))),
-			r#"{
-  "type": "valid",
-  "data": [
-    "0x01",
-    "0x010203"
+	fn test_validation_result() {
+		assert_eq!(ser::to_string_pretty(&ValidationResult {
+	head_data: parachain::HeadData(vec![1]),
+	egress_queues: vec![vec![EgressPost(vec![1])]],
+	balance_uploads: vec![BalanceUpload(vec![2])],
+			}), r#"{
+  "headData": "0x01",
+  "egressQueues": [
+    [
+      "0x01"
+    ]
+  ],
+  "balanceUploads": [
+    "0x02"
   ]
 }"#);
 	}
diff --git a/substrate/rpc/src/chain/tests.rs b/substrate/rpc/src/chain/tests.rs
index 03cee366513ab39abf22ac3c2b9e5e9441c4eec7..00208b95981804c47adcd232a8c6a7fbf146a0c6 100644
--- a/substrate/rpc/src/chain/tests.rs
+++ b/substrate/rpc/src/chain/tests.rs
@@ -14,6 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
+use primitives::parachain;
 use super::*;
 
 use test_helpers::Blockchain;
@@ -26,9 +27,10 @@ fn should_return_header() {
 		ChainApi::header(&state, 0.into()),
 		Ok(Some(ref x)) if x == &block::Header {
 			parent_hash: 0.into(),
-			state_root: 0.into(),
-			timestamp: 0,
 			number: 0,
+			state_root: 0.into(),
+			parachain_activity: parachain::Activity(vec![0]),
+			logs: vec![],
 		}
 	);
 
diff --git a/substrate/rpc/src/test_helpers.rs b/substrate/rpc/src/test_helpers.rs
index 3866d657f4656d3a6ff4f333015c355f2f3e8576..6d2e23485b7c35424693bffea6f3fd45db7a5c70 100644
--- a/substrate/rpc/src/test_helpers.rs
+++ b/substrate/rpc/src/test_helpers.rs
@@ -15,7 +15,7 @@
 // along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
 
 use client;
-use primitives::block;
+use primitives::{block, parachain};
 
 /// Temporary dummy blockchain implementation for tests.
 #[derive(Debug, Default)]
@@ -33,10 +33,11 @@ impl client::Blockchain for Blockchain {
 			None
 		} else {
 			Some(block::Header {
-				number: 0,
 				parent_hash: 0.into(),
+				number: 0,
 				state_root: 0.into(),
-				timestamp: 0,
+				parachain_activity: parachain::Activity(vec![0]),
+				logs: vec![],
 			})
 		})
 	}
diff --git a/substrate/validator/src/parachains.rs b/substrate/validator/src/parachains.rs
index 7c73ffabae588c123237d36fbec74af4506c5ae9..5adfe704c7f75b68128548e850c6d4932a020800 100644
--- a/substrate/validator/src/parachains.rs
+++ b/substrate/validator/src/parachains.rs
@@ -19,16 +19,29 @@ use std::fmt;
 use primitives::validator;
 use serde::de::DeserializeOwned;
 
+use error::Result;
+
 /// Parachain code implementation.
 pub trait ParachainCode: fmt::Debug {
-	/// Deserialized messages type.
-	type Messages: DeserializeOwned;
-	/// Deserialized proof type.
-	type Proof: DeserializeOwned;
+	/// Deserialized message type.
+	type Message: DeserializeOwned;
+	/// Balance download.
+	type Download: DeserializeOwned;
+	/// Deserialized block data type.
+	type BlockData: DeserializeOwned;
+	/// Parachain head data.
+	type HeadData: DeserializeOwned;
+	/// Result
+	type Result: Into<validator::ValidationResult>;
 
 	/// Given decoded messages and proof validate it and return egress posts.
-	fn check(&self, messages: Self::Messages, proof: Self::Proof) ->
-		Option<(validator::IngressPostsDelta, validator::EgressPosts)>;
+	fn check(
+		&self,
+		messages: Vec<(u64, Vec<Self::Message>)>,
+		downloads: Vec<Self::Download>,
+		block_data: Self::BlockData,
+		head_data: Self::HeadData,
+	) -> Result<Self::Result>;
 }
 
 /// Dummy implementation of the first parachain validation.
@@ -36,11 +49,20 @@ pub trait ParachainCode: fmt::Debug {
 pub struct ParaChain1;
 
 impl ParachainCode for ParaChain1 {
-	type Messages = ();
-	type Proof = ();
+	type Message = ();
+	type Download = ();
+	type BlockData = ();
+	type HeadData = ();
+	type Result = validator::ValidationResult;
 
-	fn check(&self, _messages: Self::Messages, _proof: Self::Proof)
-		-> Option<(validator::IngressPostsDelta, validator::EgressPosts)> {
-		None
+	fn check(
+		&self,
+		_messages: Vec<(u64, Vec<Self::Message>)>,
+		_downloads: Vec<Self::Download>,
+		_block_data: Self::BlockData,
+		_head_data: Self::HeadData,
+	) -> Result<Self::Result>
+	{
+		unimplemented!()
 	}
 }
diff --git a/substrate/validator/src/validator.rs b/substrate/validator/src/validator.rs
index fcacc23d074793a48797701ffeaca27e21ad0067..40fa94b80d71cd1aa833a2c4f732462f246bdfb5 100644
--- a/substrate/validator/src/validator.rs
+++ b/substrate/validator/src/validator.rs
@@ -45,14 +45,16 @@ impl validator::Validator for Validator {
 
 	fn validate(
 		&self,
-		messages: &validator::IngressPosts,
-		proof: &parachain::Proof,
 		code: &[u8],
-	) -> Result<validator::ProofValidity> {
+		consolidated_ingress: &[(u64, Vec<parachain::Message>)],
+		balance_downloads: &[validator::BalanceDownload],
+		block_data: &parachain::BlockData,
+		previous_head_data: &parachain::HeadData,
+	) -> Result<validator::ValidationResult> {
 		ensure!(code.len() == 1, ErrorKind::InvalidCode(format!("The code should be a single byte.")));
 
 		match self.codes.get(code[0] as usize) {
-			Some(code) => code.check(messages, proof),
+			Some(code) => code.check(consolidated_ingress, balance_downloads, block_data, previous_head_data),
 			None => bail!(ErrorKind::InvalidCode(format!("Unknown parachain code."))),
 		}
 	}
@@ -60,20 +62,43 @@ impl validator::Validator for Validator {
 
 /// Simplified parachain code verification
 trait Code: fmt::Debug {
-	/// Given bytes of messages and proof determine if the proof is valid and return egress posts.
-	fn check(&self, messages: &validator::IngressPosts, proof: &parachain::Proof) -> Result<validator::ProofValidity>;
+	/// Given parachain candidate block data returns it's validity
+	/// and possible generated egress posts.
+	fn check(
+		&self,
+		consolidated_ingress: &[(u64, Vec<parachain::Message>)],
+		balance_downloads: &[validator::BalanceDownload],
+		block_data: &parachain::BlockData,
+		previous_head_data: &parachain::HeadData,
+	) -> Result<validator::ValidationResult>;
 }
 
-impl<M, P, T> Code for T where
+impl<M, B, T, R> Code for T where
 	M: DeserializeOwned,
-	P: DeserializeOwned,
-	T: ParachainCode<Messages=M, Proof=P>,
+	B: DeserializeOwned,
+	R: Into<validator::ValidationResult>,
+	T: ParachainCode<Message=M, BlockData=B, Result=R>,
 {
-	fn check(&self, messages: &validator::IngressPosts, proof: &parachain::Proof) -> Result<validator::ProofValidity> {
-		let messages = serializer::from_slice(&messages.0)?;
-		let proof = serializer::from_slice(&proof.raw().0)?;
+	fn check(
+		&self,
+		consolidated_ingress: &[(u64, Vec<parachain::Message>)],
+		balance_downloads: &[validator::BalanceDownload],
+		block_data: &parachain::BlockData,
+		previous_head_data: &parachain::HeadData,
+	) -> Result<validator::ValidationResult> {
+		let messages = consolidated_ingress.iter()
+			.map(|&(ref block, ref vec)| Ok((*block, vec.iter()
+				 .map(|msg| serializer::from_slice(&msg.0).map_err(Into::into))
+				 .collect::<Result<Vec<_>>>()?
+			)))
+			.collect::<Result<Vec<_>>>()?;
+		let downloads = balance_downloads.iter()
+			.map(|download| serializer::from_slice(&download.0).map_err(Into::into))
+			.collect::<Result<Vec<_>>>()?;
+		let block_data = serializer::from_slice(&block_data.0)?;
+		let head_data = serializer::from_slice(&previous_head_data.0)?;
 
-		Ok(self.check(messages, proof).into())
+		Ok(self.check(messages, downloads, block_data, head_data)?.into())
 	}
 }