diff --git a/Cargo.lock b/Cargo.lock
index 6eefaabce9d229ae6cf99b38a37791fddda8537c..d526d6f65f10b77b5810e7d9afc575c88420978c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5221,6 +5221,7 @@ name = "substrate-runtime-test"
 version = "2.0.0"
 dependencies = [
  "sr-io 2.0.0",
+ "sr-primitives 2.0.0",
  "sr-sandbox 2.0.0",
  "sr-std 2.0.0",
  "substrate-primitives 2.0.0",
diff --git a/core/application-crypto/src/ed25519.rs b/core/application-crypto/src/ed25519.rs
index 209743bd281a9de3d544d51491091ca40d61b551..a1aef4a328d0742dfdbe94ba129f2d98b2f41541 100644
--- a/core/application-crypto/src/ed25519.rs
+++ b/core/application-crypto/src/ed25519.rs
@@ -42,7 +42,7 @@ impl RuntimePublic for Public {
 	}
 
 	fn sign<M: AsRef<[u8]>>(&self, key_type: KeyTypeId, msg: &M) -> Option<Self::Signature> {
-		runtime_io::ed25519_sign(key_type, self, msg)
+		runtime_io::ed25519_sign(key_type, self, msg.as_ref())
 	}
 
 	fn verify<M: AsRef<[u8]>>(&self, msg: &M, signature: &Self::Signature) -> bool {
diff --git a/core/application-crypto/src/sr25519.rs b/core/application-crypto/src/sr25519.rs
index e333208966541217ec7c0dccc0a9bf77e285a479..c3cc9df267e1747cc14744dbd5b71e130a50609f 100644
--- a/core/application-crypto/src/sr25519.rs
+++ b/core/application-crypto/src/sr25519.rs
@@ -42,7 +42,7 @@ impl RuntimePublic for Public {
 	}
 
 	fn sign<M: AsRef<[u8]>>(&self, key_type: KeyTypeId, msg: &M) -> Option<Self::Signature> {
-		runtime_io::sr25519_sign(key_type, self, msg)
+		runtime_io::sr25519_sign(key_type, self, msg.as_ref())
 	}
 
 	fn verify<M: AsRef<[u8]>>(&self, msg: &M, signature: &Self::Signature) -> bool {
diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs
index 722309b415e8bf0f9c46219bf6e1c2f6b5f6b742..4acb178506e3297ed9a33245ec129e170d64184d 100644
--- a/core/client/db/src/lib.rs
+++ b/core/client/db/src/lib.rs
@@ -1527,7 +1527,7 @@ mod tests {
 		let header = Header {
 			number,
 			parent_hash,
-			state_root: BlakeTwo256::trie_root::<_, &[u8], &[u8]>(Vec::new()),
+			state_root: BlakeTwo256::trie_root(Vec::new()),
 			digest,
 			extrinsics_root,
 		};
diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs
index b6fae5068a28445d7f312943afa874924ae64f38..08711469e9a1b5164721bd186f914a4389805b3f 100644
--- a/core/client/src/block_builder/block_builder.rs
+++ b/core/client/src/block_builder/block_builder.rs
@@ -128,7 +128,7 @@ where
 		debug_assert_eq!(
 			self.header.extrinsics_root().clone(),
 			HashFor::<Block>::ordered_trie_root(
-				self.extrinsics.iter().map(Encode::encode)
+				self.extrinsics.iter().map(Encode::encode).collect(),
 			),
 		);
 
diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs
index 2f31462955e311a81c96c3bd5682ba76baa61807..796d1417f24f04ec8cfaa09697adfe18ca022d07 100644
--- a/core/client/src/genesis.rs
+++ b/core/client/src/genesis.rs
@@ -25,7 +25,7 @@ pub fn construct_genesis_block<
 	state_root: Block::Hash
 ) -> Block {
 	let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-		std::iter::empty::<(&[u8], &[u8])>(),
+		Vec::new(),
 	);
 
 	Block::new(
diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs
index c25092c32c1f17528958ab535e0e6eabd8eeb323..068534c5f64ec87275af9b8e725495ae3fef436d 100644
--- a/core/client/src/light/fetcher.rs
+++ b/core/client/src/light/fetcher.rs
@@ -436,7 +436,9 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
 		body: Vec<Block::Extrinsic>
 	) -> ClientResult<Vec<Block::Extrinsic>> {
 		// TODO: #2621
-		let	extrinsics_root = HashFor::<Block>::ordered_trie_root(body.iter().map(Encode::encode));
+		let	extrinsics_root = HashFor::<Block>::ordered_trie_root(
+			body.iter().map(Encode::encode).collect(),
+		);
 		if *request.header.extrinsics_root() == extrinsics_root {
 			Ok(body)
 		} else {
diff --git a/core/executor/runtime-test/Cargo.toml b/core/executor/runtime-test/Cargo.toml
index 28a0ed2b874aaa5fbf71ef4b17ea192524fa8a45..fcdacd98ca458d5d04572775b7a359135c9b486f 100644
--- a/core/executor/runtime-test/Cargo.toml
+++ b/core/executor/runtime-test/Cargo.toml
@@ -10,6 +10,7 @@ rstd = { package = "sr-std", path = "../../sr-std", default-features = false }
 runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false }
 sandbox = { package = "sr-sandbox", path = "../../sr-sandbox", default-features = false }
 primitives = { package = "substrate-primitives",  path = "../../primitives", default-features = false }
+sr-primitives = { package = "sr-primitives",  path = "../../sr-primitives", default-features = false }
 
 [build-dependencies]
 wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.2", path = "../../utils/wasm-builder-runner" }
diff --git a/core/executor/runtime-test/src/lib.rs b/core/executor/runtime-test/src/lib.rs
index 5e276a88141684eb520cea68bd0a114117a67881..35f3191ffdf5cc13260aabe377d34c2b95481246 100644
--- a/core/executor/runtime-test/src/lib.rs
+++ b/core/executor/runtime-test/src/lib.rs
@@ -8,9 +8,10 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
 use rstd::{vec::Vec, slice, vec};
 
 use runtime_io::{
-	set_storage, storage, clear_prefix, print, blake2_128, blake2_256,
-	twox_128, twox_256, ed25519_verify, sr25519_verify, ordered_trie_root
+	set_storage, storage, clear_prefix, blake2_128, blake2_256,
+	twox_128, twox_256, ed25519_verify, sr25519_verify,
 };
+use sr_primitives::{print, traits::{BlakeTwo256, Hash}};
 use primitives::{ed25519, sr25519};
 
 macro_rules! impl_stubs {
@@ -94,12 +95,12 @@ impl_stubs!(
 		[sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) as u8].to_vec()
 	},
 	test_ordered_trie_root => |_| {
-		ordered_trie_root::<primitives::Blake2Hasher, _, _>(
-			&[
-				&b"zero"[..],
-				&b"one"[..],
-				&b"two"[..],
-			]
+		BlakeTwo256::ordered_trie_root(
+			vec![
+				b"zero"[..].into(),
+				b"one"[..].into(),
+				b"two"[..].into(),
+			],
 		).as_ref().to_vec()
 	},
 	test_sandbox => |code: &[u8]| {
diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs
index 38b8d8eff17e342093ed6b452d948cd95e69b86c..cc7d5d9344ddb2084b99a6d0b41f503ac99d7cf4 100644
--- a/core/executor/src/wasm_executor.rs
+++ b/core/executor/src/wasm_executor.rs
@@ -31,7 +31,7 @@ use crate::error::{Error, Result};
 use codec::{Encode, Decode};
 use primitives::{
 	blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Pair, crypto::KeyTypeId,
-	offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, Blake2Hasher,
+	offchain, sandbox as sandbox_primitives, Blake2Hasher,
 	traits::Externalities,
 };
 use trie::{TrieConfiguration, trie_types::Layout};
@@ -418,22 +418,20 @@ impl_wasm_host_interface! {
 
 		ext_print_utf8(utf8_data: Pointer<u8>, utf8_len: WordSize) {
 			if let Ok(utf8) = context.read_memory(utf8_data, utf8_len) {
-				if let Ok(message) = String::from_utf8(utf8) {
-					println!("{}", message);
-				}
+				runtime_io::print_utf8(&utf8);
 			}
 			Ok(())
 		}
 
 		ext_print_hex(data: Pointer<u8>, len: WordSize) {
 			if let Ok(hex) = context.read_memory(data, len) {
-				println!("{}", HexDisplay::from(&hex));
+				runtime_io::print_hex(&hex);
 			}
 			Ok(())
 		}
 
 		ext_print_num(number: u64) {
-			println!("{}", number);
+			runtime_io::print_num(number);
 			Ok(())
 		}
 
diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs
index 642b3e488175ad84f2a578595c2f7ae588fd07bc..aee9e23909b22460b654ea466dbedb81c8a17196 100644
--- a/core/sr-io/src/lib.rs
+++ b/core/sr-io/src/lib.rs
@@ -29,12 +29,8 @@
 use hash_db::Hasher;
 use rstd::vec::Vec;
 
-#[doc(hidden)]
-pub use codec;
-
-pub use primitives::Blake2Hasher;
 use primitives::{
-	crypto::KeyTypeId, ed25519, sr25519,
+	crypto::KeyTypeId, ed25519, sr25519, H256,
 	offchain::{
 		Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState,
 	},
@@ -52,18 +48,6 @@ pub enum EcdsaVerifyError {
 
 pub mod offchain;
 
-/// Trait for things which can be printed.
-pub trait Printable {
-	/// Print the object.
-	fn print(&self);
-}
-
-impl Printable for u8 {
-	fn print(&self) {
-		u64::from(*self).print()
-	}
-}
-
 /// Converts a public trait definition into a private trait and set of public functions
 /// that assume the trait is implemented for `()` for ease of calling.
 macro_rules! export_api {
@@ -73,7 +57,6 @@ macro_rules! export_api {
 			$(
 				$( #[$attr:meta] )*
 				fn $name:ident
-					$(< $( $g_name:ident $( : $g_ty:path )? ),+ >)?
 					( $( $arg:ident : $arg_ty:ty ),* $(,)? )
 					$( -> $ret:ty )?
 					$( where $( $w_name:path : $w_ty:path ),+ )?;
@@ -84,18 +67,18 @@ macro_rules! export_api {
 		pub(crate) trait $trait_name {
 			$(
 				$( #[$attr] )*
-				fn $name $(< $( $g_name $( : $g_ty )? ),+ >)? ( $($arg : $arg_ty ),* ) $( -> $ret )?
+				fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )?
 				$( where $( $w_name : $w_ty ),+ )?;
 			)*
 		}
 
 		$(
 			$( #[$attr] )*
-			pub fn $name $(< $( $g_name $( : $g_ty )? ),+ >)? ( $($arg : $arg_ty ),* ) $( -> $ret )?
+			pub fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )?
 				$( where $( $w_name : $w_ty ),+ )?
 			{
 				#[allow(deprecated)]
-				<()>:: $name $(::< $( $g_name ),+ > )?  ( $( $arg ),* )
+				<()>:: $name ( $( $arg ),* )
 			}
 		)*
 	}
@@ -160,26 +143,10 @@ export_api! {
 		fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]>;
 
 		/// A trie root formed from the iterated items.
-		fn trie_root<H, I, A, B>(input: I) -> H::Out
-		where
-			I: IntoIterator<Item = (A, B)>,
-			A: AsRef<[u8]>,
-			A: Ord,
-			B: AsRef<[u8]>,
-			H: Hasher,
-			H: self::imp::HasherBounds,
-			H::Out: Ord
-		;
+		fn blake2_256_trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256;
 
 		/// A trie root formed from the enumerated items.
-		fn ordered_trie_root<H, I, A>(input: I) -> H::Out
-		where
-			I: IntoIterator<Item = A>,
-			A: AsRef<[u8]>,
-			H: Hasher,
-			H: self::imp::HasherBounds,
-			H::Out: Ord
-		;
+		fn blake2_256_ordered_trie_root(input: Vec<Vec<u8>>) -> H256;
 	}
 }
 
@@ -188,12 +155,12 @@ export_api! {
 		/// The current relay chain identifier.
 		fn chain_id() -> u64;
 
-		/// Print a printable value.
-		fn print<T>(value: T)
-		where
-			T: Printable,
-			T: Sized
-		;
+		/// Print a number.
+		fn print_num(val: u64);
+		/// Print any valid `utf8` buffer.
+		fn print_utf8(utf8: &[u8]);
+		/// Print any `u8` slice as hex.
+		fn print_hex(data: &[u8]);
 	}
 }
 
@@ -209,10 +176,10 @@ export_api! {
 		/// key type in the keystore.
 		///
 		/// Returns the raw signature.
-		fn ed25519_sign<M: AsRef<[u8]>>(
+		fn ed25519_sign(
 			id: KeyTypeId,
 			pubkey: &ed25519::Public,
-			msg: &M,
+			msg: &[u8],
 		) -> Option<ed25519::Signature>;
 		/// Verify an ed25519 signature.
 		///
@@ -229,10 +196,10 @@ export_api! {
 		/// key type in the keystore.
 		///
 		/// Returns the raw signature.
-		fn sr25519_sign<M: AsRef<[u8]>>(
+		fn sr25519_sign(
 			id: KeyTypeId,
 			pubkey: &sr25519::Public,
-			msg: &M,
+			msg: &[u8],
 		) -> Option<sr25519::Signature>;
 		/// Verify an sr25519 signature.
 		///
@@ -315,7 +282,7 @@ export_api! {
 			kind: StorageKind,
 			key: &[u8],
 			old_value: Option<&[u8]>,
-			new_value: &[u8]
+			new_value: &[u8],
 		) -> bool;
 
 		/// Gets a value from the local storage.
@@ -332,14 +299,14 @@ export_api! {
 		fn http_request_start(
 			method: &str,
 			uri: &str,
-			meta: &[u8]
+			meta: &[u8],
 		) -> Result<HttpRequestId, ()>;
 
 		/// Append header to the request.
 		fn http_request_add_header(
 			request_id: HttpRequestId,
 			name: &str,
-			value: &str
+			value: &str,
 		) -> Result<(), ()>;
 
 		/// Write a chunk of request body.
@@ -351,7 +318,7 @@ export_api! {
 		fn http_request_write_body(
 			request_id: HttpRequestId,
 			chunk: &[u8],
-			deadline: Option<Timestamp>
+			deadline: Option<Timestamp>,
 		) -> Result<(), HttpError>;
 
 		/// Block and wait for the responses for given requests.
@@ -363,16 +330,14 @@ export_api! {
 		/// Passing `None` as deadline blocks forever.
 		fn http_response_wait(
 			ids: &[HttpRequestId],
-			deadline: Option<Timestamp>
+			deadline: Option<Timestamp>,
 		) -> Vec<HttpRequestStatus>;
 
 		/// Read all response headers.
 		///
 		/// Returns a vector of pairs `(HeaderKey, HeaderValue)`.
 		/// NOTE response headers have to be read before response body.
-		fn http_response_headers(
-			request_id: HttpRequestId
-		) -> Vec<(Vec<u8>, Vec<u8>)>;
+		fn http_response_headers(request_id: HttpRequestId) -> Vec<(Vec<u8>, Vec<u8>)>;
 
 		/// Read a chunk of body response to given buffer.
 		///
@@ -385,7 +350,7 @@ export_api! {
 		fn http_response_read_body(
 			request_id: HttpRequestId,
 			buffer: &mut [u8],
-			deadline: Option<Timestamp>
+			deadline: Option<Timestamp>,
 		) -> Result<usize, HttpError>;
 	}
 }
diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs
index 41baf295328c6eb22ac6e018924f44def167da75..f93194bb4740960688773570299cf24b95127f5a 100644
--- a/core/sr-io/with_std.rs
+++ b/core/sr-io/with_std.rs
@@ -15,15 +15,14 @@
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
 use primitives::{
-	blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair,
-	traits::Externalities, child_storage_key::ChildStorageKey,
+	blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, H256,
+	traits::Externalities, child_storage_key::ChildStorageKey, hexdisplay::HexDisplay, offchain,
 };
 // Switch to this after PoC-3
 // pub use primitives::BlakeHasher;
 pub use substrate_state_machine::{BasicExternalities, TestExternalities};
 
 use environmental::environmental;
-use primitives::{offchain, hexdisplay::HexDisplay, H256};
 use trie::{TrieConfiguration, trie_types::Layout};
 
 use std::{collections::HashMap, convert::TryFrom};
@@ -166,25 +165,12 @@ impl StorageApi for () {
 		).unwrap_or(Ok(None)).expect("Invalid parent hash passed to storage_changes_root")
 	}
 
-	fn trie_root<H, I, A, B>(input: I) -> H::Out
-	where
-		I: IntoIterator<Item = (A, B)>,
-		A: AsRef<[u8]> + Ord,
-		B: AsRef<[u8]>,
-		H: Hasher,
-		H::Out: Ord,
-	{
-		Layout::<H>::trie_root(input)
+	fn blake2_256_trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
+		Layout::<Blake2Hasher>::trie_root(input)
 	}
 
-	fn ordered_trie_root<H, I, A>(input: I) -> H::Out
-	where
-		I: IntoIterator<Item = A>,
-		A: AsRef<[u8]>,
-		H: Hasher,
-		H::Out: Ord,
-	{
-		Layout::<H>::ordered_trie_root(input)
+	fn blake2_256_ordered_trie_root(input: Vec<Vec<u8>>) -> H256 {
+		Layout::<Blake2Hasher>::ordered_trie_root(input)
 	}
 }
 
@@ -195,8 +181,18 @@ impl OtherApi for () {
 		).unwrap_or(0)
 	}
 
-	fn print<T: Printable + Sized>(value: T) {
-		value.print()
+	fn print_num(val: u64) {
+		println!("{}", val);
+	}
+
+	fn print_utf8(utf8: &[u8]) {
+		if let Ok(data) = std::str::from_utf8(utf8) {
+			println!("{}", data)
+		}
+	}
+
+	fn print_hex(data: &[u8]) {
+		println!("{}", HexDisplay::from(&data));
 	}
 }
 
@@ -220,10 +216,10 @@ impl CryptoApi for () {
 		}).expect("`ed25519_generate` cannot be called outside of an Externalities-provided environment.")
 	}
 
-	fn ed25519_sign<M: AsRef<[u8]>>(
+	fn ed25519_sign(
 		id: KeyTypeId,
 		pubkey: &ed25519::Public,
-		msg: &M,
+		msg: &[u8],
 	) -> Option<ed25519::Signature> {
 		let pub_key = ed25519::Public::try_from(pubkey.as_ref()).ok()?;
 
@@ -232,7 +228,7 @@ impl CryptoApi for () {
 				.expect("No `keystore` associated for the current context!")
 				.read()
 				.ed25519_key_pair(id, &pub_key)
-				.map(|k| k.sign(msg.as_ref()))
+				.map(|k| k.sign(msg))
 		}).expect("`ed25519_sign` cannot be called outside of an Externalities-provided environment.")
 	}
 
@@ -259,10 +255,10 @@ impl CryptoApi for () {
 		}).expect("`sr25519_generate` cannot be called outside of an Externalities-provided environment.")
 	}
 
-	fn sr25519_sign<M: AsRef<[u8]>>(
+	fn sr25519_sign(
 		id: KeyTypeId,
 		pubkey: &sr25519::Public,
-		msg: &M,
+		msg: &[u8],
 	) -> Option<sr25519::Signature> {
 		let pub_key = sr25519::Public::try_from(pubkey.as_ref()).ok()?;
 
@@ -271,7 +267,7 @@ impl CryptoApi for () {
 				.expect("No `keystore` associated for the current context!")
 				.read()
 				.sr25519_key_pair(id, &pub_key)
-				.map(|k| k.sign(msg.as_ref()))
+				.map(|k| k.sign(msg))
 		}).expect("`sr25519_sign` cannot be called outside of an Externalities-provided environment.")
 	}
 
@@ -389,7 +385,7 @@ impl OffchainApi for () {
 	fn http_request_start(
 		method: &str,
 		uri: &str,
-		meta: &[u8]
+		meta: &[u8],
 	) -> Result<offchain::HttpRequestId, ()> {
 		with_offchain(|ext| {
 			ext.http_request_start(method, uri, meta)
@@ -399,7 +395,7 @@ impl OffchainApi for () {
 	fn http_request_add_header(
 		request_id: offchain::HttpRequestId,
 		name: &str,
-		value: &str
+		value: &str,
 	) -> Result<(), ()> {
 		with_offchain(|ext| {
 			ext.http_request_add_header(request_id, name, value)
@@ -409,7 +405,7 @@ impl OffchainApi for () {
 	fn http_request_write_body(
 		request_id: offchain::HttpRequestId,
 		chunk: &[u8],
-		deadline: Option<offchain::Timestamp>
+		deadline: Option<offchain::Timestamp>,
 	) -> Result<(), offchain::HttpError> {
 		with_offchain(|ext| {
 			ext.http_request_write_body(request_id, chunk, deadline)
@@ -418,7 +414,7 @@ impl OffchainApi for () {
 
 	fn http_response_wait(
 		ids: &[offchain::HttpRequestId],
-		deadline: Option<offchain::Timestamp>
+		deadline: Option<offchain::Timestamp>,
 	) -> Vec<offchain::HttpRequestStatus> {
 		with_offchain(|ext| {
 			ext.http_response_wait(ids, deadline)
@@ -426,7 +422,7 @@ impl OffchainApi for () {
 	}
 
 	fn http_response_headers(
-		request_id: offchain::HttpRequestId
+		request_id: offchain::HttpRequestId,
 	) -> Vec<(Vec<u8>, Vec<u8>)> {
 		with_offchain(|ext| {
 			ext.http_response_headers(request_id)
@@ -436,7 +432,7 @@ impl OffchainApi for () {
 	fn http_response_read_body(
 		request_id: offchain::HttpRequestId,
 		buffer: &mut [u8],
-		deadline: Option<offchain::Timestamp>
+		deadline: Option<offchain::Timestamp>,
 	) -> Result<usize, offchain::HttpError> {
 		with_offchain(|ext| {
 			ext.http_response_read_body(request_id, buffer, deadline)
@@ -477,24 +473,6 @@ pub fn with_storage<R, F: FnOnce() -> R>(
 	r
 }
 
-impl<'a> Printable for &'a [u8] {
-	fn print(&self) {
-		println!("Runtime: {}", HexDisplay::from(self));
-	}
-}
-
-impl<'a> Printable for &'a str {
-	fn print(&self) {
-		println!("Runtime: {}", self);
-	}
-}
-
-impl Printable for u64 {
-	fn print(&self) {
-		println!("Runtime: {}", self);
-	}
-}
-
 #[cfg(test)]
 mod std_tests {
 	use super::*;
diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs
index f7b0ce9b02a9c36c19570da36e871e29999482e6..6803b41ebd3fb64abbd544aed40eeb44a7c78b1f 100644
--- a/core/sr-io/without_std.rs
+++ b/core/sr-io/without_std.rs
@@ -126,44 +126,6 @@ pub mod ext {
 		}
 	}
 
-	/// Ensures we use the right crypto when calling into native
-	pub trait ExternTrieCrypto: Hasher {
-		/// A trie root formed from the enumerated items.
-		fn ordered_trie_root<
-			A: AsRef<[u8]>,
-			I: IntoIterator<Item = A>
-		>(values: I) -> Self::Out;
-	}
-
-	/// Additional bounds for Hasher trait for without_std.
-	pub trait HasherBounds: ExternTrieCrypto {}
-	impl<T: ExternTrieCrypto + Hasher> HasherBounds for T {}
-
-	// Ensures we use a Blake2_256-flavored Hasher when calling into native
-	impl ExternTrieCrypto for Blake2Hasher {
-		fn ordered_trie_root<
-			A: AsRef<[u8]>,
-			I: IntoIterator<Item = A>
-		>(items: I) -> Self::Out {
-			let mut values = Vec::new();
-			let mut lengths = Vec::new();
-			for v in items.into_iter() {
-				values.extend_from_slice(v.as_ref());
-				lengths.push((v.as_ref().len() as u32).to_le());
-			}
-			let mut result: [u8; 32] = Default::default();
-			unsafe {
-				ext_blake2_256_enumerated_trie_root.get()(
-					values.as_ptr(),
-					lengths.as_ptr(),
-					lengths.len() as u32,
-					result.as_mut_ptr()
-				);
-			}
-			result.into()
-		}
-	}
-
 	/// Declare extern functions
 	macro_rules! extern_functions {
 		(
@@ -228,7 +190,7 @@ pub mod ext {
 			storage_key_data: *const u8,
 			storage_key_len: u32,
 			prefix_data: *const u8,
-			prefix_len: u32
+			prefix_len: u32,
 		);
 		/// Gets the value of the given key from storage.
 		///
@@ -255,7 +217,7 @@ pub mod ext {
 			key_len: u32,
 			value_data: *mut u8,
 			value_len: u32,
-			value_offset: u32
+			value_offset: u32,
 		) -> u32;
 		/// Gets the trie root of the storage.
 		fn ext_storage_root(result: *mut u8);
@@ -266,7 +228,10 @@ pub mod ext {
 		/// - `1` if the change trie root was found.
 		/// - `0` if the change trie root was not found.
 		fn ext_storage_changes_root(
-			parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32;
+			parent_hash_data: *const u8,
+			parent_hash_len: u32,
+			result: *mut u8,
+		) -> u32;
 
 		/// A child storage function.
 		///
@@ -279,7 +244,7 @@ pub mod ext {
 			key_data: *const u8,
 			key_len: u32,
 			value_data: *const u8,
-			value_len: u32
+			value_len: u32,
 		);
 		/// A child storage function.
 		///
@@ -290,7 +255,7 @@ pub mod ext {
 			storage_key_data: *const u8,
 			storage_key_len: u32,
 			key_data: *const u8,
-			key_len: u32
+			key_len: u32,
 		);
 		/// A child storage function.
 		///
@@ -301,7 +266,7 @@ pub mod ext {
 			storage_key_data: *const u8,
 			storage_key_len: u32,
 			key_data: *const u8,
-			key_len: u32
+			key_len: u32,
 		) -> u32;
 		/// A child storage function.
 		///
@@ -319,7 +284,7 @@ pub mod ext {
 			storage_key_len: u32,
 			key_data: *const u8,
 			key_len: u32,
-			written_out: *mut u32
+			written_out: *mut u32,
 		) -> *mut u8;
 		/// A child storage function.
 		///
@@ -333,7 +298,7 @@ pub mod ext {
 			key_len: u32,
 			value_data: *mut u8,
 			value_len: u32,
-			value_offset: u32
+			value_offset: u32,
 		) -> u32;
 		/// Commits all changes and calculates the child-storage root.
 		///
@@ -498,7 +463,7 @@ pub mod ext {
 			old_value: *const u8,
 			old_value_len: u32,
 			new_value: *const u8,
-			new_value_len: u32
+			new_value_len: u32,
 		) -> u32;
 
 		/// Read a value from local storage.
@@ -526,7 +491,7 @@ pub mod ext {
 			url: *const u8,
 			url_len: u32,
 			meta: *const u8,
-			meta_len: u32
+			meta_len: u32,
 		) -> u32;
 
 		/// Add a header to the request.
@@ -540,7 +505,7 @@ pub mod ext {
 			name: *const u8,
 			name_len: u32,
 			value: *const u8,
-			value_len: u32
+			value_len: u32,
 		) -> u32;
 
 		/// Write a chunk of request body.
@@ -556,7 +521,7 @@ pub mod ext {
 			request_id: u32,
 			chunk: *const u8,
 			chunk_len: u32,
-			deadline: u64
+			deadline: u64,
 		) -> u32;
 
 		/// Block and wait for the responses for given requests.
@@ -570,7 +535,7 @@ pub mod ext {
 			ids: *const u32,
 			ids_len: u32,
 			statuses: *mut u32,
-			deadline: u64
+			deadline: u64,
 		);
 
 		/// Read all response headers.
@@ -583,7 +548,7 @@ pub mod ext {
 		/// - In case invalid `id` is passed it returns a pointer to parity-encoded empty vector.
 		fn ext_http_response_headers(
 			id: u32,
-			written_out: *mut u32
+			written_out: *mut u32,
 		) -> *mut u8;
 
 		/// Read a chunk of body response to given buffer.
@@ -605,7 +570,7 @@ pub mod ext {
 			id: u32,
 			buffer: *mut u8,
 			buffer_len: u32,
-			deadline: u64
+			deadline: u64,
 		) -> u32;
 	}
 }
@@ -777,21 +742,28 @@ impl StorageApi for () {
 		}
 	}
 
-	fn trie_root<
-		H: Hasher + ExternTrieCrypto,
-		I: IntoIterator<Item = (A, B)>,
-		A: AsRef<[u8]> + Ord,
-		B: AsRef<[u8]>,
-	>(_input: I) -> H::Out {
+
+	fn blake2_256_trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
 		unimplemented!()
 	}
 
-	fn ordered_trie_root<
-		H: Hasher + ExternTrieCrypto,
-		I: IntoIterator<Item = A>,
-		A: AsRef<[u8]>
-	>(values: I) -> H::Out {
-		H::ordered_trie_root(values)
+	fn blake2_256_ordered_trie_root(input: Vec<Vec<u8>>) -> H256 {
+		let mut values = Vec::new();
+		let mut lengths = Vec::new();
+		for v in input {
+			values.extend_from_slice(&v);
+			lengths.push((v.len() as u32).to_le());
+		}
+		let mut result: [u8; 32] = Default::default();
+		unsafe {
+			ext_blake2_256_enumerated_trie_root.get()(
+				values.as_ptr(),
+				lengths.as_ptr(),
+				lengths.len() as u32,
+				result.as_mut_ptr(),
+			);
+		}
+		result.into()
 	}
 }
 
@@ -802,10 +774,23 @@ impl OtherApi for () {
 		}
 	}
 
-	fn print<T: Printable + Sized>(value: T) {
-		value.print()
+	fn print_num(val: u64) {
+		unsafe {
+			ext_print_num.get()(val);
+		}
 	}
 
+	fn print_utf8(utf8: &[u8]) {
+		unsafe {
+			ext_print_utf8.get()(utf8.as_ptr(), utf8.len() as u32);
+		}
+	}
+
+	fn print_hex(data: &[u8]) {
+		unsafe {
+			ext_print_hex.get()(data.as_ptr(), data.len() as u32);
+		}
+	}
 }
 
 impl HashingApi for () {
@@ -876,18 +861,18 @@ impl CryptoApi for () {
 		ed25519::Public(res)
 	}
 
-	fn ed25519_sign<M: AsRef<[u8]>>(
+	fn ed25519_sign(
 		id: KeyTypeId,
 		pubkey: &ed25519::Public,
-		msg: &M,
+		msg: &[u8],
 	) -> Option<ed25519::Signature> {
 		let mut res = [0u8; 64];
 		let success = unsafe {
 			ext_ed25519_sign.get()(
 				id.0.as_ptr(),
 				pubkey.0.as_ptr(),
-				msg.as_ref().as_ptr(),
-				msg.as_ref().len() as u32,
+				msg.as_ptr(),
+				msg.len() as u32,
 				res.as_mut_ptr(),
 			) == 0
 		};
@@ -927,18 +912,18 @@ impl CryptoApi for () {
 		sr25519::Public(res)
 	}
 
-	fn sr25519_sign<M: AsRef<[u8]>>(
+	fn sr25519_sign(
 		id: KeyTypeId,
 		pubkey: &sr25519::Public,
-		msg: &M,
+		msg: &[u8],
 	) -> Option<sr25519::Signature> {
 		let mut res = [0u8; 64];
 		let success = unsafe {
 			ext_sr25519_sign.get()(
 				id.0.as_ptr(),
 				pubkey.0.as_ptr(),
-				msg.as_ref().as_ptr(),
-				msg.as_ref().len() as u32,
+				msg.as_ptr(),
+				msg.len() as u32,
 				res.as_mut_ptr(),
 			) == 0
 		};
@@ -1218,24 +1203,3 @@ unsafe fn from_raw_parts(ptr: *mut u8, len: u32) -> Option<Vec<u8>> {
 
 impl Api for () {}
 
-impl<'a> Printable for &'a [u8] {
-	fn print(&self) {
-		unsafe {
-			ext_print_hex.get()(self.as_ptr(), self.len() as u32);
-		}
-	}
-}
-
-impl<'a> Printable for &'a str {
-	fn print(&self) {
-		unsafe {
-			ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32);
-		}
-	}
-}
-
-impl Printable for u64 {
-	fn print(&self) {
-		unsafe { ext_print_num.get()(*self); }
-	}
-}
diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs
index f3d3eabfcb3822b48eec28c9f7cb838c250fa4ab..c3f47f29c4073c88cb3900c09cf1ee25363136c0 100644
--- a/core/sr-primitives/src/lib.rs
+++ b/core/sr-primitives/src/lib.rs
@@ -699,7 +699,7 @@ impl DispatchError {
 	}
 }
 
-impl runtime_io::Printable for DispatchError {
+impl traits::Printable for DispatchError {
 	fn print(&self) {
 		"DispatchError".print();
 		if let Some(module) = self.module {
@@ -895,6 +895,11 @@ impl traits::Extrinsic for OpaqueExtrinsic {
 	type SignaturePayload = ();
 }
 
+/// Print something that implements `Printable` from the runtime.
+pub fn print(print: impl traits::Printable) {
+	print.print();
+}
+
 #[cfg(test)]
 mod tests {
 	use super::DispatchError;
diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs
index 0479f9401c3f50c6fbc7554f17a0de2ef583f258..a2bc5bc6dc0d55cd4b8fc83361b79e6763176246 100644
--- a/core/sr-primitives/src/traits.rs
+++ b/core/sr-primitives/src/traits.rs
@@ -439,8 +439,9 @@ pub trait OffchainWorker<BlockNumber> {
 }
 
 /// Abstraction around hashing
-pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq {	// Stupid bug in the Rust compiler believes derived
-																	// traits must be fulfilled by all type parameters.
+// Stupid bug in the Rust compiler believes derived
+// traits must be fulfilled by all type parameters.
+pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq {
 	/// The hash type produced.
 	type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy
 		+ Default + Encode + Decode;
@@ -456,18 +457,11 @@ pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq {	// Stup
 		Encode::using_encoded(s, Self::hash)
 	}
 
-	/// Iterator-based version of `ordered_trie_root`.
-	fn ordered_trie_root<
-		I: IntoIterator<Item = A>,
-		A: AsRef<[u8]>
-	>(input: I) -> Self::Output;
+	/// The ordered Patricia tree root of the given `input`.
+	fn ordered_trie_root(input: Vec<Vec<u8>>) -> Self::Output;
 
-	/// The Patricia tree root of the given mapping as an iterator.
-	fn trie_root<
-		I: IntoIterator<Item = (A, B)>,
-		A: AsRef<[u8]> + Ord,
-		B: AsRef<[u8]>
-	>(input: I) -> Self::Output;
+	/// The Patricia tree root of the given mapping.
+	fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> Self::Output;
 
 	/// Acquire the global storage root.
 	fn storage_root() -> Self::Output;
@@ -487,22 +481,19 @@ impl Hash for BlakeTwo256 {
 	fn hash(s: &[u8]) -> Self::Output {
 		runtime_io::blake2_256(s).into()
 	}
-	fn trie_root<
-		I: IntoIterator<Item = (A, B)>,
-		A: AsRef<[u8]> + Ord,
-		B: AsRef<[u8]>
-	>(input: I) -> Self::Output {
-		runtime_io::trie_root::<Blake2Hasher, _, _, _>(input).into()
+
+	fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> Self::Output {
+		runtime_io::blake2_256_trie_root(input)
 	}
-	fn ordered_trie_root<
-		I: IntoIterator<Item = A>,
-		A: AsRef<[u8]>
-	>(input: I) -> Self::Output {
-		runtime_io::ordered_trie_root::<Blake2Hasher, _, _>(input).into()
+
+	fn ordered_trie_root(input: Vec<Vec<u8>>) -> Self::Output {
+		runtime_io::blake2_256_ordered_trie_root(input)
 	}
+
 	fn storage_root() -> Self::Output {
 		runtime_io::storage_root().into()
 	}
+
 	fn storage_changes_root(parent_hash: Self::Output) -> Option<Self::Output> {
 		runtime_io::storage_changes_root(parent_hash.into()).map(Into::into)
 	}
@@ -519,16 +510,20 @@ impl CheckEqual for primitives::H256 {
 	fn check_equal(&self, other: &Self) {
 		use primitives::hexdisplay::HexDisplay;
 		if self != other {
-			println!("Hash: given={}, expected={}", HexDisplay::from(self.as_fixed_bytes()), HexDisplay::from(other.as_fixed_bytes()));
+			println!(
+				"Hash: given={}, expected={}",
+				HexDisplay::from(self.as_fixed_bytes()),
+				HexDisplay::from(other.as_fixed_bytes()),
+			);
 		}
 	}
 
 	#[cfg(not(feature = "std"))]
 	fn check_equal(&self, other: &Self) {
 		if self != other {
-			runtime_io::print("Hash not equal");
-			runtime_io::print(self.as_bytes());
-			runtime_io::print(other.as_bytes());
+			"Hash not equal".print();
+			self.as_bytes().print();
+			other.as_bytes().print();
 		}
 	}
 }
@@ -544,9 +539,9 @@ impl<H: PartialEq + Eq + MaybeDebug> CheckEqual for super::generic::DigestItem<H
 	#[cfg(not(feature = "std"))]
 	fn check_equal(&self, other: &Self) {
 		if self != other {
-			runtime_io::print("DigestItem not equal");
-			runtime_io::print(&Encode::encode(self)[..]);
-			runtime_io::print(&Encode::encode(other)[..]);
+			"DigestItem not equal".print();
+			(&Encode::encode(self)[..]).print();
+			(&Encode::encode(other)[..]).print();
 		}
 	}
 }
@@ -1157,76 +1152,6 @@ impl<T: Encode + Decode + Default, Id: Encode + Decode + TypeId> AccountIdConver
 	}
 }
 
-#[cfg(test)]
-mod tests {
-	use super::AccountIdConversion;
-	use crate::codec::{Encode, Decode, Input};
-
-	#[derive(Encode, Decode, Default, PartialEq, Debug)]
-	struct U32Value(u32);
-	impl super::TypeId for U32Value {
-		const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
-	}
-	// cafef00d
-
-	#[derive(Encode, Decode, Default, PartialEq, Debug)]
-	struct U16Value(u16);
-	impl super::TypeId for U16Value {
-		const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
-	}
-	// f00dcafe
-
-	type AccountId = u64;
-
-	#[test]
-	fn into_account_should_work() {
-		let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef));
-		assert_eq!(r, 0x_deadbeef_cafef00d);
-	}
-
-	#[test]
-	fn try_from_account_should_work() {
-		let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
-		assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
-	}
-
-	#[test]
-	fn into_account_with_fill_should_work() {
-		let r: AccountId = U16Value::into_account(&U16Value(0xc0da));
-		assert_eq!(r, 0x_0000_c0da_f00dcafe);
-	}
-
-	#[test]
-	fn try_from_account_with_fill_should_work() {
-		let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
-		assert_eq!(r.unwrap(), U16Value(0xc0da));
-	}
-
-	#[test]
-	fn bad_try_from_account_should_fail() {
-		let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
-		assert!(r.is_none());
-		let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
-		assert!(r.is_none());
-	}
-
-	#[test]
-	fn trailing_zero_should_work() {
-		let mut t = super::TrailingZeroInput(&[1, 2, 3]);
-		assert_eq!(t.remaining_len(), Ok(None));
-		let mut buffer = [0u8; 2];
-		assert_eq!(t.read(&mut buffer), Ok(()));
-		assert_eq!(t.remaining_len(), Ok(None));
-		assert_eq!(buffer, [1, 2]);
-		assert_eq!(t.read(&mut buffer), Ok(()));
-		assert_eq!(t.remaining_len(), Ok(None));
-		assert_eq!(buffer, [3, 0]);
-		assert_eq!(t.read(&mut buffer), Ok(()));
-		assert_eq!(t.remaining_len(), Ok(None));
-		assert_eq!(buffer, [0, 0]);
-	}
-}
-
 /// Calls a given macro a number of times with a set of fixed params and an incrementing numeral.
 /// e.g.
 /// ```nocompile
@@ -1318,3 +1243,103 @@ macro_rules! impl_opaque_keys {
 		}
 	};
 }
+
+/// Trait for things which can be printed from the runtime.
+pub trait Printable {
+	/// Print the object.
+	fn print(&self);
+}
+
+impl Printable for u8 {
+	fn print(&self) {
+		u64::from(*self).print()
+	}
+}
+
+impl Printable for &[u8] {
+	fn print(&self) {
+		runtime_io::print_hex(self);
+	}
+}
+
+impl Printable for &str {
+	fn print(&self) {
+		runtime_io::print_utf8(self.as_bytes());
+	}
+}
+
+impl Printable for u64 {
+	fn print(&self) {
+		runtime_io::print_num(*self);
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::AccountIdConversion;
+	use crate::codec::{Encode, Decode, Input};
+
+	#[derive(Encode, Decode, Default, PartialEq, Debug)]
+	struct U32Value(u32);
+	impl super::TypeId for U32Value {
+		const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca];
+	}
+	// cafef00d
+
+	#[derive(Encode, Decode, Default, PartialEq, Debug)]
+	struct U16Value(u16);
+	impl super::TypeId for U16Value {
+		const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0];
+	}
+	// f00dcafe
+
+	type AccountId = u64;
+
+	#[test]
+	fn into_account_should_work() {
+		let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef));
+		assert_eq!(r, 0x_deadbeef_cafef00d);
+	}
+
+	#[test]
+	fn try_from_account_should_work() {
+		let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64);
+		assert_eq!(r.unwrap(), U32Value(0xdeadbeef));
+	}
+
+	#[test]
+	fn into_account_with_fill_should_work() {
+		let r: AccountId = U16Value::into_account(&U16Value(0xc0da));
+		assert_eq!(r, 0x_0000_c0da_f00dcafe);
+	}
+
+	#[test]
+	fn try_from_account_with_fill_should_work() {
+		let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64);
+		assert_eq!(r.unwrap(), U16Value(0xc0da));
+	}
+
+	#[test]
+	fn bad_try_from_account_should_fail() {
+		let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64);
+		assert!(r.is_none());
+		let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
+		assert!(r.is_none());
+	}
+
+	#[test]
+	fn trailing_zero_should_work() {
+		let mut t = super::TrailingZeroInput(&[1, 2, 3]);
+		assert_eq!(t.remaining_len(), Ok(None));
+		let mut buffer = [0u8; 2];
+		assert_eq!(t.read(&mut buffer), Ok(()));
+		assert_eq!(t.remaining_len(), Ok(None));
+		assert_eq!(buffer, [1, 2]);
+		assert_eq!(t.read(&mut buffer), Ok(()));
+		assert_eq!(t.remaining_len(), Ok(None));
+		assert_eq!(buffer, [3, 0]);
+		assert_eq!(t.read(&mut buffer), Ok(()));
+		assert_eq!(t.remaining_len(), Ok(None));
+		assert_eq!(buffer, [0, 0]);
+	}
+}
diff --git a/core/test-runtime/client/src/lib.rs b/core/test-runtime/client/src/lib.rs
index 229fcbdaf9072279ad7f3d848b896b8e65117824..d2cf704fdfb01481049cd5c3c160ad377e2017fd 100644
--- a/core/test-runtime/client/src/lib.rs
+++ b/core/test-runtime/client/src/lib.rs
@@ -122,12 +122,12 @@ impl generic_test_client::GenesisInit for GenesisParameters {
 
 		let child_roots = storage.1.iter().map(|(sk, child_map)| {
 			let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-				child_map.clone().into_iter()
+				child_map.clone().into_iter().collect()
 			);
 			(sk.clone(), state_root.encode())
 		});
 		let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-			storage.0.clone().into_iter().chain(child_roots)
+			storage.0.clone().into_iter().chain(child_roots).collect()
 		);
 		let block: runtime::Block = client::genesis::construct_genesis_block(state_root);
 		storage.0.extend(additional_storage_with_genesis(&block));
diff --git a/core/test-runtime/src/genesismap.rs b/core/test-runtime/src/genesismap.rs
index 34d7eecae0c80378642ea5145383fbe723c2ffd1..a3abf235ff1ca9132132046940d959d60ac95729 100644
--- a/core/test-runtime/src/genesismap.rs
+++ b/core/test-runtime/src/genesismap.rs
@@ -90,15 +90,14 @@ pub fn insert_genesis_block(
 		HashMap<Vec<u8>, HashMap<Vec<u8>, Vec<u8>>>,
 	)
 ) -> primitives::hash::H256 {
-
 	let child_roots = storage.1.iter().map(|(sk, child_map)| {
 		let state_root = <<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-			child_map.clone().into_iter()
+			child_map.clone().into_iter().collect(),
 		);
 		(sk.clone(), state_root.encode())
 	});
 	let state_root = <<<crate::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-		storage.0.clone().into_iter().chain(child_roots)
+		storage.0.clone().into_iter().chain(child_roots).collect()
 	);
 	let block: crate::Block = substrate_client::genesis::construct_genesis_block(state_root);
 	let genesis_hash = block.header.hash();
diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs
index 88a246b094741a18e07df0a3aabcca1d2ed749ce..c3b05b53d4ef0a9697237ffd4df6e93c1d454819 100644
--- a/core/test-runtime/src/lib.rs
+++ b/core/test-runtime/src/lib.rs
@@ -188,7 +188,7 @@ pub type Header = sr_primitives::generic::Header<BlockNumber, BlakeTwo256>;
 
 /// Run whatever tests we have.
 pub fn run_tests(mut input: &[u8]) -> Vec<u8> {
-	use runtime_io::print;
+	use sr_primitives::print;
 
 	print("run_tests...");
 	let block = Block::decode(&mut input).unwrap();
diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs
index f1288f8b2806f980e289531f770fca57e4971d95..e61e72f3a0e85cb1fa3bdbf343757ddee566c87f 100644
--- a/core/test-runtime/src/system.rs
+++ b/core/test-runtime/src/system.rs
@@ -18,7 +18,7 @@
 //! and depositing logs.
 
 use rstd::prelude::*;
-use runtime_io::{storage_root, ordered_trie_root, storage_changes_root, twox_128, blake2_256};
+use runtime_io::{storage_root, storage_changes_root, twox_128, blake2_256};
 use runtime_support::storage::{self, StorageValue, StorageMap};
 use runtime_support::storage_items;
 use sr_primitives::{
@@ -29,7 +29,7 @@ use codec::{KeyedVec, Encode};
 use crate::{
 	AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId
 };
-use primitives::{Blake2Hasher, storage::well_known_keys};
+use primitives::storage::well_known_keys;
 
 const NONCE_OF: &[u8] = b"nonce:";
 const BALANCE_OF: &[u8] = b"balance:";
@@ -101,8 +101,7 @@ fn execute_block_with_state_root_handler(
 
 	// check transaction trie root represents the transactions.
 	let txs = block.extrinsics.iter().map(Encode::encode).collect::<Vec<_>>();
-	let txs = txs.iter().map(Vec::as_slice).collect::<Vec<_>>();
-	let txs_root = ordered_trie_root::<Blake2Hasher, _, _>(&txs).into();
+	let txs_root = BlakeTwo256::ordered_trie_root(txs);
 	info_expect_equal_hash(&txs_root, &header.extrinsics_root);
 	if let Mode::Overwrite = mode {
 		header.extrinsics_root = txs_root;
@@ -211,8 +210,7 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyResult {
 pub fn finalize_block() -> Header {
 	let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap();
 	let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect();
-	let txs = txs.iter().map(Vec::as_slice).collect::<Vec<_>>();
-	let extrinsics_root = ordered_trie_root::<Blake2Hasher, _, _>(&txs).into();
+	let extrinsics_root = BlakeTwo256::ordered_trie_root(txs).into();
 	let number = <Number>::take().expect("Number is set by `initialize_block`");
 	let parent_hash = <ParentHash>::take();
 	let mut digest = <StorageDigest>::take().expect("StorageDigest is set by `initialize_block`");
@@ -311,9 +309,9 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
 #[cfg(not(feature = "std"))]
 fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
 	if given != expected {
-		runtime_io::print("Hash not equal");
-		runtime_io::print(given.as_bytes());
-		runtime_io::print(expected.as_bytes());
+		sr_primitives::print("Hash not equal");
+		sr_primitives::print(given.as_bytes());
+		sr_primitives::print(expected.as_bytes());
 	}
 }
 
diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs
index 3cc85731d85c8fa8c6f941435c9331192cf890a6..eab05bab28af016ed9d9c092d832f97ad69b6122 100644
--- a/core/trie/src/lib.rs
+++ b/core/trie/src/lib.rs
@@ -33,15 +33,15 @@ pub use trie_stream::TrieStream;
 /// The Substrate format implementation of `NodeCodec`.
 pub use node_codec::NodeCodec;
 /// Various re-exports from the `trie-db` crate.
-pub use trie_db::{Trie, TrieMut, DBValue, Recorder, CError,
-	Query, TrieLayout, TrieConfiguration, nibble_ops};
+pub use trie_db::{
+	Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops,
+};
 /// Various re-exports from the `memory-db` crate.
 pub use memory_db::KeyFunction;
 pub use memory_db::prefixed_key;
 /// Various re-exports from the `hash-db` crate.
 pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
 
-
 #[derive(Default)]
 /// substrate trie layout
 pub struct Layout<H>(rstd::marker::PhantomData<H>);
diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs
index 41d7b834b05b10ae6043e1fd04741578d7eb2143..e399b5c02ea4d7356403d6733352acedc26bcbbe 100644
--- a/node/executor/src/lib.rs
+++ b/node/executor/src/lib.rs
@@ -49,7 +49,7 @@ mod tests {
 		traits::{CodeExecutor, Externalities},
 	};
 	use sr_primitives::{
-		traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyOutcome, ApplyResult,
+		traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyResult,
 		transaction_validity::InvalidTransaction, weights::{WeightMultiplier, GetDispatchInfo},
 	};
 	use contracts::ContractAddressFor;
diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs
index bc2d6201b7c3d551edae27eb9386197b0b2a4701..13140ad44cdddfecc04e7fa0114f7314e5ef85c0 100644
--- a/node/runtime/src/lib.rs
+++ b/node/runtime/src/lib.rs
@@ -82,8 +82,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	// and set impl_version to equal spec_version. If only runtime
 	// implementation changes and behavior does not, then leave spec_version as
 	// is and increment impl_version.
-	spec_version: 157,
-	impl_version: 159,
+	spec_version: 158,
+	impl_version: 158,
 	apis: RUNTIME_API_VERSIONS,
 };
 
diff --git a/srml/contracts/src/wasm/runtime.rs b/srml/contracts/src/wasm/runtime.rs
index 4baece3d9186a4d0642213f7768313a6b00022d8..573132cf31617eb81830ca98a125a9249f9fa238 100644
--- a/srml/contracts/src/wasm/runtime.rs
+++ b/srml/contracts/src/wasm/runtime.rs
@@ -822,7 +822,7 @@ define_env!(Env, <E: Ext>,
 	ext_println(ctx, str_ptr: u32, str_len: u32) => {
 		let data = read_sandbox_memory(ctx, str_ptr, str_len)?;
 		if let Ok(utf8) = core::str::from_utf8(&data) {
-			runtime_io::print(utf8);
+			sr_primitives::print(utf8);
 		}
 		Ok(())
 	},
diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs
index 2b74c44598b2a5d70ad2889f0dc14360df5350f8..585ffde14d491c934b822234e835cdf6fbc4d335 100644
--- a/srml/democracy/src/lib.rs
+++ b/srml/democracy/src/lib.rs
@@ -562,7 +562,7 @@ decl_module! {
 
 		fn on_initialize(n: T::BlockNumber) {
 			if let Err(e) = Self::end_block(n) {
-				runtime_io::print(e);
+				sr_primitives::print(e);
 			}
 		}
 
diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs
index 2ebdbade0c283d295b0f869db4c04ac4b0cce261..1cd3258cf7c1908fe785055d31bcd43f1d191a9e 100644
--- a/srml/elections/src/lib.rs
+++ b/srml/elections/src/lib.rs
@@ -24,9 +24,9 @@
 #![recursion_limit="128"]
 
 use rstd::prelude::*;
-use sr_primitives::traits::{Zero, One, StaticLookup, Bounded, Saturating};
-use sr_primitives::weights::SimpleDispatchInfo;
-use runtime_io::print;
+use sr_primitives::{
+	print, traits::{Zero, One, StaticLookup, Bounded, Saturating}, weights::SimpleDispatchInfo,
+};
 use support::{
 	StorageValue, StorageMap,
 	dispatch::Result, decl_storage, decl_event, ensure, decl_module,
diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs
index cfa3636e4d03aa3094d25543c77623e93140b7cc..ff797557f59936d0b92eb3bf0b8abc6ea324ee83 100644
--- a/srml/example/src/lib.rs
+++ b/srml/example/src/lib.rs
@@ -579,7 +579,7 @@ impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T> {
 		// check for `set_dummy`
 		match call {
 			Call::set_dummy(..) => {
-				runtime_io::print("set_dummy was received.");
+				sr_primitives::print("set_dummy was received.");
 
 				let mut valid_tx = ValidTransaction::default();
 				valid_tx.priority = Bounded::max_value();
diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs
index ff0fc32e9b690beddfab265a1d15f332b0485f03..ad9cb7bf80742fa00f07384dfd3ca5c3670264b7 100644
--- a/srml/executive/src/lib.rs
+++ b/srml/executive/src/lib.rs
@@ -217,7 +217,7 @@ where
 		let l = uxt.encode().len();
 		match Self::apply_extrinsic_with_len(uxt, l, None) {
 			Ok(Ok(())) => (),
-			Ok(Err(e)) => runtime_io::print(e),
+			Ok(Err(e)) => sr_primitives::print(e),
 			Err(e) => { let err: &'static str = e.into(); panic!(err) },
 		}
 	}
diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs
index 5daa39299d2197f6d7c25e217081a4398f1114ce..7da88836f3ec915090516692e97dc11519c764d1 100644
--- a/srml/im-online/src/lib.rs
+++ b/srml/im-online/src/lib.rs
@@ -75,9 +75,8 @@ use codec::{Encode, Decode};
 use primitives::offchain::{OpaqueNetworkState, StorageKind};
 use rstd::prelude::*;
 use session::historical::IdentificationTuple;
-use runtime_io::Printable;
 use sr_primitives::{
-	traits::{Convert, Member}, Perbill,
+	traits::{Convert, Member, Printable}, Perbill,
 	transaction_validity::{
 		TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransaction,
 	},
diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs
index 7d80851719badab6343e2e6cfeebb6f12d3a427f..2a733ccb2e7f78e1680ecb98798963395fec6e9d 100644
--- a/srml/sudo/src/lib.rs
+++ b/srml/sudo/src/lib.rs
@@ -126,7 +126,7 @@ decl_module! {
 				Ok(_) => true,
 				Err(e) => {
 					let e: DispatchError = e.into();
-					runtime_io::print(e);
+					sr_primitives::print(e);
 					false
 				}
 			};
@@ -176,7 +176,7 @@ decl_module! {
 				Ok(_) => true,
 				Err(e) => {
 					let e: DispatchError = e.into();
-					runtime_io::print(e);
+					sr_primitives::print(e);
 					false
 				}
 			};
diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs
index 13fb69990ef6132a3c56261b075317c6b3688225..6935b4508d34ff0e96063f0bcdd1a051678feeeb 100644
--- a/srml/support/src/lib.rs
+++ b/srml/support/src/lib.rs
@@ -67,8 +67,8 @@ pub use self::storage::{StorageValue, StorageMap, StorageLinkedMap, StorageDoubl
 pub use self::hashable::Hashable;
 pub use self::dispatch::{Parameter, Callable, IsSubType};
 pub use self::double_map::StorageDoubleMapWithHasher;
-pub use runtime_io::{print, storage_root, Printable};
-pub use sr_primitives::{self, ConsensusEngineId};
+pub use runtime_io::storage_root;
+pub use sr_primitives::{self, ConsensusEngineId, print, traits::Printable};
 
 /// Macro for easily creating a new implementation of the `Get` trait. Use similarly to
 /// how you would declare a `const`:
@@ -270,7 +270,8 @@ pub use serde::{Serialize, Deserialize};
 mod tests {
 	use super::*;
 	use codec::Codec;
-	use runtime_io::{with_externalities, Blake2Hasher};
+	use runtime_io::with_externalities;
+	use primitives::Blake2Hasher;
 	pub use srml_metadata::{
 		DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType,
 		StorageEntryModifier, DefaultByte, DefaultByteGetter, StorageHasher
diff --git a/srml/support/test/tests/final_keys.rs b/srml/support/test/tests/final_keys.rs
index 73de126050f8b22abf0a6770fd98d5163592e754..dfa363b5822c52777855ffcea00bf43d47c78ae8 100644
--- a/srml/support/test/tests/final_keys.rs
+++ b/srml/support/test/tests/final_keys.rs
@@ -14,7 +14,8 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
-use runtime_io::{with_externalities, Blake2Hasher};
+use runtime_io::with_externalities;
+use primitives::Blake2Hasher;
 use support::{StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap};
 use support::storage::unhashed;
 use codec::{Encode, Decode};
diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs
index 3370c0d201d572246fed4a58c949fd5555d58a58..0662689379cce58670261167de3e6213324fae96 100644
--- a/srml/support/test/tests/instance.rs
+++ b/srml/support/test/tests/instance.rs
@@ -15,7 +15,7 @@
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 #![recursion_limit="128"]
 
-use runtime_io::{with_externalities, Blake2Hasher};
+use runtime_io::with_externalities;
 use support::{
 	Parameter, traits::Get, parameter_types,
 	sr_primitives::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}},
@@ -28,7 +28,7 @@ use support::{
 use inherents::{
 	ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError
 };
-use primitives::{H256, sr25519};
+use primitives::{H256, sr25519, Blake2Hasher};
 
 mod system;
 
diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs
index b050e80c48b7da93311b807c072f1292b3e638a0..b24e52f45720bbd7c43d01dc50e12653cf2a3191 100644
--- a/srml/system/benches/bench.rs
+++ b/srml/system/benches/bench.rs
@@ -17,8 +17,8 @@
 use criterion::{Criterion, criterion_group, criterion_main, black_box};
 use srml_system as system;
 use support::{decl_module, decl_event, impl_outer_origin, impl_outer_event};
-use runtime_io::{with_externalities, Blake2Hasher};
-use primitives::H256;
+use runtime_io::with_externalities;
+use primitives::{H256, Blake2Hasher};
 use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header};
 
 mod module {
diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs
index 02a70028060f3d5506a22b7ae59c76e51a39f512..9bacbd688764303feaa35249776b66390865bbc7 100644
--- a/srml/system/src/lib.rs
+++ b/srml/system/src/lib.rs
@@ -118,10 +118,10 @@ use safe_mix::TripletMix;
 use codec::{Encode, Decode};
 
 #[cfg(any(feature = "std", test))]
-use runtime_io::{TestExternalities, Blake2Hasher};
+use runtime_io::TestExternalities;
 
 #[cfg(any(feature = "std", test))]
-use primitives::ChangesTrieConfiguration;
+use primitives::{ChangesTrieConfiguration, Blake2Hasher};
 
 pub mod offchain;
 
@@ -151,8 +151,7 @@ pub fn extrinsics_root<H: Hash, E: codec::Encode>(extrinsics: &[E]) -> H::Output
 
 /// Compute the trie root of a list of extrinsics.
 pub fn extrinsics_data_root<H: Hash>(xts: Vec<Vec<u8>>) -> H::Output {
-	let xts = xts.iter().map(Vec::as_slice).collect::<Vec<_>>();
-	H::ordered_trie_root(&xts)
+	H::ordered_trie_root(xts)
 }
 
 pub trait Trait: 'static + Eq + Clone {