diff --git a/substrate/core/state-machine/src/changes_trie/build.rs b/substrate/core/state-machine/src/changes_trie/build.rs
index 96d2278cc2a76e93e40134948d561ba57946c131..d32d28906fb48eb0f37345df3c32877800b1d66e 100644
--- a/substrate/core/state-machine/src/changes_trie/build.rs
+++ b/substrate/core/state-machine/src/changes_trie/build.rs
@@ -16,7 +16,8 @@
 
 //! Structures and functions required to build changes trie for given block.
 
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::BTreeMap;
+use std::collections::btree_map::Entry;
 use parity_codec::Decode;
 use hash_db::Hasher;
 use num_traits::One;
@@ -31,75 +32,89 @@ use crate::changes_trie::{AnchorBlockId, Configuration, Storage, BlockNumber};
 ///
 /// Returns Err if storage error has occurred OR if storage haven't returned
 /// required data.
-/// Returns Ok(None) data required to prepare input pairs is not collected
-/// or storage is not provided.
 pub fn prepare_input<'a, B, S, H, Number>(
-	backend: &B,
+	backend: &'a B,
 	storage: &'a S,
 	config: &'a Configuration,
-	changes: &OverlayedChanges,
+	changes: &'a OverlayedChanges,
 	parent: &'a AnchorBlockId<H::Out, Number>,
-) -> Result<Option<Vec<InputPair<Number>>>, String>
+) -> Result<impl Iterator<Item=InputPair<Number>> + 'a, String>
 	where
 		B: Backend<H>,
 		S: Storage<H, Number>,
-		H: Hasher,
+		H: Hasher + 'a,
 		Number: BlockNumber,
 {
-	let mut input = Vec::new();
-	input.extend(prepare_extrinsics_input(
+	let number = parent.number.clone() + One::one();
+	let extrinsics_input = prepare_extrinsics_input(
 		backend,
-		parent.number.clone() + 1.into(),
-		changes)?);
-	input.extend(prepare_digest_input::<_, H, Number>(
+		&number,
+		changes)?;
+	let digest_input = prepare_digest_input::<_, H, Number>(
 		parent,
 		config,
-		storage)?);
-
-	Ok(Some(input))
+		number,
+		storage)?;
+	Ok(extrinsics_input.chain(digest_input))
 }
 
 /// Prepare ExtrinsicIndex input pairs.
-fn prepare_extrinsics_input<B, H, Number>(
-	backend: &B,
-	block: Number,
-	changes: &OverlayedChanges,
-) -> Result<impl Iterator<Item=InputPair<Number>>, String>
+fn prepare_extrinsics_input<'a, B, H, Number>(
+	backend: &'a B,
+	block: &Number,
+	changes: &'a OverlayedChanges,
+) -> Result<impl Iterator<Item=InputPair<Number>> + 'a, String>
 	where
 		B: Backend<H>,
 		H: Hasher,
 		Number: BlockNumber,
 {
-	let mut extrinsic_map = BTreeMap::<Vec<u8>, BTreeSet<u32>>::new();
-	for (key, val) in changes.prospective.top.iter().chain(changes.committed.top.iter()) {
-		let extrinsics = match val.extrinsics {
-			Some(ref extrinsics) => extrinsics,
-			None => continue,
-		};
+	changes.committed.top.iter()
+		.chain(changes.prospective.top.iter())
+		.filter(|( _, v)| v.extrinsics.is_some())
+		.try_fold(BTreeMap::new(), |mut map: BTreeMap<&[u8], (ExtrinsicIndex<Number>, Vec<u32>)>, (k, v)| {
+			match map.entry(k) {
+				Entry::Vacant(entry) => {
+					// ignore temporary values (values that have null value at the end of operation
+					// AND are not in storage at the beginning of operation
+					if !changes.storage(k).map(|v| v.is_some()).unwrap_or_default() {
+						if !backend.exists_storage(k).map_err(|e| format!("{}", e))? {
+							return Ok(map);
+						}
+					}
 
-		// ignore values that have null value at the end of operation AND are not in storage
-		// at the beginning of operation
-		if !changes.storage(key).map(|v| v.is_some()).unwrap_or_default() {
-			if !backend.exists_storage(key).map_err(|e| format!("{}", e))? {
-				continue;
+					let extrinsics = v.extrinsics.as_ref()
+						.expect("filtered by filter() call above; qed")
+						.iter().cloned().collect();
+					entry.insert((ExtrinsicIndex {
+						block: block.clone(),
+						key: k.to_vec(),
+					}, extrinsics));
+				},
+				Entry::Occupied(mut entry) => {
+					// we do not need to check for temporary values here, because entry is Occupied
+					// AND we are checking it before insertion
+					let extrinsics = &mut entry.get_mut().1;
+					extrinsics.extend(
+						v.extrinsics.as_ref()
+							.expect("filtered by filter() call above; qed")
+							.iter()
+							.cloned()
+					);
+					extrinsics.sort_unstable();
+				},
 			}
-		}
-
-		extrinsic_map.entry(key.clone()).or_default()
-			.extend(extrinsics.iter().cloned());
-	}
 
-	Ok(extrinsic_map.into_iter()
-		.map(move |(key, extrinsics)| InputPair::ExtrinsicIndex(ExtrinsicIndex {
-			block: block.clone(),
-			key,
-		}, extrinsics.iter().cloned().collect())))
+			Ok(map)
+		})
+		.map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::ExtrinsicIndex(k, v)))
 }
 
 /// Prepare DigestIndex input pairs.
 fn prepare_digest_input<'a, S, H, Number>(
 	parent: &'a AnchorBlockId<H::Out, Number>,
 	config: &Configuration,
+	block: Number,
 	storage: &'a S
 ) -> Result<impl Iterator<Item=InputPair<Number>> + 'a, String>
 	where
@@ -108,35 +123,52 @@ fn prepare_digest_input<'a, S, H, Number>(
 		H::Out: 'a,
 		Number: BlockNumber,
 {
-	let mut digest_map = BTreeMap::<Vec<u8>, BTreeSet<Number>>::new();
-	for digest_build_block in digest_build_iterator(config, parent.number.clone() + One::one()) {
-		let trie_root = storage.root(parent, digest_build_block.clone())?;
-		let trie_root = trie_root.ok_or_else(|| format!("No changes trie root for block {}", digest_build_block.clone()))?;
-		let trie_storage = TrieBackendEssence::<_, H>::new(
-			crate::changes_trie::TrieBackendStorageAdapter(storage),
-			trie_root,
-		);
+	digest_build_iterator(config, block.clone())
+		.try_fold(BTreeMap::new(), move |mut map, digest_build_block| {
+			let trie_root = storage.root(parent, digest_build_block.clone())?;
+			let trie_root = trie_root.ok_or_else(|| format!("No changes trie root for block {}", digest_build_block.clone()))?;
+			let trie_storage = TrieBackendEssence::<_, H>::new(
+				crate::changes_trie::TrieBackendStorageAdapter(storage),
+				trie_root,
+			);
 
-		let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone());
-		trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key|
-			if let Some(InputKey::ExtrinsicIndex::<Number>(trie_key)) = Decode::decode(&mut &key[..]) {
-				digest_map.entry(trie_key.key).or_default()
-					.insert(digest_build_block.clone());
-			});
+			let mut insert_to_map = |key: Vec<u8>| {
+				match map.entry(key.clone()) {
+					Entry::Vacant(entry) => {
+						entry.insert((DigestIndex {
+							block: block.clone(),
+							key,
+						}, vec![digest_build_block.clone()]));
+					},
+					Entry::Occupied(mut entry) => {
+						// DigestIndexValue must be sorted. Here we are relying on the fact that digest_build_iterator()
+						// returns blocks in ascending order => we only need to check for duplicates
+						//
+						// is_dup_block could be true when key has been changed in both digest block
+						// AND other blocks that it covers
+						let is_dup_block = entry.get().1.last() == Some(&digest_build_block);
+						if !is_dup_block {
+							entry.get_mut().1.push(digest_build_block.clone());
+						}
+					},
+				}
+			};
 
-		let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone());
-		trie_storage.for_keys_with_prefix(&digest_prefix, |key|
-			if let Some(InputKey::DigestIndex::<Number>(trie_key)) = Decode::decode(&mut &key[..]) {
-				digest_map.entry(trie_key.key).or_default()
-					.insert(digest_build_block.clone());
-			});
-	}
+			let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone());
+			trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key|
+				if let Some(InputKey::ExtrinsicIndex::<Number>(trie_key)) = Decode::decode(&mut &key[..]) {
+					insert_to_map(trie_key.key);
+				});
 
-	Ok(digest_map.into_iter()
-		.map(move |(key, set)| InputPair::DigestIndex(DigestIndex {
-			block: parent.number.clone() + One::one(),
-			key
-		}, set.into_iter().collect())))
+			let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone());
+			trie_storage.for_keys_with_prefix(&digest_prefix, |key|
+				if let Some(InputKey::DigestIndex::<Number>(trie_key)) = Decode::decode(&mut &key[..]) {
+					insert_to_map(trie_key.key);
+				});
+
+			Ok(map)
+		})
+		.map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)))
 }
 
 #[cfg(test)]
@@ -227,32 +259,34 @@ mod test {
 	fn build_changes_trie_nodes_on_non_digest_block() {
 		let (backend, storage, changes) = prepare_for_build();
 		let config = changes.changes_trie_config.as_ref().unwrap();
+		let parent = AnchorBlockId { hash: Default::default(), number: 4 };
 		let changes_trie_nodes = prepare_input(
 			&backend,
 			&storage,
 			config,
 			&changes,
-			&AnchorBlockId { hash: Default::default(), number: 4 },
+			&parent,
 		).unwrap();
-		assert_eq!(changes_trie_nodes, Some(vec![
+		assert_eq!(changes_trie_nodes.collect::<Vec<InputPair<u64>>>(), vec![
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 5, key: vec![100] }, vec![0, 2, 3]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 5, key: vec![101] }, vec![1]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 5, key: vec![103] }, vec![0, 1]),
-		]));
+		]);
 	}
 
 	#[test]
 	fn build_changes_trie_nodes_on_digest_block_l1() {
 		let (backend, storage, changes) = prepare_for_build();
 		let config = changes.changes_trie_config.as_ref().unwrap();
+		let parent = AnchorBlockId { hash: Default::default(), number: 3 };
 		let changes_trie_nodes = prepare_input(
 			&backend,
 			&storage,
 			config,
 			&changes,
-			&AnchorBlockId { hash: Default::default(), number: 3 },
+			&parent,
 		).unwrap();
-		assert_eq!(changes_trie_nodes, Some(vec![
+		assert_eq!(changes_trie_nodes.collect::<Vec<InputPair<u64>>>(), vec![
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![100] }, vec![0, 2, 3]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![101] }, vec![1]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![103] }, vec![0, 1]),
@@ -261,21 +295,22 @@ mod test {
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![101] }, vec![1]),
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![102] }, vec![2]),
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![105] }, vec![1, 3]),
-		]));
+		]);
 	}
 
 	#[test]
 	fn build_changes_trie_nodes_on_digest_block_l2() {
 		let (backend, storage, changes) = prepare_for_build();
 		let config = changes.changes_trie_config.as_ref().unwrap();
+		let parent = AnchorBlockId { hash: Default::default(), number: 15 };
 		let changes_trie_nodes = prepare_input(
 			&backend,
 			&storage,
 			config,
 			&changes,
-			&AnchorBlockId { hash: Default::default(), number: 15 },
+			&parent,
 		).unwrap();
-		assert_eq!(changes_trie_nodes, Some(vec![
+		assert_eq!(changes_trie_nodes.collect::<Vec<InputPair<u64>>>(), vec![
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![100] }, vec![0, 2, 3]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![101] }, vec![1]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![103] }, vec![0, 1]),
@@ -285,7 +320,7 @@ mod test {
 			InputPair::DigestIndex(DigestIndex { block: 16, key: vec![102] }, vec![4]),
 			InputPair::DigestIndex(DigestIndex { block: 16, key: vec![103] }, vec![4]),
 			InputPair::DigestIndex(DigestIndex { block: 16, key: vec![105] }, vec![4, 8]),
-		]));
+		]);
 	}
 
 	#[test]
@@ -299,14 +334,15 @@ mod test {
 		});
 
 		let config = changes.changes_trie_config.as_ref().unwrap();
+		let parent = AnchorBlockId { hash: Default::default(), number: 3 };
 		let changes_trie_nodes = prepare_input(
 			&backend,
 			&storage,
 			config,
 			&changes,
-			&AnchorBlockId { hash: Default::default(), number: 3 },
+			&parent,
 		).unwrap();
-		assert_eq!(changes_trie_nodes, Some(vec![
+		assert_eq!(changes_trie_nodes.collect::<Vec<InputPair<u64>>>(), vec![
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![100] }, vec![0, 2, 3]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![101] }, vec![1]),
 			InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 4, key: vec![103] }, vec![0, 1]),
@@ -315,6 +351,6 @@ mod test {
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![101] }, vec![1]),
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![102] }, vec![2]),
 			InputPair::DigestIndex(DigestIndex { block: 4, key: vec![105] }, vec![1, 3]),
-		]));
+		]);
 	}
 }
diff --git a/substrate/core/state-machine/src/changes_trie/build_iterator.rs b/substrate/core/state-machine/src/changes_trie/build_iterator.rs
index b0c7180d26bdff223ce1baaa0ff6488287754421..f4fff28765667685e1d35b7c06f2aa894c2100d7 100644
--- a/substrate/core/state-machine/src/changes_trie/build_iterator.rs
+++ b/substrate/core/state-machine/src/changes_trie/build_iterator.rs
@@ -20,7 +20,8 @@
 use crate::changes_trie::{Configuration, BlockNumber};
 
 /// Returns iterator of OTHER blocks that are required for inclusion into
-/// changes trie of given block.
+/// changes trie of given block. Blocks are guaranteed to be returned in
+/// ascending order.
 pub fn digest_build_iterator<Number: BlockNumber>(
 	config: &Configuration,
 	block: Number,
@@ -47,6 +48,8 @@ pub struct DigestBuildIterator<Number: BlockNumber> {
 	max_step: u32,
 	/// Step of current blocks range.
 	current_step: u32,
+	/// Reverse step of current blocks range.
+	current_step_reverse: u32,
 	/// Current blocks range.
 	current_range: Option<BlocksRange<Number>>,
 }
@@ -58,7 +61,8 @@ impl<Number: BlockNumber> DigestBuildIterator<Number> {
 			block,
 			digest_interval,
 			max_step,
-			current_step: 0,
+			current_step: max_step,
+			current_step_reverse: 0,
 			current_range: None,
 		}
 	}
@@ -81,18 +85,27 @@ impl<Number: BlockNumber> Iterator for DigestBuildIterator<Number> {
 		// DigestBuildIterator is created only by internal function that is checking
 		// that all multiplications/subtractions are safe within max_step limit
 
-		let next_step = if self.current_step == 0 { 1 } else { self.current_step * self.digest_interval };
-		if next_step > self.max_step {
+		let next_step_reverse = if self.current_step_reverse == 0 {
+			1
+		} else {
+			self.current_step_reverse * self.digest_interval
+		};
+		if next_step_reverse > self.max_step {
 			return None;
 		}
 
-		self.current_step = next_step;
+		self.current_step_reverse = next_step_reverse;
 		self.current_range = Some(BlocksRange::new(
 			self.block.clone() - (self.current_step * self.digest_interval - self.current_step).into(),
 			self.block.clone(),
 			self.current_step.into(),
 		));
 
+		self.current_step = self.current_step / self.digest_interval;
+		if self.current_step == 0 {
+			self.current_step = 1;
+		}
+
 		Some(self.current_range.as_mut()
 			.expect("assigned one line above; qed")
 			.next()
@@ -203,18 +216,18 @@ mod tests {
 	fn digest_iterator_returns_level1_and_level2_blocks() {
 		assert_eq!(digest_build_iterator_blocks(16, 2, 256),
 			vec![
-				// level2 is a level1 digest of 16-1 previous blocks:
-				241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
 				// level2 points to previous 16-1 level1 digests:
 				16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240,
+				// level2 is a level1 digest of 16-1 previous blocks:
+				241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
 			],
 		);
 		assert_eq!(digest_build_iterator_blocks(16, 2, 4096),
 			vec![
-				// level2 is a level1 digest of 16-1 previous blocks:
-				4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095,
 				// level2 points to previous 16-1 level1 digests:
 				3856, 3872, 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000, 4016, 4032, 4048, 4064, 4080,
+				// level2 is a level1 digest of 16-1 previous blocks:
+				4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095,
 			],
 		);
 	}
@@ -223,12 +236,12 @@ mod tests {
 	fn digest_iterator_returns_level1_and_level2_and_level3_blocks() {
 		assert_eq!(digest_build_iterator_blocks(16, 3, 4096),
 			vec![
-				// level3 is a level1 digest of 16-1 previous blocks:
-				4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095,
-				// level3 points to previous 16-1 level1 digests:
-				3856, 3872, 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000, 4016, 4032, 4048, 4064, 4080,
 				// level3 points to previous 16-1 level2 digests:
 				256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840,
+				// level3 points to previous 16-1 level1 digests:
+				3856, 3872, 3888, 3904, 3920, 3936, 3952, 3968, 3984, 4000, 4016, 4032, 4048, 4064, 4080,
+				// level3 is a level1 digest of 16-1 previous blocks:
+				4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095,
 			],
 		);
 	}
diff --git a/substrate/core/state-machine/src/changes_trie/mod.rs b/substrate/core/state-machine/src/changes_trie/mod.rs
index 7dc95fb5a7ba7350e930d93366ceb5cd1d695cfb..ab36eb6423b2e4fd865341be77ee7372c67905da 100644
--- a/substrate/core/state-machine/src/changes_trie/mod.rs
+++ b/substrate/core/state-machine/src/changes_trie/mod.rs
@@ -53,7 +53,7 @@ use parity_codec::{Decode, Encode};
 use primitives;
 use crate::changes_trie::build::prepare_input;
 use crate::overlayed_changes::OverlayedChanges;
-use trie::{DBValue, trie_root};
+use trie::{MemoryDB, TrieDBMut, TrieMut, DBValue};
 
 /// Changes that are made outside of extrinsics are marked with this index;
 pub const NO_EXTRINSIC_INDEX: u32 = 0xffffffff;
@@ -128,13 +128,13 @@ pub type Configuration = primitives::ChangesTrieConfiguration;
 /// Compute the changes trie root and transaction for given block.
 /// Returns Err(()) if unknown `parent_hash` has been passed.
 /// Returns Ok(None) if there's no data to perform computation.
-/// Panics if background storage returns an error.
-pub fn compute_changes_trie_root<'a, B: Backend<H>, S: Storage<H, Number>, H: Hasher, Number: BlockNumber>(
+/// Panics if background storage returns an error OR if insert to MemoryDB fails.
+pub fn build_changes_trie<'a, B: Backend<H>, S: Storage<H, Number>, H: Hasher, Number: BlockNumber>(
 	backend: &B,
 	storage: Option<&'a S>,
 	changes: &OverlayedChanges,
 	parent_hash: H::Out,
-) -> Result<Option<(H::Out, Vec<(Vec<u8>, Vec<u8>)>)>, ()>
+) -> Result<Option<(MemoryDB<H>, H::Out)>, ()>
 	where
 		H::Out: Ord + 'static,
 {
@@ -148,16 +148,16 @@ pub fn compute_changes_trie_root<'a, B: Backend<H>, S: Storage<H, Number>, H: Ha
 
 	// storage errors are considered fatal (similar to situations when runtime fetches values from storage)
 	let input_pairs = prepare_input::<B, S, H, Number>(backend, storage, config, changes, &parent)
-		.expect("storage is not allowed to fail within runtime");
-	match input_pairs {
-		Some(input_pairs) => {
-			let transaction = input_pairs.into_iter()
-				.map(Into::into)
-				.collect::<Vec<_>>();
-			let root = trie_root::<H, _, _, _>(transaction.iter().map(|(k, v)| (&*k, &*v)));
-
-			Ok(Some((root, transaction)))
-		},
-		None => Ok(None),
+		.expect("changes trie: storage access is not allowed to fail within runtime");
+	let mut root = Default::default();
+	let mut mdb = MemoryDB::default();
+	{
+		let mut trie = TrieDBMut::<H>::new(&mut mdb, &mut root);
+		for (key, value) in input_pairs.map(Into::into) {
+			trie.insert(&key, &value)
+				.expect("changes trie: insertion to trie is not allowed to fail within runtime");
+		}
 	}
+
+	Ok(Some((mdb, root)))
 }
diff --git a/substrate/core/state-machine/src/ext.rs b/substrate/core/state-machine/src/ext.rs
index d8619d1506d68e2dee345ab305cc0f19f5d3d413..4ade53a6f1ae39af034b3ec9b566379b098c98bb 100644
--- a/substrate/core/state-machine/src/ext.rs
+++ b/substrate/core/state-machine/src/ext.rs
@@ -19,12 +19,12 @@
 use std::{error, fmt, cmp::Ord};
 use log::warn;
 use crate::backend::Backend;
-use crate::changes_trie::{Storage as ChangesTrieStorage, compute_changes_trie_root};
+use crate::changes_trie::{Storage as ChangesTrieStorage, build_changes_trie};
 use crate::{Externalities, OverlayedChanges, ChildStorageKey};
 use hash_db::Hasher;
 use primitives::offchain;
 use primitives::storage::well_known_keys::is_child_storage_key;
-use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root};
+use trie::{MemoryDB, default_child_trie_root};
 
 const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime";
 
@@ -320,27 +320,13 @@ where
 
 	fn storage_changes_root(&mut self, parent_hash: H::Out) -> Result<Option<H::Out>, ()> {
 		let _guard = panic_handler::AbortGuard::new(true);
-		let root_and_tx = compute_changes_trie_root::<_, T, H, N>(
+		self.changes_trie_transaction = build_changes_trie::<_, T, H, N>(
 			self.backend,
 			self.changes_trie_storage.clone(),
 			self.overlay,
 			parent_hash,
 		)?;
-		let root_and_tx = root_and_tx.map(|(root, changes)| {
-			let mut calculated_root = Default::default();
-			let mut mdb = MemoryDB::default();
-			{
-				let mut trie = TrieDBMut::<H>::new(&mut mdb, &mut calculated_root);
-				for (key, value) in changes {
-					trie.insert(&key, &value).expect(EXT_NOT_ALLOWED_TO_FAIL);
-				}
-			}
-
-			(mdb, root)
-		});
-		let root = root_and_tx.as_ref().map(|(_, root)| root.clone());
-		self.changes_trie_transaction = root_and_tx;
-		Ok(root)
+		Ok(self.changes_trie_transaction.as_ref().map(|(_, root)| root.clone()))
 	}
 
 	fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> {
diff --git a/substrate/core/state-machine/src/overlayed_changes.rs b/substrate/core/state-machine/src/overlayed_changes.rs
index 7d6d6081bd26bc9e1c211d94a7fd015e975f18a6..c6d7ab89d3b37ea9f05ccb016f01fa7429d31634 100644
--- a/substrate/core/state-machine/src/overlayed_changes.rs
+++ b/substrate/core/state-machine/src/overlayed_changes.rs
@@ -17,7 +17,7 @@
 //! The overlayed changes to state.
 
 #[cfg(test)] use std::iter::FromIterator;
-use std::collections::{HashMap, HashSet};
+use std::collections::{HashMap, BTreeSet};
 use parity_codec::Decode;
 use crate::changes_trie::{NO_EXTRINSIC_INDEX, Configuration as ChangesTrieConfig};
 use primitives::storage::well_known_keys::EXTRINSIC_INDEX;
@@ -45,7 +45,7 @@ pub struct OverlayedValue {
 	pub value: Option<Vec<u8>>,
 	/// The set of extinsic indices where the values has been changed.
 	/// Is filled only if runtime has announced changes trie support.
-	pub extrinsics: Option<HashSet<u32>>,
+	pub extrinsics: Option<BTreeSet<u32>>,
 }
 
 /// Prospective or committed overlayed change set.
@@ -55,7 +55,7 @@ pub struct OverlayedChangeSet {
 	/// Top level storage changes.
 	pub top: HashMap<Vec<u8>, OverlayedValue>,
 	/// Child storage changes.
-	pub children: HashMap<Vec<u8>, (Option<HashSet<u32>>, HashMap<Vec<u8>, Option<Vec<u8>>>)>,
+	pub children: HashMap<Vec<u8>, (Option<BTreeSet<u32>>, HashMap<Vec<u8>, Option<Vec<u8>>>)>,
 }
 
 #[cfg(test)]
diff --git a/substrate/core/state-machine/src/testing.rs b/substrate/core/state-machine/src/testing.rs
index 4a0e221809004ab9620ea0baaefe17cbd56072d0..dc19dad7b34bba61d43fc7b14a42f68443d52b0e 100644
--- a/substrate/core/state-machine/src/testing.rs
+++ b/substrate/core/state-machine/src/testing.rs
@@ -22,7 +22,7 @@ use hash_db::Hasher;
 use crate::backend::{InMemory, Backend};
 use primitives::storage::well_known_keys::is_child_storage_key;
 use crate::changes_trie::{
-	compute_changes_trie_root, InMemoryStorage as ChangesTrieInMemoryStorage,
+	build_changes_trie, InMemoryStorage as ChangesTrieInMemoryStorage,
 	BlockNumber as ChangesTrieBlockNumber,
 };
 use primitives::offchain;
@@ -250,12 +250,12 @@ impl<H, N> Externalities<H> for TestExternalities<H, N>
 	}
 
 	fn storage_changes_root(&mut self, parent: H::Out) -> Result<Option<H::Out>, ()> {
-		Ok(compute_changes_trie_root::<_, _, H, N>(
+		Ok(build_changes_trie::<_, _, H, N>(
 			&self.backend,
 			Some(&self.changes_trie_storage),
 			&self.overlay,
 			parent,
-		)?.map(|(root, _)| root.clone()))
+		)?.map(|(_, root)| root))
 	}
 
 	fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> {