diff --git a/substrate/core/client/db/src/lib.rs b/substrate/core/client/db/src/lib.rs
index b39fbb9f06adccc4d3de8b97f787814a42748f91..99483b428882c5617746c8864944f6e8468bb4c8 100644
--- a/substrate/core/client/db/src/lib.rs
+++ b/substrate/core/client/db/src/lib.rs
@@ -52,6 +52,7 @@ use executor::RuntimeInfo;
 use state_machine::{CodeExecutor, DBValue};
 use crate::utils::{Meta, db_err, meta_keys, open_database, read_db, block_id_to_lookup_key, read_meta};
 use client::LeafSet;
+use client::children;
 use state_db::StateDb;
 use crate::storage_cache::{CachingState, SharedCache, new_shared_cache};
 use log::{trace, debug, warn};
@@ -249,6 +250,10 @@ impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> {
 	fn leaves(&self) -> Result<Vec<Block::Hash>, client::error::Error> {
 		Ok(self.leaves.read().hashes())
 	}
+
+	fn children(&self, parent_hash: Block::Hash) -> Result<Vec<Block::Hash>, client::error::Error> {
+		children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash)
+	}
 }
 
 /// Database transaction
@@ -857,6 +862,10 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
 				displaced_leaf
 			};
 
+			let mut children = children::read_children(&*self.storage.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash)?;
+			children.push(hash);
+			children::write_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash, children);
+
 			meta_updates.push((hash, number, pending_block.leaf_state.is_best(), finalized));
 
 			Some((number, hash, enacted, retracted, displaced_leaf, is_best))
@@ -1080,6 +1089,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
 					let key = utils::number_and_hash_to_lookup_key(best.clone(), &hash);
 					transaction.put(columns::META, meta_keys::BEST_BLOCK, &key);
 					transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref());
+					children::remove_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, hash);
 					self.storage.db.write(transaction).map_err(db_err)?;
 					self.blockchain.update_meta(hash, best, true, false);
 					self.blockchain.leaves.write().revert(removed.hash().clone(), removed.number().clone(), removed.parent_hash().clone());
@@ -1793,6 +1803,12 @@ mod tests {
 		test_client::trait_tests::test_leaves_for_backend(backend);
 	}
 
+	#[test]
+	fn test_children_with_complex_block_tree() {
+		let backend: Arc<Backend<test_client::runtime::Block>> = Arc::new(Backend::new_test(20, 20));
+		test_client::trait_tests::test_children_for_backend(backend);
+	}
+
 	#[test]
 	fn test_blockchain_query_by_number_gets_canonical() {
 		let backend: Arc<Backend<test_client::runtime::Block>> = Arc::new(Backend::new_test(20, 20));
diff --git a/substrate/core/client/db/src/utils.rs b/substrate/core/client/db/src/utils.rs
index f1e4f3d2e23256a92391dbad1d342c268a59aef7..150c1fdd98ccdef5b596735f2e523bd179a3a35f 100644
--- a/substrate/core/client/db/src/utils.rs
+++ b/substrate/core/client/db/src/utils.rs
@@ -51,6 +51,8 @@ pub mod meta_keys {
 	pub const GENESIS_HASH: &[u8; 3] = b"gen";
 	/// Leaves prefix list key.
 	pub const LEAF_PREFIX: &[u8; 4] = b"leaf";
+	/// Children prefix list key.
+	pub const CHILDREN_PREFIX: &[u8; 8] = b"children";
 }
 
 /// Database metadata.
diff --git a/substrate/core/client/src/blockchain.rs b/substrate/core/client/src/blockchain.rs
index 986360764d3dacf3b2608a9c6bc02ab45e3272d4..eb9ce1342eade2c58ef154d583a302f4ddb54987 100644
--- a/substrate/core/client/src/blockchain.rs
+++ b/substrate/core/client/src/blockchain.rs
@@ -84,6 +84,9 @@ pub trait Backend<Block: BlockT>: HeaderBackend<Block> {
 	/// in other words, that have no children, are chain heads.
 	/// Results must be ordered best (longest, heighest) chain first.
 	fn leaves(&self) -> Result<Vec<Block::Hash>>;
+
+	/// Return hashes of all blocks that are children of the block with `parent_hash`.
+	fn children(&self, parent_hash: Block::Hash) -> Result<Vec<Block::Hash>>;
 }
 
 /// Blockchain optional data cache.
diff --git a/substrate/core/client/src/children.rs b/substrate/core/client/src/children.rs
new file mode 100644
index 0000000000000000000000000000000000000000..48b39d18cdd60d8c11585aae71d30ce1ab9ce335
--- /dev/null
+++ b/substrate/core/client/src/children.rs
@@ -0,0 +1,121 @@
+// Copyright 2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Functionality for reading and storing children hashes from db.
+
+use kvdb::{KeyValueDB, DBTransaction};
+use parity_codec::{Encode, Decode};
+use crate::error;
+use std::hash::Hash;
+
+
+/// Returns the hashes of the children blocks of the block with `parent_hash`.
+pub fn read_children<
+	K: Eq + Hash + Clone + Encode + Decode,
+	V: Eq + Hash + Clone + Encode + Decode,
+>(db: &KeyValueDB, column: Option<u32>, prefix: &[u8], parent_hash: K) -> error::Result<Vec<V>> {
+	let mut buf = prefix.to_vec();
+	parent_hash.using_encoded(|s| buf.extend(s));
+
+	let raw_val_opt = match db.get(column, &buf[..]) {
+		Ok(raw_val_opt) => raw_val_opt,
+		Err(_) => return Err(error::ErrorKind::Backend("Error reading value from database".into()).into()),
+	};
+
+	let raw_val = match raw_val_opt {
+		Some(val) => val,
+		None => return Ok(Vec::new()),
+	};
+
+	let children: Vec<V> = match Decode::decode(&mut &raw_val[..]) {
+		Some(children) => children,
+		None => return Err(error::ErrorKind::Backend("Error decoding children".into()).into()),
+	};
+
+	Ok(children)
+}
+
+/// Insert the key-value pair (`parent_hash`, `children_hashes`) in the transaction.
+/// Any existing value is overwritten upon write.
+pub fn write_children<
+	K: Eq + Hash + Clone + Encode + Decode,
+	V: Eq + Hash + Clone + Encode + Decode,
+>(
+	tx: &mut DBTransaction,
+	column: Option<u32>,
+	prefix: &[u8],
+	parent_hash: K,
+	children_hashes: V,
+) {
+	let mut key = prefix.to_vec();
+	parent_hash.using_encoded(|s| key.extend(s));
+	tx.put_vec(column, &key[..], children_hashes.encode());
+}
+
+/// Prepare transaction to remove the children of `parent_hash`.
+pub fn remove_children<
+	K: Eq + Hash + Clone + Encode + Decode,
+>(
+	tx: &mut DBTransaction,
+	column: Option<u32>,
+	prefix: &[u8],
+	parent_hash: K,
+) {
+	let mut key = prefix.to_vec();
+	parent_hash.using_encoded(|s| key.extend(s));
+	tx.delete(column, &key[..]);
+}
+
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+
+	#[test]
+	fn children_write_read_remove() {
+		const PREFIX: &[u8] = b"children";
+		let db = ::kvdb_memorydb::create(0);
+
+		let mut tx = DBTransaction::new();
+
+		let mut children1 = Vec::new();
+		children1.push(1_3);
+		children1.push(1_5);
+		write_children(&mut tx, None, PREFIX, 1_1, children1);
+
+		let mut children2 = Vec::new();
+		children2.push(1_4);
+		children2.push(1_6);
+		write_children(&mut tx, None, PREFIX, 1_2, children2);
+
+		db.write(tx.clone()).unwrap();
+
+		let r1: Vec<u32> = read_children(&db, None, PREFIX, 1_1).unwrap();
+		let r2: Vec<u32> = read_children(&db, None, PREFIX, 1_2).unwrap();
+
+		assert_eq!(r1, vec![1_3, 1_5]);
+		assert_eq!(r2, vec![1_4, 1_6]);
+
+		remove_children(&mut tx, None, PREFIX, 1_2);
+		db.write(tx).unwrap();
+
+		let r1: Vec<u32> = read_children(&db, None, PREFIX, 1_1).unwrap();
+		let r2: Vec<u32> = read_children(&db, None, PREFIX, 1_2).unwrap();
+
+		assert_eq!(r1, vec![1_3, 1_5]);
+		assert_eq!(r2.len(), 0);		
+	}
+}
\ No newline at end of file
diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs
index 375e36e81f54518c692af192b551e028aabb8fda..99f276ea2bbaf59015c8b8f242cd6b6507324386 100644
--- a/substrate/core/client/src/client.rs
+++ b/substrate/core/client/src/client.rs
@@ -56,7 +56,7 @@ use executor::{RuntimeVersion, RuntimeInfo};
 use crate::notifications::{StorageNotifications, StorageEventStream};
 use crate::light::{call_executor::prove_execution, fetcher::ChangesProof};
 use crate::cht;
-use crate::error;
+use crate::error::{self, ErrorKind};
 use crate::in_mem;
 use crate::block_builder::{self, api::BlockBuilder as BlockBuilderAPI};
 use crate::genesis;
@@ -1230,6 +1230,37 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
 		Ok(None)
 	}
 
+	/// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors.
+	pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor<Block>) -> error::Result<Vec<Block::Hash>> {
+		let load_header = |id: Block::Hash| -> error::Result<Block::Header> {
+			match self.backend.blockchain().header(BlockId::Hash(id))? {
+				Some(hdr) => Ok(hdr),
+				None => Err(ErrorKind::UnknownBlock(format!("Unknown block {:?}", id)).into()),
+			}
+		};
+
+		let genesis_hash = self.backend.blockchain().info()?.genesis_hash;
+		if genesis_hash == target_hash { return Ok(Vec::new()); }
+
+		let mut current_hash = target_hash;
+		let mut current = load_header(current_hash)?;
+		let mut ancestor_hash = *current.parent_hash();
+		let mut ancestor = load_header(ancestor_hash)?;
+		let mut uncles = Vec::new();
+
+		for _generation in 0..max_generation.as_() {
+			let children = self.backend.blockchain().children(ancestor_hash)?;
+			uncles.extend(children.into_iter().filter(|h| h != &current_hash));
+			current_hash = ancestor_hash;
+			if genesis_hash == current_hash { break; }
+			current = ancestor;
+			ancestor_hash = *current.parent_hash();
+			ancestor = load_header(ancestor_hash)?;
+		}
+
+		Ok(uncles)
+	}
+
 	fn changes_trie_config(&self) -> Result<Option<ChangesTrieConfiguration>, Error> {
 		Ok(self.backend.state_at(BlockId::Number(self.backend.blockchain().info()?.best_number))?
 			.storage(well_known_keys::CHANGES_TRIE_CONFIG)
@@ -1705,6 +1736,117 @@ pub(crate) mod tests {
 		assert_eq!(None, client.best_containing(uninserted_block.hash().clone(), None).unwrap());
 	}
 
+	#[test]
+	fn uncles_with_only_ancestors() {
+		// block tree:
+		// G -> A1 -> A2
+		let client = test_client::new();
+
+		// G -> A1
+		let a1 = client.new_block().unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a1.clone()).unwrap();
+
+		// A1 -> A2
+		let a2 = client.new_block().unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a2.clone()).unwrap();
+		let v: Vec<H256> = Vec::new();
+		assert_eq!(v, client.uncles(a2.hash(), 3).unwrap());
+	}
+
+	#[test]
+	fn uncles_with_multiple_forks() {
+		// block tree:
+		// G -> A1 -> A2 -> A3 -> A4 -> A5
+		//      A1 -> B2 -> B3 -> B4
+		//	          B2 -> C3
+		//	    A1 -> D2
+		let client = test_client::new();
+
+		// G -> A1
+		let a1 = client.new_block().unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a1.clone()).unwrap();
+
+		// A1 -> A2
+		let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a2.clone()).unwrap();
+
+		// A2 -> A3
+		let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a3.clone()).unwrap();
+
+		// A3 -> A4
+		let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a4.clone()).unwrap();
+
+		// A4 -> A5
+		let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, a5.clone()).unwrap();
+
+		// A1 -> B2
+		let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap();
+		// this push is required as otherwise B2 has the same hash as A2 and won't get imported
+		builder.push_transfer(Transfer {
+			from: Keyring::Alice.to_raw_public().into(),
+			to: Keyring::Ferdie.to_raw_public().into(),
+			amount: 41,
+			nonce: 0,
+		}).unwrap();
+		let b2 = builder.bake().unwrap();
+		client.import(BlockOrigin::Own, b2.clone()).unwrap();
+
+		// B2 -> B3
+		let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, b3.clone()).unwrap();
+
+		// B3 -> B4
+		let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap();
+		client.import(BlockOrigin::Own, b4.clone()).unwrap();
+
+		// // B2 -> C3
+		let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap();
+		// this push is required as otherwise C3 has the same hash as B3 and won't get imported
+		builder.push_transfer(Transfer {
+			from: Keyring::Alice.to_raw_public().into(),
+			to: Keyring::Ferdie.to_raw_public().into(),
+			amount: 1,
+			nonce: 1,
+		}).unwrap();
+		let c3 = builder.bake().unwrap();
+		client.import(BlockOrigin::Own, c3.clone()).unwrap();
+
+		// A1 -> D2
+		let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap();
+		// this push is required as otherwise D2 has the same hash as B2 and won't get imported
+		builder.push_transfer(Transfer {
+			from: Keyring::Alice.to_raw_public().into(),
+			to: Keyring::Ferdie.to_raw_public().into(),
+			amount: 1,
+			nonce: 0,
+		}).unwrap();
+		let d2 = builder.bake().unwrap();
+		client.import(BlockOrigin::Own, d2.clone()).unwrap();
+
+		let genesis_hash = client.info().unwrap().chain.genesis_hash;
+
+		let uncles1 = client.uncles(a4.hash(), 10).unwrap();
+		assert_eq!(vec![b2.hash(), d2.hash()], uncles1);
+
+		let uncles2 = client.uncles(a4.hash(), 0).unwrap();
+		assert_eq!(0, uncles2.len());
+
+		let uncles3 = client.uncles(a1.hash(), 10).unwrap();
+		assert_eq!(0, uncles3.len());
+
+		let uncles4 = client.uncles(genesis_hash, 10).unwrap();
+		assert_eq!(0, uncles4.len());
+
+		let uncles5 = client.uncles(d2.hash(), 10).unwrap();
+		assert_eq!(vec![a2.hash(), b2.hash()], uncles5);
+
+		let uncles6 = client.uncles(b3.hash(), 1).unwrap();
+		assert_eq!(vec![c3.hash()], uncles6);
+	}
+
 	#[test]
 	fn best_containing_with_single_chain_3_blocks() {
 		// block tree:
diff --git a/substrate/core/client/src/in_mem.rs b/substrate/core/client/src/in_mem.rs
index fda962aca01dab32785502ff178574d98f1403fb..6c90d9ae3e84fb5d3947d9b7bc03dbf02059db6c 100644
--- a/substrate/core/client/src/in_mem.rs
+++ b/substrate/core/client/src/in_mem.rs
@@ -19,22 +19,23 @@
 use std::collections::HashMap;
 use std::sync::Arc;
 use parking_lot::RwLock;
-use crate::error;
-use crate::backend::{self, NewBlockState};
-use crate::light;
 use primitives::{ChangesTrieConfiguration, storage::well_known_keys};
 use runtime_primitives::generic::BlockId;
 use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero,
 	NumberFor, As, Digest, DigestItem, AuthorityIdFor};
 use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay};
-use crate::blockchain::{self, BlockStatus, HeaderBackend};
 use state_machine::backend::{Backend as StateBackend, InMemory, Consolidate};
 use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId};
 use hash_db::Hasher;
 use heapsize::HeapSizeOf;
-use crate::leaves::LeafSet;
 use trie::MemoryDB;
 
+use crate::error;
+use crate::backend::{self, NewBlockState};
+use crate::light;
+use crate::leaves::LeafSet;
+use crate::blockchain::{self, BlockStatus, HeaderBackend};
+
 struct PendingBlock<B: BlockT> {
 	block: StoredBlock<B>,
 	state: NewBlockState,
@@ -168,7 +169,6 @@ impl<Block: BlockT> Blockchain<Block> {
 		new_state: NewBlockState,
 	) -> crate::error::Result<()> {
 		let number = header.number().clone();
-
 		if new_state.is_best() {
 			self.apply_head(&header)?;
 		}
@@ -362,6 +362,10 @@ impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
 	fn leaves(&self) -> error::Result<Vec<Block::Hash>> {
 		Ok(self.storage.read().leaves.hashes())
 	}
+
+	fn children(&self, _parent_hash: Block::Hash) -> error::Result<Vec<Block::Hash>> {
+		unimplemented!()
+	}
 }
 
 impl<Block: BlockT> backend::AuxStore for Blockchain<Block> {
diff --git a/substrate/core/client/src/leaves.rs b/substrate/core/client/src/leaves.rs
index 83741556216973185492c876b40b5275fbfd501a..92bdfa64ec64096bb1b6cb22e0ed7e0fac12e517 100644
--- a/substrate/core/client/src/leaves.rs
+++ b/substrate/core/client/src/leaves.rs
@@ -84,7 +84,6 @@ impl<H, N> LeafSet<H, N> where
 	/// Read the leaf list from the DB, using given prefix for keys.
 	pub fn read_from_db(db: &KeyValueDB, column: Option<u32>, prefix: &[u8]) -> error::Result<Self> {
 		let mut storage = BTreeSet::new();
-
 		for (key, value) in db.iter_from_prefix(column, prefix) {
 			if !key.starts_with(prefix) { break }
 			let raw_hash = &mut &key[prefix.len()..];
diff --git a/substrate/core/client/src/lib.rs b/substrate/core/client/src/lib.rs
index 7472b358d0d72c51f36eaeb60af51c3ab43bfc50..44eaa449245bb36551e2b3c01959c5e261ba1807 100644
--- a/substrate/core/client/src/lib.rs
+++ b/substrate/core/client/src/lib.rs
@@ -38,6 +38,8 @@ pub mod block_builder;
 #[cfg(feature = "std")]
 pub mod light;
 #[cfg(feature = "std")]
+pub mod children;
+#[cfg(feature = "std")]
 mod leaves;
 #[cfg(feature = "std")]
 mod call_executor;
@@ -46,6 +48,7 @@ mod client;
 #[cfg(feature = "std")]
 mod notifications;
 
+
 #[cfg(feature = "std")]
 pub use crate::blockchain::Info as ChainInfo;
 #[cfg(feature = "std")]
diff --git a/substrate/core/client/src/light/blockchain.rs b/substrate/core/client/src/light/blockchain.rs
index 36a236f32e2df06e83178e8140447d92c2832894..73d530ce455454f8b4295d4403aee137bfde8a90 100644
--- a/substrate/core/client/src/light/blockchain.rs
+++ b/substrate/core/client/src/light/blockchain.rs
@@ -163,6 +163,10 @@ impl<S, F, Block> BlockchainBackend<Block> for Blockchain<S, F> where Block: Blo
 	fn leaves(&self) -> ClientResult<Vec<Block::Hash>> {
 		unimplemented!()
 	}
+
+	fn children(&self, _parent_hash: Block::Hash) -> ClientResult<Vec<Block::Hash>> {
+		unimplemented!()
+	}
 }
 
 #[cfg(test)]
diff --git a/substrate/core/test-client/src/trait_tests.rs b/substrate/core/test-client/src/trait_tests.rs
index 7fadc128faf2c544f1f9e00e23150bb509426c88..8242f30d2e23f412477a8bdfb0753dea53469084 100644
--- a/substrate/core/test-client/src/trait_tests.rs
+++ b/substrate/core/test-client/src/trait_tests.rs
@@ -144,6 +144,96 @@ pub fn test_leaves_for_backend<B: 'static>(backend: Arc<B>) where
 		vec![a5.hash(), b4.hash(), c3.hash(), d2.hash()]);
 }
 
+/// helper to test the `children` implementation for various backends
+pub fn test_children_for_backend<B: 'static>(backend: Arc<B>) where
+	B: backend::LocalBackend<runtime::Block, Blake2Hasher>,
+{
+	// block tree:
+	// G -> A1 -> A2 -> A3 -> A4 -> A5
+	//		A1 -> B2 -> B3 -> B4
+	//			  B2 -> C3
+	//		A1 -> D2
+
+	let client = new_with_backend(backend.clone(), false);
+
+	// G -> A1
+	let a1 = client.new_block().unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, a1.clone()).unwrap();
+
+	// A1 -> A2
+	let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, a2.clone()).unwrap();
+
+	// A2 -> A3
+	let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, a3.clone()).unwrap();
+
+	// A3 -> A4
+	let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, a4.clone()).unwrap();
+
+	// A4 -> A5
+	let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, a5.clone()).unwrap();
+
+	// A1 -> B2
+	let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap();
+	// this push is required as otherwise B2 has the same hash as A2 and won't get imported
+	builder.push_transfer(Transfer {
+		from: Keyring::Alice.to_raw_public().into(),
+		to: Keyring::Ferdie.to_raw_public().into(),
+		amount: 41,
+		nonce: 0,
+	}).unwrap();
+	let b2 = builder.bake().unwrap();
+	client.import(BlockOrigin::Own, b2.clone()).unwrap();
+
+	// B2 -> B3
+	let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, b3.clone()).unwrap();
+
+	// B3 -> B4
+	let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap();
+	client.import(BlockOrigin::Own, b4.clone()).unwrap();
+
+	// // B2 -> C3
+	let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap();
+	// this push is required as otherwise C3 has the same hash as B3 and won't get imported
+	builder.push_transfer(Transfer {
+		from: Keyring::Alice.to_raw_public().into(),
+		to: Keyring::Ferdie.to_raw_public().into(),
+		amount: 1,
+		nonce: 1,
+	}).unwrap();
+	let c3 = builder.bake().unwrap();
+	client.import(BlockOrigin::Own, c3.clone()).unwrap();
+
+	// A1 -> D2
+	let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap();
+	// this push is required as otherwise D2 has the same hash as B2 and won't get imported
+	builder.push_transfer(Transfer {
+		from: Keyring::Alice.to_raw_public().into(),
+		to: Keyring::Ferdie.to_raw_public().into(),
+		amount: 1,
+		nonce: 0,
+	}).unwrap();
+	let d2 = builder.bake().unwrap();
+	client.import(BlockOrigin::Own, d2.clone()).unwrap();
+
+	let genesis_hash = client.info().unwrap().chain.genesis_hash;
+
+	let children1 = backend.blockchain().children(a4.hash()).unwrap();
+	assert_eq!(vec![a5.hash()], children1);
+
+	let children2 = backend.blockchain().children(a1.hash()).unwrap();
+	assert_eq!(vec![a2.hash(), b2.hash(), d2.hash()], children2);
+
+	let children3 = backend.blockchain().children(genesis_hash).unwrap();
+	assert_eq!(vec![a1.hash()], children3);
+
+	let children4 = backend.blockchain().children(b2.hash()).unwrap();
+	assert_eq!(vec![b3.hash(), c3.hash()], children4);
+}
 
 pub fn test_blockchain_query_by_number_gets_canonical<B: 'static>(backend: Arc<B>) where
 	B: backend::LocalBackend<runtime::Block, Blake2Hasher>,