aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MemTrie.cpp479
-rw-r--r--MemTrie.h54
-rw-r--r--TrieHash.cpp198
-rw-r--r--TrieHash.h34
-rw-r--r--trie.cpp4
5 files changed, 767 insertions, 2 deletions
diff --git a/MemTrie.cpp b/MemTrie.cpp
new file mode 100644
index 00000000..0a7d0ebe
--- /dev/null
+++ b/MemTrie.cpp
@@ -0,0 +1,479 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file MemTrie.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "MemTrie.h"
+
+#include <CommonEth.h>
+#include <TrieCommon.h>
+using namespace std;
+using namespace eth;
+
+namespace eth
+{
+
+#define ENABLE_DEBUG_PRINT 0
+
+/*/
+#define APPEND_CHILD appendData
+/*/
+#define APPEND_CHILD appendRaw
+/**/
+
+class MemTrieNode
+{
+public:
+ MemTrieNode() {}
+ virtual ~MemTrieNode() {}
+
+ virtual std::string const& at(bytesConstRef _key) const = 0;
+ virtual MemTrieNode* insert(bytesConstRef _key, std::string const& _value) = 0;
+ virtual MemTrieNode* remove(bytesConstRef _key) = 0;
+ void putRLP(RLPStream& _parentStream) const;
+
+#if ENABLE_DEBUG_PRINT
+ void debugPrint(std::string const& _indent = "") const { std::cerr << std::hex << hash256() << ":" << std::dec << std::endl; debugPrintBody(_indent); }
+#endif
+
+ /// 256-bit hash of the node - this is a SHA-3/256 hash of the RLP of the node.
+ h256 hash256() const { RLPStream s; makeRLP(s); return eth::sha3(s.out()); }
+ bytes rlp() const { RLPStream s; makeRLP(s); return s.out(); }
+ void mark() { m_hash256 = h256(); }
+
+protected:
+ virtual void makeRLP(RLPStream& _intoStream) const = 0;
+
+#if ENABLE_DEBUG_PRINT
+ virtual void debugPrintBody(std::string const& _indent = "") const = 0;
+#endif
+
+ static MemTrieNode* newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2);
+
+private:
+ mutable h256 m_hash256;
+};
+
+static const std::string c_nullString;
+
+class TrieExtNode: public MemTrieNode
+{
+public:
+ TrieExtNode(bytesConstRef _bytes): m_ext(_bytes.begin(), _bytes.end()) {}
+
+ bytes m_ext;
+};
+
+class TrieBranchNode: public MemTrieNode
+{
+public:
+ TrieBranchNode(std::string const& _value): m_value(_value)
+ {
+ memset(m_nodes.data(), 0, sizeof(MemTrieNode*) * 16);
+ }
+
+ TrieBranchNode(byte _i1, MemTrieNode* _n1, std::string const& _value = std::string()): m_value(_value)
+ {
+ memset(m_nodes.data(), 0, sizeof(MemTrieNode*) * 16);
+ m_nodes[_i1] = _n1;
+ }
+
+ TrieBranchNode(byte _i1, MemTrieNode* _n1, byte _i2, MemTrieNode* _n2)
+ {
+ memset(m_nodes.data(), 0, sizeof(MemTrieNode*) * 16);
+ m_nodes[_i1] = _n1;
+ m_nodes[_i2] = _n2;
+ }
+
+ virtual ~TrieBranchNode()
+ {
+ for (auto i: m_nodes)
+ delete i;
+ }
+
+#if ENABLE_DEBUG_PRINT
+ virtual void debugPrintBody(std::string const& _indent) const
+ {
+
+ if (m_value.size())
+ std::cerr << _indent << "@: " << m_value << std::endl;
+ for (auto i = 0; i < 16; ++i)
+ if (m_nodes[i])
+ {
+ std::cerr << _indent << std::hex << i << ": " << std::dec;
+ m_nodes[i]->debugPrint(_indent + " ");
+ }
+ }
+#endif
+
+ virtual std::string const& at(bytesConstRef _key) const override;
+ virtual MemTrieNode* insert(bytesConstRef _key, std::string const& _value) override;
+ virtual MemTrieNode* remove(bytesConstRef _key) override;
+ virtual void makeRLP(RLPStream& _parentStream) const override;
+
+private:
+ /// @returns (byte)-1 when no active branches, 16 when multiple active and the index of the active branch otherwise.
+ byte activeBranch() const;
+
+ MemTrieNode* rejig();
+
+ std::array<MemTrieNode*, 16> m_nodes;
+ std::string m_value;
+};
+
+class TrieLeafNode: public TrieExtNode
+{
+public:
+ TrieLeafNode(bytesConstRef _key, std::string const& _value): TrieExtNode(_key), m_value(_value) {}
+
+#if ENABLE_DEBUG_PRINT
+ virtual void debugPrintBody(std::string const& _indent) const
+ {
+ assert(m_value.size());
+ std::cerr << _indent;
+ if (m_ext.size())
+ std::cerr << toHex(m_ext, 1) << ": ";
+ else
+ std::cerr << "@: ";
+ std::cerr << m_value << std::endl;
+ }
+#endif
+
+ virtual std::string const& at(bytesConstRef _key) const override { return contains(_key) ? m_value : c_nullString; }
+ virtual MemTrieNode* insert(bytesConstRef _key, std::string const& _value) override;
+ virtual MemTrieNode* remove(bytesConstRef _key) override;
+ virtual void makeRLP(RLPStream& _parentStream) const override;
+
+private:
+ bool contains(bytesConstRef _key) const { return _key.size() == m_ext.size() && !memcmp(_key.data(), m_ext.data(), _key.size()); }
+
+ std::string m_value;
+};
+
+class TrieInfixNode: public TrieExtNode
+{
+public:
+ TrieInfixNode(bytesConstRef _key, MemTrieNode* _next): TrieExtNode(_key), m_next(_next) {}
+ virtual ~TrieInfixNode() { delete m_next; }
+
+#if ENABLE_DEBUG_PRINT
+ virtual void debugPrintBody(std::string const& _indent) const
+ {
+ std::cerr << _indent << toHex(m_ext, 1) << ": ";
+ m_next->debugPrint(_indent + " ");
+ }
+#endif
+
+ virtual std::string const& at(bytesConstRef _key) const override { assert(m_next); return contains(_key) ? m_next->at(_key.cropped(m_ext.size())) : c_nullString; }
+ virtual MemTrieNode* insert(bytesConstRef _key, std::string const& _value) override;
+ virtual MemTrieNode* remove(bytesConstRef _key) override;
+ virtual void makeRLP(RLPStream& _parentStream) const override;
+
+private:
+ bool contains(bytesConstRef _key) const { return _key.size() >= m_ext.size() && !memcmp(_key.data(), m_ext.data(), m_ext.size()); }
+
+ MemTrieNode* m_next;
+};
+
+void MemTrieNode::putRLP(RLPStream& _parentStream) const
+{
+ RLPStream s;
+ makeRLP(s);
+ if (s.out().size() < 32)
+ _parentStream.APPEND_CHILD(s.out());
+ else
+ _parentStream << eth::sha3(s.out());
+}
+
+void TrieBranchNode::makeRLP(RLPStream& _intoStream) const
+{
+ _intoStream.appendList(17);
+ for (auto i: m_nodes)
+ if (i)
+ i->putRLP(_intoStream);
+ else
+ _intoStream << "";
+ _intoStream << m_value;
+}
+
+void TrieLeafNode::makeRLP(RLPStream& _intoStream) const
+{
+ _intoStream.appendList(2) << hexPrefixEncode(m_ext, true) << m_value;
+}
+
+void TrieInfixNode::makeRLP(RLPStream& _intoStream) const
+{
+ assert(m_next);
+ _intoStream.appendList(2);
+ _intoStream << hexPrefixEncode(m_ext, false);
+ m_next->putRLP(_intoStream);
+}
+
+MemTrieNode* MemTrieNode::newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2)
+{
+ uint prefix = commonPrefix(_k1, _k2);
+
+ MemTrieNode* ret;
+ if (_k1.size() == prefix)
+ ret = new TrieBranchNode(_k2[prefix], new TrieLeafNode(_k2.cropped(prefix + 1), _v2), _v1);
+ else if (_k2.size() == prefix)
+ ret = new TrieBranchNode(_k1[prefix], new TrieLeafNode(_k1.cropped(prefix + 1), _v1), _v2);
+ else // both continue after split
+ ret = new TrieBranchNode(_k1[prefix], new TrieLeafNode(_k1.cropped(prefix + 1), _v1), _k2[prefix], new TrieLeafNode(_k2.cropped(prefix + 1), _v2));
+
+ if (prefix)
+ // have shared prefix - split.
+ ret = new TrieInfixNode(_k1.cropped(0, prefix), ret);
+
+ return ret;
+}
+
+std::string const& TrieBranchNode::at(bytesConstRef _key) const
+{
+ if (_key.empty())
+ return m_value;
+ else if (m_nodes[_key[0]] != nullptr)
+ return m_nodes[_key[0]]->at(_key.cropped(1));
+ return c_nullString;
+}
+
+MemTrieNode* TrieBranchNode::insert(bytesConstRef _key, std::string const& _value)
+{
+ assert(_value.size());
+ mark();
+ if (_key.empty())
+ m_value = _value;
+ else
+ if (!m_nodes[_key[0]])
+ m_nodes[_key[0]] = new TrieLeafNode(_key.cropped(1), _value);
+ else
+ m_nodes[_key[0]] = m_nodes[_key[0]]->insert(_key.cropped(1), _value);
+ return this;
+}
+
+MemTrieNode* TrieBranchNode::remove(bytesConstRef _key)
+{
+ if (_key.empty())
+ if (m_value.size())
+ {
+ m_value.clear();
+ return rejig();
+ }
+ else {}
+ else if (m_nodes[_key[0]] != nullptr)
+ {
+ m_nodes[_key[0]] = m_nodes[_key[0]]->remove(_key.cropped(1));
+ return rejig();
+ }
+ return this;
+}
+
+MemTrieNode* TrieBranchNode::rejig()
+{
+ mark();
+ byte n = activeBranch();
+
+ if (n == (byte)-1 && m_value.size())
+ {
+ // switch to leaf
+ auto r = new TrieLeafNode(bytesConstRef(), m_value);
+ delete this;
+ return r;
+ }
+ else if (n < 16 && m_value.empty())
+ {
+ // only branching to n...
+ if (auto b = dynamic_cast<TrieBranchNode*>(m_nodes[n]))
+ {
+ // switch to infix
+ m_nodes[n] = nullptr;
+ delete this;
+ return new TrieInfixNode(bytesConstRef(&n, 1), b);
+ }
+ else
+ {
+ auto x = dynamic_cast<TrieExtNode*>(m_nodes[n]);
+ assert(x);
+ // include in child
+ pushFront(x->m_ext, n);
+ m_nodes[n] = nullptr;
+ delete this;
+ return x;
+ }
+ }
+
+ return this;
+}
+
+byte TrieBranchNode::activeBranch() const
+{
+ byte n = (byte)-1;
+ for (int i = 0; i < 16; ++i)
+ if (m_nodes[i] != nullptr)
+ {
+ if (n == (byte)-1)
+ n = (byte)i;
+ else
+ return 16;
+ }
+ return n;
+}
+
+MemTrieNode* TrieInfixNode::insert(bytesConstRef _key, std::string const& _value)
+{
+ assert(_value.size());
+ mark();
+ if (contains(_key))
+ {
+ m_next = m_next->insert(_key.cropped(m_ext.size()), _value);
+ return this;
+ }
+ else
+ {
+ uint prefix = commonPrefix(_key, m_ext);
+ if (prefix)
+ {
+ // one infix becomes two infixes, then insert into the second
+ // instead of pop_front()...
+ trimFront(m_ext, prefix);
+
+ return new TrieInfixNode(_key.cropped(0, prefix), insert(_key.cropped(prefix), _value));
+ }
+ else
+ {
+ // split here.
+ auto f = m_ext[0];
+ trimFront(m_ext, 1);
+ MemTrieNode* n = m_ext.empty() ? m_next : this;
+ if (n != this)
+ {
+ m_next = nullptr;
+ delete this;
+ }
+ TrieBranchNode* ret = new TrieBranchNode(f, n);
+ ret->insert(_key, _value);
+ return ret;
+ }
+ }
+}
+
+MemTrieNode* TrieInfixNode::remove(bytesConstRef _key)
+{
+ if (contains(_key))
+ {
+ mark();
+ m_next = m_next->remove(_key.cropped(m_ext.size()));
+ if (auto p = dynamic_cast<TrieExtNode*>(m_next))
+ {
+ // merge with child...
+ m_ext.reserve(m_ext.size() + p->m_ext.size());
+ for (auto i: p->m_ext)
+ m_ext.push_back(i);
+ p->m_ext = m_ext;
+ p->mark();
+ m_next = nullptr;
+ delete this;
+ return p;
+ }
+ if (!m_next)
+ {
+ delete this;
+ return nullptr;
+ }
+ }
+ return this;
+}
+
+MemTrieNode* TrieLeafNode::insert(bytesConstRef _key, std::string const& _value)
+{
+ assert(_value.size());
+ mark();
+ if (contains(_key))
+ {
+ m_value = _value;
+ return this;
+ }
+ else
+ {
+ // create new trie.
+ auto n = MemTrieNode::newBranch(_key, _value, bytesConstRef(&m_ext), m_value);
+ delete this;
+ return n;
+ }
+}
+
+MemTrieNode* TrieLeafNode::remove(bytesConstRef _key)
+{
+ if (contains(_key))
+ {
+ delete this;
+ return nullptr;
+ }
+ return this;
+}
+
+MemTrie::~MemTrie()
+{
+ delete m_root;
+}
+
+h256 MemTrie::hash256() const
+{
+ return m_root ? m_root->hash256() : h256();
+}
+
+bytes MemTrie::rlp() const
+{
+ return m_root ? m_root->rlp() : bytes();
+}
+
+void MemTrie::debugPrint()
+{
+#if ENABLE_DEBUG_PRINT
+ if (m_root)
+ m_root->debugPrint();
+#endif
+}
+
+std::string const& MemTrie::at(std::string const& _key) const
+{
+ if (!m_root)
+ return c_nullString;
+ auto h = asNibbles(_key);
+ return m_root->at(bytesConstRef(&h));
+}
+
+void MemTrie::insert(std::string const& _key, std::string const& _value)
+{
+ if (_value.empty())
+ remove(_key);
+ auto h = asNibbles(_key);
+ m_root = m_root ? m_root->insert(&h, _value) : new TrieLeafNode(bytesConstRef(&h), _value);
+}
+
+void MemTrie::remove(std::string const& _key)
+{
+ if (m_root)
+ {
+ auto h = asNibbles(_key);
+ m_root = m_root->remove(&h);
+ }
+}
+
+}
diff --git a/MemTrie.h b/MemTrie.h
new file mode 100644
index 00000000..622ea531
--- /dev/null
+++ b/MemTrie.h
@@ -0,0 +1,54 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file MemTrie.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#pragma once
+
+#include <Common.h>
+#include <FixedHash.h>
+
+namespace eth
+{
+
+class MemTrieNode;
+
+/**
+ * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree.
+ */
+class MemTrie
+{
+public:
+ MemTrie(): m_root(nullptr) {}
+ ~MemTrie();
+
+ h256 hash256() const;
+ bytes rlp() const;
+
+ void debugPrint();
+
+ std::string const& at(std::string const& _key) const;
+ void insert(std::string const& _key, std::string const& _value);
+ void remove(std::string const& _key);
+
+private:
+ MemTrieNode* m_root;
+};
+
+}
diff --git a/TrieHash.cpp b/TrieHash.cpp
new file mode 100644
index 00000000..61840b0e
--- /dev/null
+++ b/TrieHash.cpp
@@ -0,0 +1,198 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file TrieHash.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "TrieHash.h"
+
+#include <CommonEth.h>
+#include <TrieCommon.h>
+using namespace std;
+using namespace eth;
+
+namespace eth
+{
+
+/*/
+#define APPEND_CHILD appendData
+/*/
+#define APPEND_CHILD appendRaw
+/**/
+
+#define ENABLE_DEBUG_PRINT 0
+
+#if ENABLE_DEBUG_PRINT
+bool g_hashDebug = false;
+#endif
+
+void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp);
+
+void hash256rlp(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
+{
+#if ENABLE_DEBUG_PRINT
+ static std::string s_indent;
+ if (_preLen)
+ s_indent += " ";
+#endif
+
+ if (_begin == _end)
+ _rlp << ""; // NULL
+ else if (std::next(_begin) == _end)
+ {
+ // only one left - terminate with the pair.
+ _rlp.appendList(2) << hexPrefixEncode(_begin->first, true, _preLen) << _begin->second;
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, _begin->first.size() - _preLen), 1) << ": " << _begin->second << " = " << sha3(_rlp.out()) << std::endl;
+#endif
+ }
+ else
+ {
+ // find the number of common prefix nibbles shared
+ // i.e. the minimum number of nibbles shared at the beginning between the first hex string and each successive.
+ uint sharedPre = (uint)-1;
+ uint c = 0;
+ for (auto i = std::next(_begin); i != _end && sharedPre; ++i, ++c)
+ {
+ uint x = std::min(sharedPre, std::min((uint)_begin->first.size(), (uint)i->first.size()));
+ uint shared = _preLen;
+ for (; shared < x && _begin->first[shared] == i->first[shared]; ++shared) {}
+ sharedPre = std::min(shared, sharedPre);
+ }
+ if (sharedPre > _preLen)
+ {
+ // if they all have the same next nibble, we also want a pair.
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << toHex(bytesConstRef(_begin->first.data() + _preLen, sharedPre), 1) << ": " << std::endl;
+#endif
+ _rlp.appendList(2) << hexPrefixEncode(_begin->first, false, _preLen, (int)sharedPre);
+ hash256aux(_s, _begin, _end, (unsigned)sharedPre, _rlp);
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl;
+#endif
+ }
+ else
+ {
+ // otherwise enumerate all 16+1 entries.
+ _rlp.appendList(17);
+ auto b = _begin;
+ if (_preLen == b->first.size())
+ {
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << "@: " << b->second << std::endl;
+#endif
+ ++b;
+ }
+ for (auto i = 0; i < 16; ++i)
+ {
+ auto n = b;
+ for (; n != _end && n->first[_preLen] == i; ++n) {}
+ if (b == n)
+ _rlp << "";
+ else
+ {
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << std::hex << i << ": " << std::dec << std::endl;
+#endif
+ hash256aux(_s, b, n, _preLen + 1, _rlp);
+ }
+ b = n;
+ }
+ if (_preLen == _begin->first.size())
+ _rlp << _begin->second;
+ else
+ _rlp << "";
+
+#if ENABLE_DEBUG_PRINT
+ if (g_hashDebug)
+ std::cerr << s_indent << "= " << hex << sha3(_rlp.out()) << dec << std::endl;
+#endif
+ }
+ }
+#if ENABLE_DEBUG_PRINT
+ if (_preLen)
+ s_indent.resize(s_indent.size() - 2);
+#endif
+}
+
+void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_iterator _end, unsigned _preLen, RLPStream& _rlp)
+{
+ RLPStream rlp;
+ hash256rlp(_s, _begin, _end, _preLen, rlp);
+ if (rlp.out().size() < 32)
+ {
+ // RECURSIVE RLP
+#if ENABLE_DEBUG_PRINT
+ cerr << "[INLINE: " << dec << rlp.out().size() << " < 32]" << endl;
+#endif
+ _rlp.APPEND_CHILD(rlp.out());
+ }
+ else
+ {
+#if ENABLE_DEBUG_PRINT
+ cerr << "[HASH: " << dec << rlp.out().size() << " >= 32]" << endl;
+#endif
+ _rlp << sha3(rlp.out());
+ }
+}
+
+h256 hash256(StringMap const& _s)
+{
+ // build patricia tree.
+ if (_s.empty())
+ return h256();
+ HexMap hexMap;
+ for (auto i = _s.rbegin(); i != _s.rend(); ++i)
+ hexMap[asNibbles(i->first)] = i->second;
+ RLPStream s;
+ hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
+ return sha3(s.out());
+}
+
+bytes rlp256(StringMap const& _s)
+{
+ // build patricia tree.
+ if (_s.empty())
+ return bytes();
+ HexMap hexMap;
+ for (auto i = _s.rbegin(); i != _s.rend(); ++i)
+ hexMap[asNibbles(i->first)] = i->second;
+ RLPStream s;
+ hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
+ return s.out();
+}
+
+h256 hash256(u256Map const& _s)
+{
+ // build patricia tree.
+ if (_s.empty())
+ return h256();
+ HexMap hexMap;
+ for (auto i = _s.rbegin(); i != _s.rend(); ++i)
+ hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second));
+ RLPStream s;
+ hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s);
+ return sha3(s.out());
+}
+
+}
diff --git a/TrieHash.h b/TrieHash.h
new file mode 100644
index 00000000..e69b2b7b
--- /dev/null
+++ b/TrieHash.h
@@ -0,0 +1,34 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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.
+
+ cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file TrieHash.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#pragma once
+
+#include <Common.h>
+#include <FixedHash.h>
+
+namespace eth
+{
+
+bytes rlp256(StringMap const& _s);
+h256 hash256(StringMap const& _s);
+h256 hash256(u256Map const& _s);
+
+}
diff --git a/trie.cpp b/trie.cpp
index 419602d6..9d2bb376 100644
--- a/trie.cpp
+++ b/trie.cpp
@@ -24,9 +24,9 @@
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include <random>
-#include <TrieHash.h>
#include <TrieDB.h>
-#include <MemTrie.h>
+#include "TrieHash.h"
+#include "MemTrie.h"
using namespace std;
using namespace eth;