diff --git a/substrate/core/executor/src/heap.rs b/substrate/core/executor/src/heap.rs
index 708c81b3598612bbe1efcea4f1bf027eefc221d1..dd6ce1bc54a85ba28528a77e158a3369268c3641 100644
--- a/substrate/core/executor/src/heap.rs
+++ b/substrate/core/executor/src/heap.rs
@@ -14,461 +14,43 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
-//! This module implements a buddy allocation heap.
-//! It uses a binary tree and follows the concepts outlined in
-//! https://en.wikipedia.org/wiki/Buddy_memory_allocation.
+#![warn(missing_docs)]
 
-extern crate fnv;
+//! This module implements a linear allocation heap.
 
-use std::vec;
-use log::trace;
-use self::fnv::FnvHashMap;
-
-// The pointers need to be aligned to 8 bytes.
-const ALIGNMENT: u32 = 8;
-
-// The block size needs to be a multiple of the memory alignment
-// requirement. This is so that the pointer returned by `allocate()`
-// always fulfills the alignment. In buddy allocation a pointer always
-// points to the start of a block, which with a fitting block size
-// will then be a multiple of the alignment requirement.
-const BLOCK_SIZE: u32 = 8192; // 2^13 bytes
-
-#[allow(path_statements)]
-fn _assert_block_size_aligned() {
-	// mem::transmute checks that type sizes are equal.
-	// this enables us to assert that pointers are aligned -- at compile time.
-	::std::mem::transmute::<[u8; BLOCK_SIZE as usize % ALIGNMENT as usize], [u8; 0]>;
-}
-
-#[derive(PartialEq, Copy, Clone)]
-enum Node {
-	Free,
-	Full,
-	Split,
-}
-
-/// A buddy allocation heap, which tracks allocations and deallocations
-/// using a binary tree.
 pub struct Heap {
-	allocated_bytes: FnvHashMap<u32, u32>,
-	levels: u32,
-	ptr_offset: u32,
-	tree: vec::Vec<Node>,
+	end: u32,
 	total_size: u32,
 }
 
 impl Heap {
-
-	/// Creates a new buddy allocation heap.
+	/// Construct new `Heap` struct.
 	///
-	/// # Arguments
+	/// Returns `Err` if the heap couldn't allocate required
+	/// number of pages.
 	///
-	/// * `ptr_offset` - The pointers returned by `allocate()`
-	///   start from this offset on. The pointer offset needs
-	///   to be aligned to a multiple of 8, hence a padding might
-	///   be added to align `ptr_offset` properly.
-	///
-	/// * `heap_size` - The size available to this heap instance
-	///   (in bytes) for allocating memory.
-	///
-	pub fn new(mut ptr_offset: u32, heap_size: u32) -> Self {
-		let padding = ptr_offset % ALIGNMENT;
-		if padding != 0 {
-			ptr_offset += ALIGNMENT - padding;
-		}
-
-		let leaves = heap_size / BLOCK_SIZE;
-		let levels = Heap::get_necessary_tree_levels(leaves);
-		let node_count: usize = (1 << levels + 1) - 1;
-
+	/// This could mean that wasm binary specifies memory
+	/// limit and we are trying to allocate beyond that limit.
+	pub fn new(reserved: u32) -> Self {
 		Heap {
-			allocated_bytes: FnvHashMap::default(),
-			levels,
-			ptr_offset,
-			tree: vec![Node::Free; node_count],
+			end: reserved,
 			total_size: 0,
 		}
 	}
 
-	/// Gets requested number of bytes to allocate and returns a pointer.
 	pub fn allocate(&mut self, size: u32) -> u32 {
-		// Get the requested level from number of blocks requested
-		let blocks_needed = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		let block_offset = match self.allocate_block_in_tree(blocks_needed) {
-			Some(v) => v,
-			None => return 0,
-		};
-
-		let ptr = BLOCK_SIZE * block_offset as u32;
-		self.allocated_bytes.insert(ptr, size as u32);
-
-		self.total_size += size;
-		trace!(target: "wasm-heap", "Heap size over {} bytes after allocation", self.total_size);
-
-		self.ptr_offset + ptr
-	}
-
-	fn allocate_block_in_tree(&mut self, blocks_needed: u32) -> Option<usize> {
-		let levels_needed = Heap::get_necessary_tree_levels(blocks_needed);
-		if levels_needed > self.levels {
-			trace!(target: "wasm-heap", "Heap is too small: {:?} > {:?}", levels_needed, self.levels);
-			return None;
-		}
-
-		// Start at tree root and traverse down
-		let mut index = 0;
-		let mut current_level = self.levels;
-		'down: loop {
-			let buddy_exists = index & 1 == 1;
-
-			if current_level == levels_needed {
-				if self.tree[index] == Node::Free {
-					self.tree[index] = Node::Full;
-
-					if index > 0 {
-						let parent = self.get_parent_node_index(index);
-						self.update_parent_nodes(parent);
-					}
-
-					break 'down;
-				}
-			} else {
-				match self.tree[index] {
-					Node::Full => {
-						if buddy_exists {
-							// Check if buddy is free
-							index += 1;
-						} else {
-							break 'down;
-						}
-						continue 'down;
-					},
-
-					Node::Free => {
-						// If node is free we split it and descend further down
-						self.tree[index] = Node::Split;
-						index = index * 2 + 1;
-						current_level -= 1;
-						continue 'down;
-					},
-
-					Node::Split => {
-						// Descend further
-						index = index * 2 + 1;
-						current_level -= 1;
-						continue 'down;
-					},
-				}
-			}
-
-			if buddy_exists {
-				// If a buddy exists it needs to be checked as well
-				index += 1;
-				continue 'down;
-			}
-
-			// Backtrack once we're at the bottom and haven't matched a free block yet
-			'up: loop {
-				if index == 0 {
-					trace!(target: "wasm-heap", "Heap is too small: tree root reached.");
-					return None;
-				}
-
-				index = self.get_parent_node_index(index);
-				current_level += 1;
-				let has_buddy = index & 1 == 1;
-				if has_buddy {
-					index += 1;
-					break 'up;
-				}
-			}
-		}
-
-		let current_level_offset = (1 << self.levels - current_level) - 1;
-		let level_offset = index - current_level_offset;
-
-		let block_offset = level_offset * (1 << current_level);
-		Some(block_offset as usize)
-	}
-
-	/// Deallocates all blocks which were allocated for a pointer.
-	pub fn deallocate(&mut self, mut ptr: u32) {
-		ptr -= self.ptr_offset;
-
-		let allocated_size = match self.allocated_bytes.get(&ptr) {
-			Some(v) => *v,
-
-			// If nothing has been allocated for the pointer nothing happens
-			None => return (),
-		};
-
-		let count_blocks = (allocated_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-		let block_offset = ptr / BLOCK_SIZE;
-		self.free(block_offset, count_blocks);
-		self.allocated_bytes.remove(&ptr).unwrap_or_default();
-
-		self.total_size = self.total_size.checked_sub(allocated_size).unwrap_or(0);
-		trace!(target: "wasm-heap", "Heap size over {} bytes after deallocation", self.total_size);
-	}
-
-	fn free(&mut self, block_offset: u32, count_blocks: u32) {
-		let requested_level = Heap::get_necessary_tree_levels(count_blocks);
-		let current_level_offset = (1 << self.levels - requested_level) - 1;
-		let level_offset = block_offset / (1 << requested_level);
-		let index_offset = current_level_offset + level_offset;
-
-		if index_offset > self.tree.len() as u32 - 1 {
-			trace!(target: "wasm-heap", "Index offset {} is > length of tree {}", index_offset, self.tree.len());
-		}
-
-		self.free_and_merge(index_offset as usize);
-
-		let parent = self.get_parent_node_index(index_offset as usize);
-		self.update_parent_nodes(parent);
-	}
-
-	fn get_parent_node_index(&mut self, index: usize) -> usize {
-		(index + 1) / 2 - 1
-	}
-
-	fn free_and_merge(&mut self, index: usize) {
-		self.tree[index] = Node::Free;
-
-		if index == 0 {
-			return;
-		}
-
-		let has_right_buddy = (index & 1) == 1;
-		let other_node = if has_right_buddy {
-			index + 1
-		} else {
-			index - 1
-		};
-
-		if self.tree[other_node] == Node::Free {
-			let parent = self.get_parent_node_index(index);
-			self.free_and_merge(parent);
-		}
-	}
-
-	fn update_parent_nodes(&mut self, index: usize) {
-		let left_child = index * 2 + 1;
-		let right_child = index * 2 + 2;
-
-		let children_free = self.tree[left_child] == Node::Free && self.tree[right_child] == Node::Free;
-		let children_full = self.tree[left_child] == Node::Full && self.tree[right_child] == Node::Full;
-		if children_free {
-			self.tree[index] = Node::Free;
-		} else if children_full {
-			self.tree[index] = Node::Full;
-		} else {
-			self.tree[index] = Node::Split;
-		}
-
-		if index == 0 {
-			// Tree root
-			return;
-		}
-
-		let parent = self.get_parent_node_index(index);
-		self.update_parent_nodes(parent);
-	}
-
-	fn get_necessary_tree_levels(count_blocks: u32) -> u32 {
-		if count_blocks == 0 {
-			0
-		} else {
-			let mut necessary_levels = 0;
-			let mut necessary_blocks = count_blocks.next_power_of_two();
-			while {necessary_blocks >>= 1; necessary_blocks > 0} {
-				necessary_levels += 1;
+		let r = self.end;
+		self.end += size;
+		let new_total_size = r + size;
+		if new_total_size > self.total_size {
+			if new_total_size / 1024  > self.total_size / 1024 {
+				trace!(target: "wasm-heap", "Allocated over {} MB",  new_total_size / 1024 / 1024);
 			}
-			necessary_levels
-		}
-	}
-
-}
-
-#[cfg(test)]
-mod tests {
-	use super::*;
-
-	#[test]
-	fn should_always_align_pointers_to_multiples_of_8() {
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(13, heap_size);
-
-		let ptr = heap.allocate(1);
-		assert_eq!(ptr, 16); // 16 is the next multiple of 8 from 13
-	}
-
-	#[test]
-	fn should_start_first_pointer_at_offset() {
-		let start_offset = 40;
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(start_offset, heap_size);
-
-		let ptr = heap.allocate(BLOCK_SIZE - 1);
-		assert_eq!(ptr, start_offset);
-	}
-
-	#[test]
-	fn should_start_second_pointer_at_second_block() {
-		let start_offset = 40;
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(start_offset, heap_size);
-
-		let _ptr1 = heap.allocate(BLOCK_SIZE - 1);
-		let ptr2 = heap.allocate(BLOCK_SIZE - 1);
-		assert_eq!(ptr2, start_offset + BLOCK_SIZE);
-	}
-
-	#[test]
-	fn should_not_panic_on_deallocation_of_nonexistent_pointer() {
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(1, heap_size);
-		let ret = heap.deallocate(heap_size + 1);
-		assert_eq!(ret, ());
-	}
-
-	#[test]
-	fn should_calculate_tree_size_from_heap_size() {
-		let heap_size = BLOCK_SIZE * 4;
-		let heap = super::Heap::new(1, heap_size);
-
-		assert_eq!(heap.levels, 2);
-	}
-
-	#[test]
-	fn should_round_tree_size_to_nearest_possible() {
-		let heap_size = BLOCK_SIZE * 4 + 1;
-		let heap = super::Heap::new(1, heap_size);
-
-		assert_eq!(heap.levels, 2);
-	}
-
-	#[test]
-	fn heap_size_should_stay_zero_in_total() {
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(1, heap_size);
-		assert_eq!(heap.total_size, 0);
-
-		let ptr = heap.allocate(42);
-		assert_eq!(heap.total_size, 42);
-
-		heap.deallocate(ptr);
-		assert_eq!(heap.total_size, 0);
-	}
-
-	#[test]
-	fn heap_size_should_stay_constant() {
-		let heap_size = BLOCK_SIZE * 4;
-		let mut heap = super::Heap::new(9, heap_size);
-		for _ in 1..10 {
-			assert_eq!(heap.total_size, 0);
-
-			let ptr = heap.allocate(42);
-			assert_eq!(ptr, 16);
-			assert_eq!(heap.total_size, 42);
-
-			heap.deallocate(ptr);
-			assert_eq!(heap.total_size, 0);
-		}
-
-		assert_eq!(heap.total_size, 0);
-	}
-
-	#[test]
-	fn should_allocate_exactly_entire_tree() {
-		let blocks = 16;
-		let heap_size = BLOCK_SIZE * blocks;
-		let mut heap = super::Heap::new(0, heap_size);
-
-		for i in 0..16 {
-			let ptr = heap.allocate(BLOCK_SIZE);
-			assert_eq!(ptr, i * BLOCK_SIZE);
-			assert_eq!(heap.total_size, (i+1) * BLOCK_SIZE);
+			self.total_size = new_total_size;
 		}
-
-		let ptr = heap.allocate(BLOCK_SIZE);
-		assert_eq!(ptr, 0);
-	}
-
-	#[test]
-	fn should_deallocate_entire_tree_exactly() {
-		let blocks = 12;
-		let heap_size = BLOCK_SIZE * blocks;
-		let mut heap = super::Heap::new(0, heap_size);
-		for i in 0..blocks {
-			let ptr = heap.allocate(BLOCK_SIZE);
-			assert_eq!(ptr, i * BLOCK_SIZE);
-			assert_eq!(heap.total_size, (i+1) * BLOCK_SIZE);
-		}
-
-		for i in 0..blocks {
-			let ptr = i * BLOCK_SIZE;
-			heap.deallocate(ptr);
-			assert_eq!(heap.total_size, blocks * BLOCK_SIZE - (i+1) * BLOCK_SIZE);
-		}
-
-		assert_eq!(heap.total_size, 0);
+		r
 	}
 
-	#[test]
-	fn should_allocate_pointers_with_odd_blocks_properly() {
-		let blocks = 6;
-		let heap_size = BLOCK_SIZE * blocks;
-		let mut heap = super::Heap::new(0, heap_size);
-
-		let ptr = heap.allocate(3 * BLOCK_SIZE);
-		assert_eq!(ptr, 0);
-
-		let ptr = heap.allocate(BLOCK_SIZE);
-		assert_eq!(ptr, 4 * BLOCK_SIZE);
-	}
-
-	#[test]
-	fn should_handle_odd_blocks_properly() {
-		let blocks = 8;
-		let heap_size = BLOCK_SIZE * blocks;
-		let mut heap = super::Heap::new(0, heap_size);
-
-		let ptr = heap.allocate(3 * BLOCK_SIZE);
-		assert_eq!(ptr, 0);
-
-		let ptr = heap.allocate(3 * BLOCK_SIZE);
-		assert_eq!(ptr, 4 * BLOCK_SIZE);
-	}
-
-	#[test]
-	fn should_calculate_zero_tree_levels_for_zero_blocks() {
-		let count_blocks = 0;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 0);
+	pub fn deallocate(&mut self, _offset: u32) {
 	}
-
-	#[test]
-	fn should_calculate_necessary_tree_levels_correctly() {
-		let count_blocks = 1;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 0);
-
-		let count_blocks = 2;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 1);
-
-		let count_blocks = 3;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 2);
-
-		let count_blocks = 4;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 2);
-
-		let count_blocks = 5;
-		let levels = Heap::get_necessary_tree_levels(count_blocks);
-		assert_eq!(levels, 3);
-	}
-
 }
diff --git a/substrate/core/executor/src/lib.rs b/substrate/core/executor/src/lib.rs
index a42b5a041d3cabdcf8a3ebebe474c513bc001bda..898e9731640c5cb0899ddf2f545c118ed34a3739 100644
--- a/substrate/core/executor/src/lib.rs
+++ b/substrate/core/executor/src/lib.rs
@@ -28,6 +28,9 @@
 #![warn(missing_docs)]
 #![recursion_limit="128"]
 
+#[macro_use]
+extern crate log;
+
 #[macro_use]
 mod wasm_utils;
 mod wasm_executor;
diff --git a/substrate/core/executor/src/wasm_executor.rs b/substrate/core/executor/src/wasm_executor.rs
index f062603aef032516cdc340df059bd0ec4c617ae7..2eee9be59f6b921b73bb38a7fc7d84c4122d6f9b 100644
--- a/substrate/core/executor/src/wasm_executor.rs
+++ b/substrate/core/executor/src/wasm_executor.rs
@@ -24,7 +24,7 @@ use wasmi::{
 	Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef,
 };
 use wasmi::RuntimeValue::{I32, I64};
-use wasmi::memory_units::{Bytes, Pages};
+use wasmi::memory_units::Pages;
 use state_machine::Externalities;
 use crate::error::{Error, ErrorKind, Result};
 use crate::wasm_utils::UserError;
@@ -57,14 +57,9 @@ struct FunctionExecutor<'e, E: Externalities<Blake2Hasher> + 'e> {
 
 impl<'e, E: Externalities<Blake2Hasher>> FunctionExecutor<'e, E> {
 	fn new(m: MemoryRef, t: Option<TableRef>, e: &'e mut E) -> Result<Self> {
-		let current_size: Bytes = m.current_size().into();
-		let current_size = current_size.0 as u32;
-		let used_size = m.used_size().0 as u32;
-		let heap_size = current_size - used_size;
-
 		Ok(FunctionExecutor {
 			sandbox_store: sandbox::Store::new(),
-			heap: heap::Heap::new(used_size, heap_size),
+			heap: heap::Heap::new(m.used_size().0 as u32),
 			memory: m,
 			table: t,
 			ext: e,