diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs
index d9426be1cb3e0d9505b67566b33d8df34ec976ca..94c5dd51ac6c31b6ae0d06e50b8de8cba1469d19 100644
--- a/substrate/executor/src/native_executor.rs
+++ b/substrate/executor/src/native_executor.rs
@@ -50,7 +50,7 @@ mod tests {
 
 	const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm");
 	const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm");
-	fn tx() -> Vec<u8> {
+	fn tx() -> UncheckedTransaction {
 		let transaction = Transaction {
 			signed: one(),
 			nonce: 0,
@@ -60,7 +60,7 @@ mod tests {
 		let signature = secret_for(&transaction.signed).unwrap()
 			.sign(&transaction.to_vec())
 			.inner();
-		UncheckedTransaction { transaction, signature }.to_vec()
+		UncheckedTransaction { transaction, signature }
 	}
 
 	#[test]
@@ -70,7 +70,7 @@ mod tests {
 			twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0]
 		], };
 
-		let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(tx()));
+		let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_err());
 	}
 
@@ -81,7 +81,7 @@ mod tests {
 			twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0]
 		], };
 
-		let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(tx()));
+		let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_err());
 	}
 
@@ -94,7 +94,7 @@ mod tests {
 			twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
 		], };
 
-		let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(tx()));
+		let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_ok());
 
 		runtime_std::with_externalities(&mut t, || {
@@ -112,7 +112,7 @@ mod tests {
 			twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
 		], };
 
-		let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(tx()));
+		let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_ok());
 
 		runtime_std::with_externalities(&mut t, || {
diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs
index 5b87270724ef7891432109a699b49c5564057ce0..a9e8a856476699b53becbbacadd9515eeff52755 100644
--- a/substrate/executor/src/wasm_executor.rs
+++ b/substrate/executor/src/wasm_executor.rs
@@ -292,9 +292,9 @@ mod tests {
 	use rustc_hex::FromHex;
 	use primitives::{blake2_256, twox_128};
 	use runtime_std::{self, TestExternalities};
-	use native_runtime::support::{one, two, StaticHexInto};
-	use native_runtime::primitives::AccountID;
-	use native_runtime::codec::KeyedVec;
+	use native_runtime::support::{one, two};
+	use native_runtime::primitives::{UncheckedTransaction, AccountID};
+	use native_runtime::codec::{Joiner, KeyedVec};
 	use native_runtime::runtime::staking::balance;
 
 	#[test]
@@ -412,7 +412,7 @@ mod tests {
 		}
 	}
 
-	fn tx() -> Vec<u8> {
+	fn tx() -> UncheckedTransaction {
 		use native_runtime::codec::{Joiner, Slicable};
 		use native_runtime::support::{one, two};
 		use native_runtime::primitives::*;
@@ -425,7 +425,7 @@ mod tests {
 		let signature = secret_for(&transaction.signed).unwrap()
 			.sign(&transaction.to_vec())
 			.inner();
-		UncheckedTransaction { transaction, signature }.to_vec()
+		UncheckedTransaction { transaction, signature }
 	}
 
 	#[test]
@@ -436,7 +436,7 @@ mod tests {
 		], };
 
 		let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm");
-		let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx()));
+		let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_err());
 	}
 
@@ -450,7 +450,7 @@ mod tests {
 		], };
 
 		let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm");
-		let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx()));
+		let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(vec![].join(&1u64).join(&tx())));
 		assert!(r.is_ok());
 
 		runtime_std::with_externalities(&mut t, || {
diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs
index 33bf5546766e8ad019b4b98757d44cb4c57d5640..32d026e42f4643956aa3201e10809ae1fa0479ba 100644
--- a/substrate/wasm-runtime/polkadot/src/lib.rs
+++ b/substrate/wasm-runtime/polkadot/src/lib.rs
@@ -38,7 +38,7 @@ pub mod runtime;
 use runtime_std::prelude::*;
 use codec::Slicable;
 use runtime_std::print;
-use primitives::{Block, UncheckedTransaction};
+use primitives::{Block, Header, BlockNumber, UncheckedTransaction};
 
 /// Execute a block, with `input` being the canonical serialisation of the block. Returns the
 /// empty vector.
@@ -49,8 +49,9 @@ pub fn execute_block(input: &[u8]) -> Vec<u8> {
 
 /// Execute a given, serialised, transaction. Returns the empty vector.
 pub fn execute_transaction(input: &[u8]) -> Vec<u8> {
-	let utx = UncheckedTransaction::from_slice(input).unwrap();
-	runtime::system::internal::execute_transaction(&utx);
+	let number = BlockNumber::from_slice(&input[0..8]).unwrap();
+	let utx = UncheckedTransaction::from_slice(&input[8..]).unwrap();
+	runtime::system::internal::execute_transaction(&utx, Header::from_block_number(number));
 	Vec::new()
 }
 
diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs
index c97d5ebf29743dcb560c554afc860a8f27214fa8..c37634cff58ced3d376aaa0cdc100a291d4af459 100644
--- a/substrate/wasm-runtime/polkadot/src/primitives/header.rs
+++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs
@@ -37,6 +37,18 @@ pub struct Header {
 	pub digest: Digest,
 }
 
+impl Header {
+	pub fn from_block_number(number: BlockNumber) -> Self {
+		Header {
+			parent_hash: Default::default(),
+			number,
+			state_root: Default::default(),
+			transaction_root: Default::default(),
+			digest: Default::default(),
+		}
+	}
+}
+
 impl Slicable for Header {
 	fn from_slice(value: &[u8]) -> Option<Self> {
 		let mut reader = StreamReader::new(value);
diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs
index 495c60701a619530a226e4041a3f3ae3efc65248..2c195dbb72d3c21bc10e15918e6ec489aefc5d95 100644
--- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs
+++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs
@@ -151,9 +151,9 @@ mod tests {
 			twox_128(&0u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![10; 32],
 			twox_128(&1u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![20; 32],
 			// initial session keys (11, 21, ...)
-			twox_128(b"con:aut:len").to_vec() => vec![].join(&2u32),
-			twox_128(&0u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![11; 32],
-			twox_128(&1u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![21; 32]
+			b"con:aut:len".to_vec() => vec![].join(&2u32),
+			0u32.to_keyed_vec(b"con:aut:") => vec![11; 32],
+			1u32.to_keyed_vec(b"con:aut:") => vec![21; 32]
 		], }
 	}
 
diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs
index 3bad5413621f7ae64caaf2074986daf87bd80007..e6d93e94923297e3ca0a83dc386b466ea7189356 100644
--- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs
+++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs
@@ -21,7 +21,7 @@ use runtime_std::prelude::*;
 use runtime_std::{mem, storage_root, enumerated_trie_root};
 use codec::{KeyedVec, Slicable};
 use support::{Hashable, storage, with_env};
-use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder};
+use primitives::{Block, BlockNumber, Header, Hash, UncheckedTransaction, TxOrder};
 use runtime::{staking, session};
 
 const NONCE_OF: &[u8] = b"sys:non:";
@@ -84,7 +84,7 @@ pub mod internal {
 
 		// execute transactions
 		for tx in &block.transactions {
-			execute_transaction(tx);
+			super::execute_transaction(tx);
 		}
 
 		staking::internal::check_new_era();
@@ -98,29 +98,34 @@ pub mod internal {
 		debug_assert_hash(&header.state_root, &storage_root);
 		assert!(header.state_root == storage_root, "Storage root must match that calculated.");
 
-		// store the header hash in storage; we can't do it before otherwise there would be a
-		// cyclic dependency.
-		let header_hash_key = header.number.to_keyed_vec(BLOCK_HASH_AT);
-		storage::put(&header_hash_key, &header.blake2_256());
+		// any stuff that we do after taking the storage root.
+		post_finalise(header);
 	}
 
-	/// Execute a given transaction.
-	pub fn execute_transaction(utx: &UncheckedTransaction) {
-		// Verify the signature is good.
-		assert!(utx.ed25519_verify(), "All transactions should be properly signed");
+	/// Execute a transaction outside of the block execution function.
+	/// This doesn't attempt to validate anything regarding the block.
+	pub fn execute_transaction(utx: &UncheckedTransaction, mut header: Header) {
+		// populate environment from header.
+		with_env(|e| {
+			e.block_number = header.number;
+			mem::swap(&mut e.digest, &mut header.digest);
+			e.next_log_index = 0;
+		});
 
-		let ref tx = utx.transaction;
+		super::execute_transaction(utx);
+	}
+
+	/// Finalise the block - it is up the caller to ensure that all header fields are valid
+	/// except state-root.
+	pub fn finalise_block(mut header: Header) -> Header {
+		staking::internal::check_new_era();
+		session::internal::check_rotate_session();
 
-		// check nonce
-		let nonce_key = tx.signed.to_keyed_vec(NONCE_OF);
-		let expected_nonce: TxOrder = storage::get_or(&nonce_key, 0);
-		assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce");
+		header.state_root = storage_root();
 
-		// increment nonce in storage
-		storage::put(&nonce_key, &(expected_nonce + 1));
+		post_finalise(&header);
 
-		// decode parameters and dispatch
-		tx.function.dispatch(&tx.signed, &tx.input_data);
+		header
 	}
 
 	#[cfg(feature = "with-std")]
@@ -135,12 +140,36 @@ pub mod internal {
 	fn debug_assert_hash(_given: &Hash, _expected: &Hash) {}
 }
 
+fn execute_transaction(utx: &UncheckedTransaction) {
+	// Verify the signature is good.
+	assert!(utx.ed25519_verify(), "All transactions should be properly signed");
+
+	let ref tx = utx.transaction;
+
+	// check nonce
+	let nonce_key = tx.signed.to_keyed_vec(NONCE_OF);
+	let expected_nonce: TxOrder = storage::get_or(&nonce_key, 0);
+	assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce");
+
+	// increment nonce in storage
+	storage::put(&nonce_key, &(expected_nonce + 1));
+
+	// decode parameters and dispatch
+	tx.function.dispatch(&tx.signed, &tx.input_data);
+}
+
 fn final_checks(_block: &Block) {
 	with_env(|e| {
 		assert_eq!(e.next_log_index, e.digest.logs.len());
 	});
 }
 
+fn post_finalise(header: &Header) {
+	// store the header hash in storage; we can't do it before otherwise there would be a
+	// cyclic dependency.
+	storage::put(&header.number.to_keyed_vec(BLOCK_HASH_AT), &header.blake2_256());
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
@@ -174,7 +203,7 @@ mod tests {
 		println!("tx is {}", HexDisplay::from(&tx.transaction.to_vec()));
 
 		with_externalities(&mut t, || {
-			execute_transaction(&tx);
+			internal::execute_transaction(&tx, Header::from_block_number(1));
 			assert_eq!(staking::balance(&one), 42);
 			assert_eq!(staking::balance(&two), 69);
 		});