diff --git a/configure.ac b/configure.ac
index 45e5b4fe4ea3315e49033cdbc5b4fd0520f94400..16f2bf429572cb9faaba7cfa01cc5a3371f8d2ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -632,6 +632,8 @@ AC_CONFIG_FILES([Makefile \
                  src/sip/Makefile \
                  src/im/Makefile \
                  src/ringdht/Makefile \
+                 src/ringdht/eth/libdevcore/Makefile \
+                 src/ringdht/eth/libdevcrypto/Makefile \
                  src/media/Makefile \
                  src/media/audio/Makefile \
                  src/media/audio/pulseaudio/Makefile \
diff --git a/src/ringdht/Makefile.am b/src/ringdht/Makefile.am
index 1b9219f452758236b474502e1e3a2f855d9e8079..4654df9a7379c1c95ef190c6c99d9d97d2e9f0ed 100644
--- a/src/ringdht/Makefile.am
+++ b/src/ringdht/Makefile.am
@@ -1,9 +1,21 @@
 include $(top_srcdir)/globals.mak
 
+SUBDIRS = eth/libdevcore eth/libdevcrypto
+
+AM_CPPFLAGS += -I$(top_srcdir)/src/ringdht/eth $(BOOST_CPPFLAGS)
 noinst_LTLIBRARIES = libringacc.la
-libringacc_la_CXXFLAGS = @CXXFLAGS@
 
-libringacc_la_LIBADD = $(DHT_LIBS)
+AM_LDFLAGS = $(BOOST_LDFLAGS)
+
+libringacc_la_CXXFLAGS = @CXXFLAGS@ @JSONCPP_CFLAGS@
+
+libringacc_la_LIBADD = $(DHT_LIBS) \
+    $(BOOST_SYSTEM_LIB) \
+    $(BOOST_FILESYSTEM_LIB) \
+    $(BOOST_RANDOM_LIB) \
+    $(BOOST_THREAD_LIB) \
+    ./eth/libdevcore/libdevcore.la \
+    ./eth/libdevcrypto/libdevcrypto.la
 
 libringacc_la_SOURCES = \
         ringaccount.cpp \
diff --git a/src/ringdht/eth/libdevcore/Common.cpp b/src/ringdht/eth/libdevcore/Common.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..22c60e44c10081c256700b97745167c0208d9cdd
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Common.cpp
@@ -0,0 +1,93 @@
+/*
+	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 Common.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "Common.h"
+#include "Exceptions.h"
+using namespace std;
+using namespace dev;
+
+namespace dev
+{
+
+char const* Version = "1.2.4";
+
+const u256 Invalid256 = ~(u256)0;
+
+void InvariantChecker::checkInvariants(HasInvariants const* _this, char const* _fn, char const* _file, int _line, bool _pre)
+{
+	if (!_this->invariants())
+	{
+		::boost::exception_detail::throw_exception_(FailedInvariant(), _fn, _file, _line);
+	}
+}
+
+TimerHelper::~TimerHelper()
+{
+}
+
+uint64_t utcTime()
+{
+	// TODO: Fix if possible to not use time(0) and merge only after testing in all platforms
+	// time_t t = time(0);
+	// return mktime(gmtime(&t));
+	return time(0);
+}
+
+string inUnits(bigint const& _b, strings const& _units)
+{
+	ostringstream ret;
+	u256 b;
+	if (_b < 0)
+	{
+		ret << "-";
+		b = (u256)-_b;
+	}
+	else
+		b = (u256)_b;
+
+	u256 biggest = 1;
+	for (unsigned i = _units.size() - 1; !!i; --i)
+		biggest *= 1000;
+
+	if (b > biggest * 1000)
+	{
+		ret << (b / biggest) << " " << _units.back();
+		return ret.str();
+	}
+	ret << setprecision(3);
+
+	u256 unit = biggest;
+	for (auto it = _units.rbegin(); it != _units.rend(); ++it)
+	{
+		auto i = *it;
+		if (i != _units.front() && b >= unit)
+		{
+			ret << (double(b / (unit / 1000)) / 1000.0) << " " << i;
+			return ret.str();
+		}
+		else
+			unit /= 1000;
+	}
+	ret << b << " " << _units.front();
+	return ret.str();
+}
+
+}
diff --git a/src/ringdht/eth/libdevcore/Common.h b/src/ringdht/eth/libdevcore/Common.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf8cf4535d38c477f4af082c74abd401df76e12c
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Common.h
@@ -0,0 +1,334 @@
+/*
+	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 Common.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * Very common stuff (i.e. that every other header needs except vector_ref.h).
+ */
+
+#pragma once
+
+// way to many unsigned to size_t warnings in 32 bit build
+#ifdef _M_IX86
+#pragma warning(disable:4244)
+#endif
+
+#if _MSC_VER && _MSC_VER < 1900
+#define _ALLOW_KEYWORD_MACROS
+#define noexcept throw()
+#endif
+
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:3682) //call through incomplete class
+#endif
+
+#include <map>
+#include <unordered_map>
+#include <vector>
+#include <set>
+#include <unordered_set>
+#include <functional>
+#include <string>
+#include <chrono>
+#pragma warning(push)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <boost/version.hpp>
+#if (BOOST_VERSION == 105800)
+	#include "boost_multiprecision_number_compare_bug_workaround.hpp"
+#endif
+#include <boost/multiprecision/cpp_int.hpp>
+#pragma warning(pop)
+#pragma GCC diagnostic pop
+#include "vector_ref.h"
+
+// CryptoPP defines byte in the global namespace, so must we.
+using byte = uint8_t;
+
+// Quote a given token stream to turn it into a string.
+#define DEV_QUOTED_HELPER(s) #s
+#define DEV_QUOTED(s) DEV_QUOTED_HELPER(s)
+
+#define DEV_IGNORE_EXCEPTIONS(X) try { X; } catch (...) {}
+
+#define DEV_IF_NO_ELSE(X) if(!(X)){}else
+#define DEV_IF_THROWS(X) try{X;}catch(...)
+
+namespace dev
+{
+
+extern char const* Version;
+
+static const std::string EmptyString;
+
+// Binary data types.
+using bytes = std::vector<byte>;
+using bytesRef = vector_ref<byte>;
+using bytesConstRef = vector_ref<byte const>;
+
+template <class T>
+class secure_vector
+{
+public:
+	secure_vector() {}
+	secure_vector(secure_vector<T> const& /*_c*/) = default;  // See https://github.com/ethereum/libweb3core/pull/44
+	explicit secure_vector(unsigned _size): m_data(_size) {}
+	explicit secure_vector(unsigned _size, T _item): m_data(_size, _item) {}
+	explicit secure_vector(std::vector<T> const& _c): m_data(_c) {}
+	explicit secure_vector(vector_ref<T> _c): m_data(_c.data(), _c.data() + _c.size()) {}
+	explicit secure_vector(vector_ref<const T> _c): m_data(_c.data(), _c.data() + _c.size()) {}
+	~secure_vector() { ref().cleanse(); }
+
+	secure_vector<T>& operator=(secure_vector<T> const& _c)
+	{
+		if (&_c == this)
+			return *this;
+
+		ref().cleanse();
+		m_data = _c.m_data;
+		return *this;
+	}
+	std::vector<T>& writable() { clear(); return m_data; }
+	std::vector<T> const& makeInsecure() const { return m_data; }
+
+	void clear() { ref().cleanse(); }
+
+	vector_ref<T> ref() { return vector_ref<T>(&m_data); }
+	vector_ref<T const> ref() const { return vector_ref<T const>(&m_data); }
+
+	size_t size() const { return m_data.size(); }
+	bool empty() const { return m_data.empty(); }
+
+	void swap(secure_vector<T>& io_other) { m_data.swap(io_other.m_data); }
+
+private:
+	std::vector<T> m_data;
+};
+
+using bytesSec = secure_vector<byte>;
+
+// Numeric types.
+using bigint = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>;
+using u64 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+using u128 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<128, 128, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+using u256 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+using s256 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<256, 256, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void>>;
+using u160 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<160, 160, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+using s160 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<160, 160, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void>>;
+using u512 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 512, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+using s512 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 512, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void>>;
+using u256s = std::vector<u256>;
+using u160s = std::vector<u160>;
+using u256Set = std::set<u256>;
+using u160Set = std::set<u160>;
+
+// Map types.
+using StringMap = std::map<std::string, std::string>;
+using BytesMap = std::map<bytes, bytes>;
+using u256Map = std::map<u256, u256>;
+using HexMap = std::map<bytes, bytes>;
+
+// Hash types.
+using StringHashMap = std::unordered_map<std::string, std::string>;
+using u256HashMap = std::unordered_map<u256, u256>;
+
+// String types.
+using strings = std::vector<std::string>;
+
+// Fixed-length string types.
+using string32 = std::array<char, 32>;
+static const string32 ZeroString32 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
+
+// Null/Invalid values for convenience.
+static const bytes NullBytes;
+static const std::map<u256, u256> EmptyMapU256U256;
+extern const u256 Invalid256;
+
+/// Interprets @a _u as a two's complement signed number and returns the resulting s256.
+inline s256 u2s(u256 _u)
+{
+	static const bigint c_end = bigint(1) << 256;
+	if (boost::multiprecision::bit_test(_u, 255))
+		return s256(-(c_end - _u));
+	else
+		return s256(_u);
+}
+
+/// @returns the two's complement signed representation of the signed number _u.
+inline u256 s2u(s256 _u)
+{
+	static const bigint c_end = bigint(1) << 256;
+    if (_u >= 0)
+		return u256(_u);
+    else
+		return u256(c_end + _u);
+}
+
+/// Converts given int to a string and appends one of a series of units according to its size.
+std::string inUnits(bigint const& _b, strings const& _units);
+
+/// @returns the smallest n >= 0 such that (1 << n) >= _x
+inline unsigned int toLog2(u256 _x)
+{
+	unsigned ret;
+	for (ret = 0; _x >>= 1; ++ret) {}
+	return ret;
+}
+
+template <size_t n> inline u256 exp10()
+{
+	return exp10<n - 1>() * u256(10);
+}
+
+template <> inline u256 exp10<0>()
+{
+	return u256(1);
+}
+
+/// @returns the absolute distance between _a and _b.
+template <class N>
+inline N diff(N const& _a, N const& _b)
+{
+	return std::max(_a, _b) - std::min(_a, _b);
+}
+
+/// RAII utility class whose destructor calls a given function.
+class ScopeGuard
+{
+public:
+	ScopeGuard(std::function<void(void)> _f): m_f(_f) {}
+	~ScopeGuard() { m_f(); }
+
+private:
+	std::function<void(void)> m_f;
+};
+
+/// Inheritable for classes that have invariants.
+class HasInvariants
+{
+public:
+	/// Reimplement to specify the invariants.
+	virtual bool invariants() const = 0;
+};
+
+/// RAII checker for invariant assertions.
+class InvariantChecker
+{
+public:
+	InvariantChecker(HasInvariants* _this, char const* _fn, char const* _file, int _line): m_this(_this), m_function(_fn), m_file(_file), m_line(_line) { checkInvariants(_this, _fn , _file, _line, true); }
+	~InvariantChecker() { checkInvariants(m_this, m_function, m_file, m_line, false); }
+	/// Check invariants are met, throw if not.
+	static void checkInvariants(HasInvariants const* _this, char const* _fn, char const* _file, int line, bool _pre);
+
+private:
+	HasInvariants const* m_this;
+	char const* m_function;
+	char const* m_file;
+	int m_line;
+};
+
+/// Scope guard for invariant check in a class derived from HasInvariants.
+#if ETH_DEBUG
+#define DEV_INVARIANT_CHECK ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)
+#define DEV_INVARIANT_CHECK_HERE ::dev::InvariantChecker::checkInvariants(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true)
+#else
+#define DEV_INVARIANT_CHECK (void)0;
+#define DEV_INVARIANT_CHECK_HERE (void)0;
+#endif
+
+/// Simple scope-based timer helper.
+class TimerHelper
+{
+public:
+	TimerHelper(std::string const& _id, unsigned _msReportWhenGreater = 0): m_t(std::chrono::high_resolution_clock::now()), m_id(_id), m_ms(_msReportWhenGreater) {}
+	~TimerHelper();
+
+private:
+	std::chrono::high_resolution_clock::time_point m_t;
+	std::string m_id;
+	unsigned m_ms;
+};
+
+class Timer
+{
+public:
+	Timer() { restart(); }
+
+	std::chrono::high_resolution_clock::duration duration() const { return std::chrono::high_resolution_clock::now() - m_t; }
+	double elapsed() const { return std::chrono::duration_cast<std::chrono::microseconds>(duration()).count() / 1000000.0; }
+	void restart() { m_t = std::chrono::high_resolution_clock::now(); }
+
+private:
+	std::chrono::high_resolution_clock::time_point m_t;
+};
+
+#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(S, true); __eth_t.second; __eth_t.second = false)
+#define DEV_TIMED_SCOPE(S) ::dev::TimerHelper __eth_t(S)
+#if defined(_WIN32)
+#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__FUNCSIG__)
+#else
+#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__)
+#endif
+
+#define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(S, MS), true); __eth_t.second; __eth_t.second = false)
+#define DEV_TIMED_SCOPE_ABOVE(S, MS) ::dev::TimerHelper __eth_t(S, MS)
+#if defined(_WIN32)
+#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS)
+#else
+#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__PRETTY_FUNCTION__, MS)
+#endif
+
+#ifdef _MSC_VER
+// TODO.
+#define DEV_UNUSED
+#else
+#define DEV_UNUSED __attribute__((unused))
+#endif
+
+enum class WithExisting: int
+{
+	Trust = 0,
+	Verify,
+	Rescue,
+	Kill
+};
+
+/// Get the current time in seconds since the epoch in UTC
+uint64_t utcTime();
+
+}
+
+namespace std
+{
+
+inline dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b)
+{
+	return static_cast<dev::WithExisting>(max(static_cast<int>(_a), static_cast<int>(_b)));
+}
+
+template <> struct hash<dev::u256>
+{
+	size_t operator()(dev::u256 const& _a) const
+	{
+		unsigned size = _a.backend().size();
+		auto limbs = _a.backend().limbs();
+		return boost::hash_range(limbs, limbs + size);
+	}
+};
+
+}
diff --git a/src/ringdht/eth/libdevcore/CommonData.cpp b/src/ringdht/eth/libdevcore/CommonData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..372f299ae56752c041a7c950e65c45626ea68b59
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/CommonData.cpp
@@ -0,0 +1,147 @@
+/*
+	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 CommonData.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "CommonData.h"
+#include <random>
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4724) // potential mod by 0, line 78 of boost/random/uniform_int_distribution.hpp (boost 1.55)
+#endif
+#include <boost/random/uniform_int_distribution.hpp>
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+#include "Exceptions.h"
+using namespace std;
+using namespace dev;
+
+bool dev::isHex(string const& _s)
+{
+	unsigned i = (_s.size() >= 2 && _s.substr(0, 2) == "0x") ? 2 : 0;
+	for (; i < _s.size(); ++i)
+		if (fromHex(_s[i], WhenError::DontThrow) == -1)
+			return false;
+	return true;
+}
+
+std::string dev::escaped(std::string const& _s, bool _all)
+{
+	static const map<char, char> prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}};
+	std::string ret;
+	ret.reserve(_s.size() + 2);
+	ret.push_back('"');
+	for (auto i: _s)
+		if (i == '"' && !_all)
+			ret += "\\\"";
+		else if (i == '\\' && !_all)
+			ret += "\\\\";
+		else if (prettyEscapes.count(i) && !_all)
+		{
+			ret += '\\';
+			ret += prettyEscapes.find(i)->second;
+		}
+		else if (i < ' ' || _all)
+		{
+			ret += "\\x";
+			ret.push_back("0123456789abcdef"[(uint8_t)i / 16]);
+			ret.push_back("0123456789abcdef"[(uint8_t)i % 16]);
+		}
+		else
+			ret.push_back(i);
+	ret.push_back('"');
+	return ret;
+}
+
+std::string dev::randomWord()
+{
+	static std::mt19937_64 s_eng(0);
+	std::string ret(boost::random::uniform_int_distribution<int>(1, 5)(s_eng), ' ');
+	char const n[] = "qwertyuiop";//asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
+	boost::random::uniform_int_distribution<int> d(0, sizeof(n) - 2);
+	for (char& c: ret)
+		c = n[d(s_eng)];
+	return ret;
+}
+
+int dev::fromHex(char _i, WhenError _throw)
+{
+	if (_i >= '0' && _i <= '9')
+		return _i - '0';
+	if (_i >= 'a' && _i <= 'f')
+		return _i - 'a' + 10;
+	if (_i >= 'A' && _i <= 'F')
+		return _i - 'A' + 10;
+	if (_throw == WhenError::Throw)
+		BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
+	else
+		return -1;
+}
+
+bytes dev::fromHex(std::string const& _s, WhenError _throw)
+{
+	unsigned s = (_s.size() >= 2 && _s[0] == '0' && _s[1] == 'x') ? 2 : 0;
+	std::vector<uint8_t> ret;
+	ret.reserve((_s.size() - s + 1) / 2);
+
+	if (_s.size() % 2)
+	{
+		int h = fromHex(_s[s++], WhenError::DontThrow);
+		if (h != -1)
+			ret.push_back(h);
+		else if (_throw == WhenError::Throw)
+			BOOST_THROW_EXCEPTION(BadHexCharacter());
+		else
+			return bytes();
+	}
+	for (unsigned i = s; i < _s.size(); i += 2)
+	{
+		int h = fromHex(_s[i], WhenError::DontThrow);
+		int l = fromHex(_s[i + 1], WhenError::DontThrow);
+		if (h != -1 && l != -1)
+			ret.push_back((byte)(h * 16 + l));
+		else if (_throw == WhenError::Throw)
+			BOOST_THROW_EXCEPTION(BadHexCharacter());
+		else
+			return bytes();
+	}
+	return ret;
+}
+
+bytes dev::asNibbles(bytesConstRef const& _s)
+{
+	std::vector<uint8_t> ret;
+	ret.reserve(_s.size() * 2);
+	for (auto i: _s)
+	{
+		ret.push_back(i / 16);
+		ret.push_back(i % 16);
+	}
+	return ret;
+}
+
+std::string dev::toString(string32 const& _s)
+{
+	std::string ret;
+	for (unsigned i = 0; i < 32 && _s[i]; ++i)
+		ret.push_back(_s[i]);
+	return ret;
+}
diff --git a/src/ringdht/eth/libdevcore/CommonData.h b/src/ringdht/eth/libdevcore/CommonData.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbd6c06a8c48428ddfe1479b49280f386328dada
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/CommonData.h
@@ -0,0 +1,388 @@
+/*
+	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 CommonData.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * Shared algorithms and data types.
+ */
+
+#pragma once
+
+#include <vector>
+#include <algorithm>
+#include <unordered_set>
+#include <type_traits>
+#include <cstring>
+#include <string>
+#include "Common.h"
+
+namespace dev
+{
+
+// String conversion functions, mainly to/from hex/nibble/byte representations.
+
+enum class WhenError
+{
+	DontThrow = 0,
+	Throw = 1,
+};
+
+enum class HexPrefix
+{
+	DontAdd = 0,
+	Add = 1,
+};
+/// Convert a series of bytes to the corresponding string of hex duplets.
+/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte.
+/// @example toHex("A\x69") == "4169"
+template <class T>
+std::string toHex(T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd)
+{
+	std::ostringstream ret;
+	unsigned ii = 0;
+	for (auto i: _data)
+		ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
+	return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
+}
+
+/// Converts a (printable) ASCII hex character into the correspnding integer value.
+/// @example fromHex('A') == 10 && fromHex('f') == 15 && fromHex('5') == 5
+int fromHex(char _i, WhenError _throw);
+
+/// Converts a (printable) ASCII hex string into the corresponding byte stream.
+/// @example fromHex("41626261") == asBytes("Abba")
+/// If _throw = ThrowType::DontThrow, it replaces bad hex characters with 0's, otherwise it will throw an exception.
+bytes fromHex(std::string const& _s, WhenError _throw = WhenError::DontThrow);
+
+/// @returns true if @a _s is a hex string.
+bool isHex(std::string const& _s);
+
+/// @returns true if @a _hash is a hash conforming to FixedHash type @a T.
+template <class T> static bool isHash(std::string const& _hash)
+{
+	return (_hash.size() == T::size * 2 || (_hash.size() == T::size * 2 + 2 && _hash.substr(0, 2) == "0x")) && isHex(_hash);
+}
+
+/// Converts byte array to a string containing the same (binary) data. Unless
+/// the byte array happens to contain ASCII data, this won't be printable.
+inline std::string asString(bytes const& _b)
+{
+	return std::string((char const*)_b.data(), (char const*)(_b.data() + _b.size()));
+}
+
+/// Converts byte array ref to a string containing the same (binary) data. Unless
+/// the byte array happens to contain ASCII data, this won't be printable.
+inline std::string asString(bytesConstRef _b)
+{
+	return std::string((char const*)_b.data(), (char const*)(_b.data() + _b.size()));
+}
+
+/// Converts a string to a byte array containing the string's (byte) data.
+inline bytes asBytes(std::string const& _b)
+{
+	return bytes((byte const*)_b.data(), (byte const*)(_b.data() + _b.size()));
+}
+
+/// Converts a string into the big-endian base-16 stream of integers (NOT ASCII).
+/// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1
+bytes asNibbles(bytesConstRef const& _s);
+
+
+// Big-endian to/from host endian conversion functions.
+
+/// Converts a templated integer value to the big-endian byte-stream represented on a templated collection.
+/// The size of the collection object will be unchanged. If it is too small, it will not represent the
+/// value properly, if too big then the additional elements will be zeroed out.
+/// @a Out will typically be either std::string or bytes.
+/// @a T will typically by unsigned, u160, u256 or bigint.
+template <class T, class Out>
+inline void toBigEndian(T _val, Out& o_out)
+{
+	static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed, "only unsigned types or bigint supported"); //bigint does not carry sign bit on shift
+	for (auto i = o_out.size(); i != 0; _val >>= 8, i--)
+	{
+		T v = _val & (T)0xff;
+		o_out[i - 1] = (typename Out::value_type)(uint8_t)v;
+	}
+}
+
+/// Converts a big-endian byte-stream represented on a templated collection to a templated integer value.
+/// @a _In will typically be either std::string or bytes.
+/// @a T will typically by unsigned, u160, u256 or bigint.
+template <class T, class _In>
+inline T fromBigEndian(_In const& _bytes)
+{
+	T ret = (T)0;
+	for (auto i: _bytes)
+		ret = (T)((ret << 8) | (byte)(typename std::make_unsigned<typename _In::value_type>::type)i);
+	return ret;
+}
+
+/// Convenience functions for toBigEndian
+inline std::string toBigEndianString(u256 _val) { std::string ret(32, '\0'); toBigEndian(_val, ret); return ret; }
+inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toBigEndian(_val, ret); return ret; }
+inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; }
+inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; }
+
+/// Convenience function for toBigEndian.
+/// @returns a byte array just big enough to represent @a _val.
+template <class T>
+inline bytes toCompactBigEndian(T _val, unsigned _min = 0)
+{
+	static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed, "only unsigned types or bigint supported"); //bigint does not carry sign bit on shift
+	int i = 0;
+	for (T v = _val; v; ++i, v >>= 8) {}
+	bytes ret(std::max<unsigned>(_min, i), 0);
+	toBigEndian(_val, ret);
+	return ret;
+}
+inline bytes toCompactBigEndian(byte _val, unsigned _min = 0)
+{
+	return (_min || _val) ? bytes{ _val } : bytes{};
+}
+
+/// Convenience function for toBigEndian.
+/// @returns a string just big enough to represent @a _val.
+template <class T>
+inline std::string toCompactBigEndianString(T _val, unsigned _min = 0)
+{
+	static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed, "only unsigned types or bigint supported"); //bigint does not carry sign bit on shift
+	int i = 0;
+	for (T v = _val; v; ++i, v >>= 8) {}
+	std::string ret(std::max<unsigned>(_min, i), '\0');
+	toBigEndian(_val, ret);
+	return ret;
+}
+
+/// Convenience function for conversion of a u256 to hex
+inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
+{
+	std::string str = toHex(toBigEndian(val));
+	return (prefix == HexPrefix::Add) ? "0x" + str : str;
+}
+
+inline std::string toCompactHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd, unsigned _min = 0)
+{
+	std::string str = toHex(toCompactBigEndian(val, _min));
+	return (prefix == HexPrefix::Add) ? "0x" + str : str;
+}
+
+// Algorithms for string and string-like collections.
+
+/// Escapes a string into the C-string representation.
+/// @p _all if true will escape all characters, not just the unprintable ones.
+std::string escaped(std::string const& _s, bool _all = true);
+
+/// Determines the length of the common prefix of the two collections given.
+/// @returns the number of elements both @a _t and @a _u share, in order, at the beginning.
+/// @example commonPrefix("Hello world!", "Hello, world!") == 5
+template <class T, class U>
+unsigned commonPrefix(T const& _t, U const& _u)
+{
+	unsigned s = std::min<unsigned>(_t.size(), _u.size());
+	for (unsigned i = 0;; ++i)
+		if (i == s || _t[i] != _u[i])
+			return i;
+	return s;
+}
+
+/// Creates a random, printable, word.
+std::string randomWord();
+
+/// Determine bytes required to encode the given integer value. @returns 0 if @a _i is zero.
+template <class T>
+inline unsigned bytesRequired(T _i)
+{
+	static_assert(std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed, "only unsigned types or bigint supported"); //bigint does not carry sign bit on shift
+	unsigned i = 0;
+	for (; _i != 0; ++i, _i >>= 8) {}
+	return i;
+}
+
+/// Trims a given number of elements from the front of a collection.
+/// Only works for POD element types.
+template <class T>
+void trimFront(T& _t, unsigned _elements)
+{
+	static_assert(std::is_pod<typename T::value_type>::value, "");
+	memmove(_t.data(), _t.data() + _elements, (_t.size() - _elements) * sizeof(_t[0]));
+	_t.resize(_t.size() - _elements);
+}
+
+/// Pushes an element on to the front of a collection.
+/// Only works for POD element types.
+template <class T, class U>
+void pushFront(T& _t, U _e)
+{
+	static_assert(std::is_pod<typename T::value_type>::value, "");
+	_t.push_back(_e);
+	memmove(_t.data() + 1, _t.data(), (_t.size() - 1) * sizeof(_e));
+	_t[0] = _e;
+}
+
+/// Concatenate two vectors of elements of POD types.
+template <class T>
+inline std::vector<T>& operator+=(std::vector<typename std::enable_if<std::is_pod<T>::value, T>::type>& _a, std::vector<T> const& _b)
+{
+	auto s = _a.size();
+	_a.resize(_a.size() + _b.size());
+	memcpy(_a.data() + s, _b.data(), _b.size() * sizeof(T));
+	return _a;
+
+}
+
+/// Concatenate two vectors of elements.
+template <class T>
+inline std::vector<T>& operator+=(std::vector<typename std::enable_if<!std::is_pod<T>::value, T>::type>& _a, std::vector<T> const& _b)
+{
+	_a.reserve(_a.size() + _b.size());
+	for (auto& i: _b)
+		_a.push_back(i);
+	return _a;
+}
+
+/// Insert the contents of a container into a set
+template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
+{
+	for (auto const& i: _b)
+		_a.insert(i);
+	return _a;
+}
+
+/// Insert the contents of a container into an unordered_set
+template <class T, class U> std::unordered_set<T>& operator+=(std::unordered_set<T>& _a, U const& _b)
+{
+	for (auto const& i: _b)
+		_a.insert(i);
+	return _a;
+}
+
+/// Concatenate the contents of a container onto a vector
+template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U const& _b)
+{
+	for (auto const& i: _b)
+		_a.push_back(i);
+	return _a;
+}
+
+/// Insert the contents of a container into a set
+template <class T, class U> std::set<T> operator+(std::set<T> _a, U const& _b)
+{
+	return _a += _b;
+}
+
+/// Insert the contents of a container into an unordered_set
+template <class T, class U> std::unordered_set<T> operator+(std::unordered_set<T> _a, U const& _b)
+{
+	return _a += _b;
+}
+
+/// Concatenate the contents of a container onto a vector
+template <class T, class U> std::vector<T> operator+(std::vector<T> _a, U const& _b)
+{
+	return _a += _b;
+}
+
+/// Concatenate two vectors of elements.
+template <class T>
+inline std::vector<T> operator+(std::vector<T> const& _a, std::vector<T> const& _b)
+{
+	std::vector<T> ret(_a);
+	return ret += _b;
+}
+
+/// Merge two sets of elements.
+template <class T>
+inline std::set<T>& operator+=(std::set<T>& _a, std::set<T> const& _b)
+{
+	for (auto& i: _b)
+		_a.insert(i);
+	return _a;
+}
+
+/// Merge two sets of elements.
+template <class T>
+inline std::set<T> operator+(std::set<T> const& _a, std::set<T> const& _b)
+{
+	std::set<T> ret(_a);
+	return ret += _b;
+}
+
+template <class A, class B>
+std::unordered_map<A, B>& operator+=(std::unordered_map<A, B>& _x, std::unordered_map<A, B> const& _y)
+{
+	for (auto const& i: _y)
+		_x.insert(i);
+	return _x;
+}
+
+template <class A, class B>
+std::unordered_map<A, B> operator+(std::unordered_map<A, B> const& _x, std::unordered_map<A, B> const& _y)
+{
+	std::unordered_map<A, B> ret(_x);
+	return ret += _y;
+}
+
+/// Make normal string from fixed-length string.
+std::string toString(string32 const& _s);
+
+template<class T, class U>
+std::vector<T> keysOf(std::map<T, U> const& _m)
+{
+	std::vector<T> ret;
+	for (auto const& i: _m)
+		ret.push_back(i.first);
+	return ret;
+}
+
+template<class T, class U>
+std::vector<T> keysOf(std::unordered_map<T, U> const& _m)
+{
+	std::vector<T> ret;
+	for (auto const& i: _m)
+		ret.push_back(i.first);
+	return ret;
+}
+
+template<class T, class U>
+std::vector<U> valuesOf(std::map<T, U> const& _m)
+{
+	std::vector<U> ret;
+	ret.reserve(_m.size());
+	for (auto const& i: _m)
+		ret.push_back(i.second);
+	return ret;
+}
+
+template<class T, class U>
+std::vector<U> valuesOf(std::unordered_map<T, U> const& _m)
+{
+	std::vector<U> ret;
+	ret.reserve(_m.size());
+	for (auto const& i: _m)
+		ret.push_back(i.second);
+	return ret;
+}
+
+template <class T, class V>
+bool contains(T const& _t, V const& _v)
+{
+	return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v);
+}
+
+}
diff --git a/src/ringdht/eth/libdevcore/Exceptions.h b/src/ringdht/eth/libdevcore/Exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6c1f9aba04a8ee142d3747aa5b36d3ebeaba5eb
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Exceptions.h
@@ -0,0 +1,87 @@
+/*
+	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 Exceptions.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#pragma once
+
+#include <exception>
+#include <string>
+#include <boost/exception/exception.hpp>
+#include <boost/exception/info.hpp>
+#include <boost/exception/info_tuple.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/tuple/tuple.hpp>
+#include "CommonData.h"
+#include "FixedHash.h"
+
+namespace dev
+{
+
+/// Base class for all exceptions.
+struct Exception: virtual std::exception, virtual boost::exception
+{
+	Exception(std::string _message = std::string()): m_message(std::move(_message)) {}
+	const char* what() const noexcept override { return m_message.empty() ? std::exception::what() : m_message.c_str(); }
+
+private:
+	std::string m_message;
+};
+
+#define DEV_SIMPLE_EXCEPTION(X) struct X: virtual Exception { const char* what() const noexcept override { return #X; } }
+
+/// Base class for all RLP exceptions.
+struct RLPException: virtual Exception { RLPException(std::string _message = std::string()): Exception(_message) {} };
+#define DEV_SIMPLE_EXCEPTION_RLP(X) struct X: virtual RLPException { const char* what() const noexcept override { return #X; } }
+
+DEV_SIMPLE_EXCEPTION_RLP(BadCast);
+DEV_SIMPLE_EXCEPTION_RLP(BadRLP);
+DEV_SIMPLE_EXCEPTION_RLP(OversizeRLP);
+DEV_SIMPLE_EXCEPTION_RLP(UndersizeRLP);
+
+DEV_SIMPLE_EXCEPTION(BadHexCharacter);
+DEV_SIMPLE_EXCEPTION(NoNetworking);
+DEV_SIMPLE_EXCEPTION(NoUPnPDevice);
+DEV_SIMPLE_EXCEPTION(RootNotFound);
+struct BadRoot: virtual Exception { public: BadRoot(h256 const& _root): Exception("BadRoot " + _root.hex()), root(_root) {} h256 root; };
+DEV_SIMPLE_EXCEPTION(FileError);
+DEV_SIMPLE_EXCEPTION(Overflow);
+DEV_SIMPLE_EXCEPTION(FailedInvariant);
+DEV_SIMPLE_EXCEPTION(ValueTooLarge);
+
+struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
+struct ExternalFunctionFailure: virtual Exception { public: ExternalFunctionFailure(std::string _f): Exception("Function " + _f + "() failed.") {} };
+
+// error information to be added to exceptions
+using errinfo_invalidSymbol = boost::error_info<struct tag_invalidSymbol, char>;
+using errinfo_wrongAddress = boost::error_info<struct tag_address, std::string>;
+using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
+using errinfo_required = boost::error_info<struct tag_required, bigint>;
+using errinfo_got = boost::error_info<struct tag_got, bigint>;
+using errinfo_min = boost::error_info<struct tag_min, bigint>;
+using errinfo_max = boost::error_info<struct tag_max, bigint>;
+using RequirementError = boost::tuple<errinfo_required, errinfo_got>;
+using errinfo_hash256 = boost::error_info<struct tag_hash, h256>;
+using errinfo_required_h256 = boost::error_info<struct tag_required_h256, h256>;
+using errinfo_got_h256 = boost::error_info<struct tag_get_h256, h256>;
+using Hash256RequirementError = boost::tuple<errinfo_required_h256, errinfo_got_h256>;
+using errinfo_extraData = boost::error_info<struct tag_extraData, bytes>;
+
+}
diff --git a/src/ringdht/eth/libdevcore/FixedHash.cpp b/src/ringdht/eth/libdevcore/FixedHash.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..420e2bb165c1103f071c482fff13e363053fbe66
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/FixedHash.cpp
@@ -0,0 +1,50 @@
+/*
+	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 FixedHash.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "FixedHash.h"
+#include <ctime>
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace dev;
+
+boost::random_device dev::s_fixedHashEngine;
+
+h128 dev::fromUUID(std::string const& _uuid)
+{
+	try
+	{
+		return h128(boost::replace_all_copy(_uuid, "-", ""));
+	}
+	catch (...)
+	{
+		return h128();
+	}
+}
+
+std::string dev::toUUID(h128 const& _uuid)
+{
+	std::string ret = toHex(_uuid.ref());
+	for (unsigned i: {20, 16, 12, 8})
+		ret.insert(ret.begin() + i, '-');
+	return ret;
+}
+
diff --git a/src/ringdht/eth/libdevcore/FixedHash.h b/src/ringdht/eth/libdevcore/FixedHash.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c1429d3d6be4e11efb780cdd932600c46ff00c0
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/FixedHash.h
@@ -0,0 +1,392 @@
+/*
+	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 FixedHash.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * The FixedHash fixed-size "hash" container type.
+ */
+
+#pragma once
+
+#include <array>
+#include <cstdint>
+#include <algorithm>
+#include <boost/random/random_device.hpp>
+#include <boost/random/uniform_int_distribution.hpp>
+#include <boost/functional/hash.hpp>
+#include "CommonData.h"
+
+namespace dev
+{
+
+/// Compile-time calculation of Log2 of constant values.
+template <unsigned N> struct StaticLog2 { enum { result = 1 + StaticLog2<N/2>::result }; };
+template <> struct StaticLog2<1> { enum { result = 0 }; };
+
+extern boost::random_device s_fixedHashEngine;
+
+/// Fixed-size raw-byte array container type, with an API optimised for storing hashes.
+/// Transparently converts to/from the corresponding arithmetic type; this will
+/// assume the data contained in the hash is big-endian.
+template <unsigned N>
+class FixedHash
+{
+public:
+	/// The corresponding arithmetic type.
+	using Arith = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
+
+	/// The size of the container.
+	enum { size = N };
+
+	/// A dummy flag to avoid accidental construction from pointer.
+	enum ConstructFromPointerType { ConstructFromPointer };
+
+	/// Method to convert from a string.
+	enum ConstructFromStringType { FromHex, FromBinary };
+
+	/// Method to convert from a string.
+	enum ConstructFromHashType { AlignLeft, AlignRight, FailIfDifferent };
+
+	/// Construct an empty hash.
+	FixedHash() { m_data.fill(0); }
+
+	/// Construct from another hash, filling with zeroes or cropping as necessary.
+	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; }
+
+	/// Convert from the corresponding arithmetic type.
+	FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
+
+	/// Convert from unsigned
+	explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); }
+
+	/// Explicitly construct, copying from a byte array.
+	explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
+
+	/// Explicitly construct, copying from a byte array.
+	explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
+
+	/// Explicitly construct, copying from a bytes in memory with given pointer.
+	explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); }
+
+	/// Explicitly construct, copying from a  string.
+	explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : dev::asBytes(_s), _ht) {}
+
+	/// Convert to arithmetic type.
+	operator Arith() const { return fromBigEndian<Arith>(m_data); }
+
+	/// @returns true iff this is the empty hash.
+	explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); }
+
+	// The obvious comparison operators.
+	bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; }
+	bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; }
+	bool operator<(FixedHash const& _c) const { for (unsigned i = 0; i < N; ++i) if (m_data[i] < _c.m_data[i]) return true; else if (m_data[i] > _c.m_data[i]) return false; return false; }
+	bool operator>=(FixedHash const& _c) const { return !operator<(_c); }
+	bool operator<=(FixedHash const& _c) const { return operator==(_c) || operator<(_c); }
+	bool operator>(FixedHash const& _c) const { return !operator<=(_c); }
+
+	// The obvious binary operators.
+	FixedHash& operator^=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] ^= _c.m_data[i]; return *this; }
+	FixedHash operator^(FixedHash const& _c) const { return FixedHash(*this) ^= _c; }
+	FixedHash& operator|=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] |= _c.m_data[i]; return *this; }
+	FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; }
+	FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; }
+	FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
+	FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; }
+
+	// Big-endian increment.
+	FixedHash& operator++() { for (unsigned i = size; i > 0 && !++m_data[--i]; ) {} return *this; }
+
+	/// @returns true if all one-bits in @a _c are set in this object.
+	bool contains(FixedHash const& _c) const { return (*this & _c) == _c; }
+
+	/// @returns a particular byte from the hash.
+	byte& operator[](unsigned _i) { return m_data[_i]; }
+	/// @returns a particular byte from the hash.
+	byte operator[](unsigned _i) const { return m_data[_i]; }
+
+	/// @returns an abridged version of the hash as a user-readable hex string.
+	std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; }
+
+	/// @returns a version of the hash as a user-readable hex string that leaves out the middle part.
+	std::string abridgedMiddle() const { return toHex(ref().cropped(0, 4)) + "\342\200\246" + toHex(ref().cropped(N - 4)); }
+
+	/// @returns the hash as a user-readable hex string.
+	std::string hex() const { return toHex(ref()); }
+
+	/// @returns a mutable byte vector_ref to the object's data.
+	bytesRef ref() { return bytesRef(m_data.data(), N); }
+
+	/// @returns a constant byte vector_ref to the object's data.
+	bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); }
+
+	/// @returns a mutable byte pointer to the object's data.
+	byte* data() { return m_data.data(); }
+
+	/// @returns a constant byte pointer to the object's data.
+	byte const* data() const { return m_data.data(); }
+
+	/// @returns a copy of the object's data as a byte vector.
+	bytes asBytes() const { return bytes(data(), data() + N); }
+
+	/// @returns a mutable reference to the object's data as an STL array.
+	std::array<byte, N>& asArray() { return m_data; }
+
+	/// @returns a constant reference to the object's data as an STL array.
+	std::array<byte, N> const& asArray() const { return m_data; }
+
+	/// Populate with random data.
+	template <class Engine>
+	void randomize(Engine& _eng)
+	{
+		for (auto& i: m_data)
+			i = (uint8_t)boost::random::uniform_int_distribution<uint16_t>(0, 255)(_eng);
+	}
+
+	/// @returns a random valued object.
+	static FixedHash random() { FixedHash ret; ret.randomize(s_fixedHashEngine); return ret; }
+
+	struct hash
+	{
+		/// Make a hash of the object's data.
+		size_t operator()(FixedHash const& _value) const { return boost::hash_range(_value.m_data.cbegin(), _value.m_data.cend()); }
+	};
+
+	template <unsigned P, unsigned M> inline FixedHash& shiftBloom(FixedHash<M> const& _h)
+	{
+		return (*this |= _h.template bloomPart<P, N>());
+	}
+
+	template <unsigned P, unsigned M> inline bool containsBloom(FixedHash<M> const& _h)
+	{
+		return contains(_h.template bloomPart<P, N>());
+	}
+
+	template <unsigned P, unsigned M> inline FixedHash<M> bloomPart() const
+	{
+		unsigned const c_bloomBits = M * 8;
+		unsigned const c_mask = c_bloomBits - 1;
+		unsigned const c_bloomBytes = (StaticLog2<c_bloomBits>::result + 7) / 8;
+
+		static_assert((M & (M - 1)) == 0, "M must be power-of-two");
+		static_assert(P * c_bloomBytes <= N, "out of range");
+
+		FixedHash<M> ret;
+		byte const* p = data();
+		for (unsigned i = 0; i < P; ++i)
+		{
+			unsigned index = 0;
+			for (unsigned j = 0; j < c_bloomBytes; ++j, ++p)
+				index = (index << 8) | *p;
+			index &= c_mask;
+			ret[M - 1 - index / 8] |= (1 << (index % 8));
+		}
+		return ret;
+	}
+
+	/// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
+	inline unsigned firstBitSet() const
+	{
+		unsigned ret = 0;
+		for (auto d: m_data)
+			if (d)
+				for (;; ++ret, d <<= 1)
+					if (d & 0x80)
+						return ret;
+					else {}
+			else
+				ret += 8;
+		return ret;
+	}
+
+	void clear() { m_data.fill(0); }
+
+private:
+	std::array<byte, N> m_data;		///< The binary data.
+};
+
+template <unsigned T>
+class SecureFixedHash: private FixedHash<T>
+{
+public:
+	using ConstructFromHashType = typename FixedHash<T>::ConstructFromHashType;
+	using ConstructFromStringType = typename FixedHash<T>::ConstructFromStringType;
+	using ConstructFromPointerType = typename FixedHash<T>::ConstructFromPointerType;
+	SecureFixedHash() = default;
+	explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b, _t) {}
+	explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b, _t) {}
+	explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash<T>::FailIfDifferent): FixedHash<T>(_b.ref(), _t) {}
+	template <unsigned M> explicit SecureFixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = FixedHash<T>::AlignLeft): FixedHash<T>(_h, _t) {}
+	template <unsigned M> explicit SecureFixedHash(SecureFixedHash<M> const& _h, ConstructFromHashType _t = FixedHash<T>::AlignLeft): FixedHash<T>(_h.makeInsecure(), _t) {}
+	explicit SecureFixedHash(std::string const& _s, ConstructFromStringType _t = FixedHash<T>::FromHex, ConstructFromHashType _ht = FixedHash<T>::FailIfDifferent): FixedHash<T>(_s, _t, _ht) {}
+	explicit SecureFixedHash(bytes const* _d, ConstructFromPointerType _t): FixedHash<T>(_d, _t) {}
+	~SecureFixedHash() { ref().cleanse(); }
+
+	SecureFixedHash<T>& operator=(SecureFixedHash<T> const& _c)
+	{
+		if (&_c == this)
+			return *this;
+		ref().cleanse();
+		FixedHash<T>::operator=(static_cast<FixedHash<T> const&>(_c));
+		return *this;
+	}
+
+	using FixedHash<T>::size;
+
+	bytesSec asBytesSec() const { return bytesSec(ref()); }
+
+	FixedHash<T> const& makeInsecure() const { return static_cast<FixedHash<T> const&>(*this); }
+	FixedHash<T>& writable() { clear(); return static_cast<FixedHash<T>&>(*this); }
+
+	using FixedHash<T>::operator bool;
+
+	// The obvious comparison operators.
+	bool operator==(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator==(static_cast<FixedHash<T> const&>(_c)); }
+	bool operator!=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator!=(static_cast<FixedHash<T> const&>(_c)); }
+	bool operator<(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator<(static_cast<FixedHash<T> const&>(_c)); }
+	bool operator>=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator>=(static_cast<FixedHash<T> const&>(_c)); }
+	bool operator<=(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator<=(static_cast<FixedHash<T> const&>(_c)); }
+	bool operator>(SecureFixedHash const& _c) const { return static_cast<FixedHash<T> const&>(*this).operator>(static_cast<FixedHash<T> const&>(_c)); }
+
+	using FixedHash<T>::operator==;
+	using FixedHash<T>::operator!=;
+	using FixedHash<T>::operator<;
+	using FixedHash<T>::operator>=;
+	using FixedHash<T>::operator<=;
+	using FixedHash<T>::operator>;
+
+	// The obvious binary operators.
+	SecureFixedHash& operator^=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
+	SecureFixedHash operator^(FixedHash<T> const& _c) const { return SecureFixedHash(*this) ^= _c; }
+	SecureFixedHash& operator|=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
+	SecureFixedHash operator|(FixedHash<T> const& _c) const { return SecureFixedHash(*this) |= _c; }
+	SecureFixedHash& operator&=(FixedHash<T> const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(_c); return *this; }
+	SecureFixedHash operator&(FixedHash<T> const& _c) const { return SecureFixedHash(*this) &= _c; }
+
+	SecureFixedHash& operator^=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
+	SecureFixedHash operator^(SecureFixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; }
+	SecureFixedHash& operator|=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
+	SecureFixedHash operator|(SecureFixedHash const& _c) const { return SecureFixedHash(*this) |= _c; }
+	SecureFixedHash& operator&=(SecureFixedHash const& _c) { static_cast<FixedHash<T>&>(*this).operator^=(static_cast<FixedHash<T> const&>(_c)); return *this; }
+	SecureFixedHash operator&(SecureFixedHash const& _c) const { return SecureFixedHash(*this) &= _c; }
+	SecureFixedHash operator~() const { auto r = ~static_cast<FixedHash<T> const&>(*this); return static_cast<SecureFixedHash const&>(r); }
+
+	using FixedHash<T>::abridged;
+	using FixedHash<T>::abridgedMiddle;
+
+	bytesConstRef ref() const { return FixedHash<T>::ref(); }
+	byte const* data() const { return FixedHash<T>::data(); }
+
+	static SecureFixedHash<T> random() { SecureFixedHash<T> ret; ret.randomize(s_fixedHashEngine); return ret; }
+	using FixedHash<T>::firstBitSet;
+
+	void clear() { ref().cleanse(); }
+};
+
+/// Fast equality operator for h256.
+template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
+{
+	const uint64_t* hash1 = (const uint64_t*)data();
+	const uint64_t* hash2 = (const uint64_t*)_other.data();
+	return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]);
+}
+
+/// Fast std::hash compatible hash function object for h256.
+template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
+{
+	uint64_t const* data = reinterpret_cast<uint64_t const*>(value.data());
+	return boost::hash_range(data, data + 4);
+}
+
+/// Stream I/O for the FixedHash class.
+template <unsigned N>
+inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
+{
+	_out << std::noshowbase << std::hex << std::setfill('0');
+	for (unsigned i = 0; i < N; ++i)
+		_out << std::setw(2) << (int)_h[i];
+	_out << std::dec;
+	return _out;
+}
+
+/// Stream I/O for the SecureFixedHash class.
+template <unsigned N>
+inline std::ostream& operator<<(std::ostream& _out, SecureFixedHash<N> const& _h)
+{
+	_out << "SecureFixedHash#" << std::hex << typename FixedHash<N>::hash()(_h.makeInsecure()) << std::dec;
+	return _out;
+}
+
+// Common types of FixedHash.
+using h2048 = FixedHash<256>;
+using h1024 = FixedHash<128>;
+using h520 = FixedHash<65>;
+using h512 = FixedHash<64>;
+using h256 = FixedHash<32>;
+using h160 = FixedHash<20>;
+using h128 = FixedHash<16>;
+using h64 = FixedHash<8>;
+using h512s = std::vector<h512>;
+using h256s = std::vector<h256>;
+using h160s = std::vector<h160>;
+using h256Set = std::set<h256>;
+using h160Set = std::set<h160>;
+using h256Hash = std::unordered_set<h256>;
+using h160Hash = std::unordered_set<h160>;
+
+/// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes.
+inline h160 right160(h256 const& _t)
+{
+	h160 ret;
+	memcpy(ret.data(), _t.data() + 12, 20);
+	return ret;
+}
+
+/// Convert the given value into h160 (160-bit unsigned integer) using the left 20 bytes.
+inline h160 left160(h256 const& _t)
+{
+	h160 ret;
+	memcpy(&ret[0], _t.data(), 20);
+	return ret;
+}
+
+h128 fromUUID(std::string const& _uuid);
+
+std::string toUUID(h128 const& _uuid);
+
+inline std::string toString(h256s const& _bs)
+{
+	std::ostringstream out;
+	out << "[ ";
+	for (auto i: _bs)
+		out << i.abridged() << ", ";
+	out << "]";
+	return out.str();
+}
+
+}
+
+namespace std
+{
+	/// Forward std::hash<dev::FixedHash> to dev::FixedHash::hash.
+	template<> struct hash<dev::h64>: dev::h64::hash {};
+	template<> struct hash<dev::h128>: dev::h128::hash {};
+	template<> struct hash<dev::h160>: dev::h160::hash {};
+	template<> struct hash<dev::h256>: dev::h256::hash {};
+	template<> struct hash<dev::h512>: dev::h512::hash {};
+}
diff --git a/src/ringdht/eth/libdevcore/Guards.cpp b/src/ringdht/eth/libdevcore/Guards.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69ae6c03a49f14e5315e9f223bf0ea1fad88c216
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Guards.cpp
@@ -0,0 +1,29 @@
+/*
+	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 Guards.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "Guards.h"
+using namespace std;
+using namespace dev;
+
+namespace dev
+{
+
+}
diff --git a/src/ringdht/eth/libdevcore/Guards.h b/src/ringdht/eth/libdevcore/Guards.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7d8c35089530d65e785413f4e95206a5484a566
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Guards.h
@@ -0,0 +1,159 @@
+/*
+	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 Guards.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#pragma once
+
+#include <mutex>
+#include <condition_variable>
+#include <atomic>
+#pragma warning(push)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <boost/thread.hpp>
+#pragma warning(pop)
+#pragma GCC diagnostic pop
+
+namespace dev
+{
+
+using Mutex = std::mutex;
+using RecursiveMutex = std::recursive_mutex;
+using SharedMutex = boost::shared_mutex;
+
+using Guard = std::lock_guard<std::mutex>;
+using UniqueGuard = std::unique_lock<std::mutex>;
+using RecursiveGuard = std::lock_guard<std::recursive_mutex>;
+using ReadGuard = boost::shared_lock<boost::shared_mutex>;
+using UpgradableGuard = boost::upgrade_lock<boost::shared_mutex>;
+using UpgradeGuard = boost::upgrade_to_unique_lock<boost::shared_mutex>;
+using WriteGuard = boost::unique_lock<boost::shared_mutex>;
+
+template <class GuardType, class MutexType>
+struct GenericGuardBool: GuardType
+{
+	GenericGuardBool(MutexType& _m): GuardType(_m) {}
+	bool b = true;
+};
+template <class MutexType>
+struct GenericUnguardBool
+{
+	GenericUnguardBool(MutexType& _m): m(_m) { m.unlock(); }
+	~GenericUnguardBool() { m.lock(); }
+	bool b = true;
+	MutexType& m;
+};
+template <class MutexType>
+struct GenericUnguardSharedBool
+{
+	GenericUnguardSharedBool(MutexType& _m): m(_m) { m.unlock_shared(); }
+	~GenericUnguardSharedBool() { m.lock_shared(); }
+	bool b = true;
+	MutexType& m;
+};
+
+/** @brief Simple lock that waits for release without making context switch */
+class SpinLock
+{
+public:
+	SpinLock() { m_lock.clear(); }
+	void lock() { while (m_lock.test_and_set(std::memory_order_acquire)) {} }
+	void unlock() { m_lock.clear(std::memory_order_release); }
+private:
+	std::atomic_flag m_lock;
+};
+using SpinGuard = std::lock_guard<SpinLock>;
+
+template <class N>
+class Notified
+{
+public:
+	Notified() {}
+	Notified(N const& _v): m_value(_v) {}
+	Notified(Notified const&) = delete;
+	Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; }
+
+	operator N() const { UniqueGuard l(m_mutex); return m_value; }
+
+	void wait() const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(old); }
+	void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); }
+	void waitNot(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value != _v;}); }
+	template <class F> void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); }
+
+	template <class R, class P> void wait(std::chrono::duration<R, P> _d) const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(_d, old); }
+	template <class R, class P> void wait(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value == _v;}); }
+	template <class R, class P> void waitNot(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value != _v;}); }
+	template <class R, class P, class F> void wait(std::chrono::duration<R, P> _d, F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, _f); }
+
+private:
+	mutable Mutex m_mutex;
+	mutable std::condition_variable m_cv;
+	N m_value;
+};
+
+/** @brief Simple block guard.
+ * The expression/block following is guarded though the given mutex.
+ * Usage:
+ * @code
+ * Mutex m;
+ * unsigned d;
+ * ...
+ * ETH_(m) d = 1;
+ * ...
+ * ETH_(m) { for (auto d = 10; d > 0; --d) foo(d); d = 0; }
+ * @endcode
+ *
+ * There are several variants of this basic mechanism for different Mutex types and Guards.
+ *
+ * There is also the UNGUARD variant which allows an unguarded expression/block to exist within a
+ * guarded expression. eg:
+ *
+ * @code
+ * Mutex m;
+ * int d;
+ * ...
+ * ETH_GUARDED(m)
+ * {
+ *   for (auto d = 50; d > 25; --d)
+ *     foo(d);
+ *   ETH_UNGUARDED(m)
+ *     bar();
+ *   for (; d > 0; --d)
+ *     foo(d);
+ * }
+ * @endcode
+ */
+
+#define DEV_GUARDED(MUTEX) \
+	for (GenericGuardBool<Guard, Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_READ_GUARDED(MUTEX) \
+	for (GenericGuardBool<ReadGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_WRITE_GUARDED(MUTEX) \
+	for (GenericGuardBool<WriteGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_RECURSIVE_GUARDED(MUTEX) \
+	for (GenericGuardBool<RecursiveGuard, RecursiveMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_UNGUARDED(MUTEX) \
+	for (GenericUnguardBool<Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_READ_UNGUARDED(MUTEX) \
+	for (GenericUnguardSharedBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+#define DEV_WRITE_UNGUARDED(MUTEX) \
+	for (GenericUnguardBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
+
+}
diff --git a/src/ringdht/eth/libdevcore/Hash.cpp b/src/ringdht/eth/libdevcore/Hash.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6b917b9033502d97f07b61479749c64f9c1634e
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Hash.cpp
@@ -0,0 +1,440 @@
+/*
+	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 Hash.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "Hash.h"
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include "picosha2.h"
+using namespace std;
+using namespace dev;
+
+namespace dev
+{
+
+h256 sha256(bytesConstRef _input)
+{
+	h256 ret;
+	picosha2::hash256(_input.begin(), _input.end(), ret.data(), ret.data() + 32);
+	return ret;
+}
+
+namespace rmd160
+{
+
+/********************************************************************\
+ *
+ *      FILE:     rmd160.h
+ *      FILE:     rmd160.c
+ *
+ *      CONTENTS: Header file for a sample C-implementation of the
+ *                RIPEMD-160 hash-function.
+ *      TARGET:   any computer with an ANSI C compiler
+ *
+ *      AUTHOR:   Antoon Bosselaers, ESAT-COSIC
+ *      DATE:     1 March 1996
+ *      VERSION:  1.0
+ *
+ *      Copyright (c) Katholieke Universiteit Leuven
+ *      1996, All Rights Reserved
+ *
+ \********************************************************************/
+
+// Adapted into "header-only" format by Gav Wood.
+
+/* macro definitions */
+
+#define RMDsize 160
+
+/* collect four bytes into one word: */
+#define BYTES_TO_DWORD(strptr)                    \
+(((uint32_t) *((strptr)+3) << 24) | \
+((uint32_t) *((strptr)+2) << 16) | \
+((uint32_t) *((strptr)+1) <<  8) | \
+((uint32_t) *(strptr)))
+
+/* ROL(x, n) cyclically rotates x over n bits to the left */
+/* x must be of an unsigned 32 bits type and 0 <= n < 32. */
+#define ROL(x, n)        (((x) << (n)) | ((x) >> (32-(n))))
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z)        ((x) ^ (y) ^ (z))
+#define G(x, y, z)        (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z)        (((x) | ~(y)) ^ (z))
+#define I(x, y, z)        (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z)        ((x) ^ ((y) | ~(z)))
+
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s)        {\
+(a) += F((b), (c), (d)) + (x);\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define GG(a, b, c, d, e, x, s)        {\
+(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define HH(a, b, c, d, e, x, s)        {\
+(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define II(a, b, c, d, e, x, s)        {\
+(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define JJ(a, b, c, d, e, x, s)        {\
+(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define FFF(a, b, c, d, e, x, s)        {\
+(a) += F((b), (c), (d)) + (x);\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define GGG(a, b, c, d, e, x, s)        {\
+(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define HHH(a, b, c, d, e, x, s)        {\
+(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define III(a, b, c, d, e, x, s)        {\
+(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+#define JJJ(a, b, c, d, e, x, s)        {\
+(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+(a) = ROL((a), (s)) + (e);\
+(c) = ROL((c), 10);\
+}
+
+void MDinit(uint32_t *MDbuf)
+{
+	MDbuf[0] = 0x67452301UL;
+	MDbuf[1] = 0xefcdab89UL;
+	MDbuf[2] = 0x98badcfeUL;
+	MDbuf[3] = 0x10325476UL;
+	MDbuf[4] = 0xc3d2e1f0UL;
+
+	return;
+}
+
+/********************************************************************/
+
+void MDcompress(uint32_t *MDbuf, uint32_t *X)
+{
+	uint32_t aa = MDbuf[0],  bb = MDbuf[1],  cc = MDbuf[2],
+	dd = MDbuf[3],  ee = MDbuf[4];
+	uint32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
+	ddd = MDbuf[3], eee = MDbuf[4];
+
+	/* round 1 */
+	FF(aa, bb, cc, dd, ee, X[ 0], 11);
+	FF(ee, aa, bb, cc, dd, X[ 1], 14);
+	FF(dd, ee, aa, bb, cc, X[ 2], 15);
+	FF(cc, dd, ee, aa, bb, X[ 3], 12);
+	FF(bb, cc, dd, ee, aa, X[ 4],  5);
+	FF(aa, bb, cc, dd, ee, X[ 5],  8);
+	FF(ee, aa, bb, cc, dd, X[ 6],  7);
+	FF(dd, ee, aa, bb, cc, X[ 7],  9);
+	FF(cc, dd, ee, aa, bb, X[ 8], 11);
+	FF(bb, cc, dd, ee, aa, X[ 9], 13);
+	FF(aa, bb, cc, dd, ee, X[10], 14);
+	FF(ee, aa, bb, cc, dd, X[11], 15);
+	FF(dd, ee, aa, bb, cc, X[12],  6);
+	FF(cc, dd, ee, aa, bb, X[13],  7);
+	FF(bb, cc, dd, ee, aa, X[14],  9);
+	FF(aa, bb, cc, dd, ee, X[15],  8);
+
+	/* round 2 */
+	GG(ee, aa, bb, cc, dd, X[ 7],  7);
+	GG(dd, ee, aa, bb, cc, X[ 4],  6);
+	GG(cc, dd, ee, aa, bb, X[13],  8);
+	GG(bb, cc, dd, ee, aa, X[ 1], 13);
+	GG(aa, bb, cc, dd, ee, X[10], 11);
+	GG(ee, aa, bb, cc, dd, X[ 6],  9);
+	GG(dd, ee, aa, bb, cc, X[15],  7);
+	GG(cc, dd, ee, aa, bb, X[ 3], 15);
+	GG(bb, cc, dd, ee, aa, X[12],  7);
+	GG(aa, bb, cc, dd, ee, X[ 0], 12);
+	GG(ee, aa, bb, cc, dd, X[ 9], 15);
+	GG(dd, ee, aa, bb, cc, X[ 5],  9);
+	GG(cc, dd, ee, aa, bb, X[ 2], 11);
+	GG(bb, cc, dd, ee, aa, X[14],  7);
+	GG(aa, bb, cc, dd, ee, X[11], 13);
+	GG(ee, aa, bb, cc, dd, X[ 8], 12);
+
+	/* round 3 */
+	HH(dd, ee, aa, bb, cc, X[ 3], 11);
+	HH(cc, dd, ee, aa, bb, X[10], 13);
+	HH(bb, cc, dd, ee, aa, X[14],  6);
+	HH(aa, bb, cc, dd, ee, X[ 4],  7);
+	HH(ee, aa, bb, cc, dd, X[ 9], 14);
+	HH(dd, ee, aa, bb, cc, X[15],  9);
+	HH(cc, dd, ee, aa, bb, X[ 8], 13);
+	HH(bb, cc, dd, ee, aa, X[ 1], 15);
+	HH(aa, bb, cc, dd, ee, X[ 2], 14);
+	HH(ee, aa, bb, cc, dd, X[ 7],  8);
+	HH(dd, ee, aa, bb, cc, X[ 0], 13);
+	HH(cc, dd, ee, aa, bb, X[ 6],  6);
+	HH(bb, cc, dd, ee, aa, X[13],  5);
+	HH(aa, bb, cc, dd, ee, X[11], 12);
+	HH(ee, aa, bb, cc, dd, X[ 5],  7);
+	HH(dd, ee, aa, bb, cc, X[12],  5);
+
+	/* round 4 */
+	II(cc, dd, ee, aa, bb, X[ 1], 11);
+	II(bb, cc, dd, ee, aa, X[ 9], 12);
+	II(aa, bb, cc, dd, ee, X[11], 14);
+	II(ee, aa, bb, cc, dd, X[10], 15);
+	II(dd, ee, aa, bb, cc, X[ 0], 14);
+	II(cc, dd, ee, aa, bb, X[ 8], 15);
+	II(bb, cc, dd, ee, aa, X[12],  9);
+	II(aa, bb, cc, dd, ee, X[ 4],  8);
+	II(ee, aa, bb, cc, dd, X[13],  9);
+	II(dd, ee, aa, bb, cc, X[ 3], 14);
+	II(cc, dd, ee, aa, bb, X[ 7],  5);
+	II(bb, cc, dd, ee, aa, X[15],  6);
+	II(aa, bb, cc, dd, ee, X[14],  8);
+	II(ee, aa, bb, cc, dd, X[ 5],  6);
+	II(dd, ee, aa, bb, cc, X[ 6],  5);
+	II(cc, dd, ee, aa, bb, X[ 2], 12);
+
+	/* round 5 */
+	JJ(bb, cc, dd, ee, aa, X[ 4],  9);
+	JJ(aa, bb, cc, dd, ee, X[ 0], 15);
+	JJ(ee, aa, bb, cc, dd, X[ 5],  5);
+	JJ(dd, ee, aa, bb, cc, X[ 9], 11);
+	JJ(cc, dd, ee, aa, bb, X[ 7],  6);
+	JJ(bb, cc, dd, ee, aa, X[12],  8);
+	JJ(aa, bb, cc, dd, ee, X[ 2], 13);
+	JJ(ee, aa, bb, cc, dd, X[10], 12);
+	JJ(dd, ee, aa, bb, cc, X[14],  5);
+	JJ(cc, dd, ee, aa, bb, X[ 1], 12);
+	JJ(bb, cc, dd, ee, aa, X[ 3], 13);
+	JJ(aa, bb, cc, dd, ee, X[ 8], 14);
+	JJ(ee, aa, bb, cc, dd, X[11], 11);
+	JJ(dd, ee, aa, bb, cc, X[ 6],  8);
+	JJ(cc, dd, ee, aa, bb, X[15],  5);
+	JJ(bb, cc, dd, ee, aa, X[13],  6);
+
+	/* parallel round 1 */
+	JJJ(aaa, bbb, ccc, ddd, eee, X[ 5],  8);
+	JJJ(eee, aaa, bbb, ccc, ddd, X[14],  9);
+	JJJ(ddd, eee, aaa, bbb, ccc, X[ 7],  9);
+	JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
+	JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
+	JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
+	JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
+	JJJ(ddd, eee, aaa, bbb, ccc, X[ 4],  5);
+	JJJ(ccc, ddd, eee, aaa, bbb, X[13],  7);
+	JJJ(bbb, ccc, ddd, eee, aaa, X[ 6],  7);
+	JJJ(aaa, bbb, ccc, ddd, eee, X[15],  8);
+	JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
+	JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
+	JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
+	JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
+	JJJ(aaa, bbb, ccc, ddd, eee, X[12],  6);
+
+	/* parallel round 2 */
+	III(eee, aaa, bbb, ccc, ddd, X[ 6],  9);
+	III(ddd, eee, aaa, bbb, ccc, X[11], 13);
+	III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
+	III(bbb, ccc, ddd, eee, aaa, X[ 7],  7);
+	III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
+	III(eee, aaa, bbb, ccc, ddd, X[13],  8);
+	III(ddd, eee, aaa, bbb, ccc, X[ 5],  9);
+	III(ccc, ddd, eee, aaa, bbb, X[10], 11);
+	III(bbb, ccc, ddd, eee, aaa, X[14],  7);
+	III(aaa, bbb, ccc, ddd, eee, X[15],  7);
+	III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
+	III(ddd, eee, aaa, bbb, ccc, X[12],  7);
+	III(ccc, ddd, eee, aaa, bbb, X[ 4],  6);
+	III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
+	III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
+	III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
+
+	/* parallel round 3 */
+	HHH(ddd, eee, aaa, bbb, ccc, X[15],  9);
+	HHH(ccc, ddd, eee, aaa, bbb, X[ 5],  7);
+	HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
+	HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
+	HHH(eee, aaa, bbb, ccc, ddd, X[ 7],  8);
+	HHH(ddd, eee, aaa, bbb, ccc, X[14],  6);
+	HHH(ccc, ddd, eee, aaa, bbb, X[ 6],  6);
+	HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
+	HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
+	HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
+	HHH(ddd, eee, aaa, bbb, ccc, X[12],  5);
+	HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
+	HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
+	HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
+	HHH(eee, aaa, bbb, ccc, ddd, X[ 4],  7);
+	HHH(ddd, eee, aaa, bbb, ccc, X[13],  5);
+
+	/* parallel round 4 */
+	GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
+	GGG(bbb, ccc, ddd, eee, aaa, X[ 6],  5);
+	GGG(aaa, bbb, ccc, ddd, eee, X[ 4],  8);
+	GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
+	GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
+	GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
+	GGG(bbb, ccc, ddd, eee, aaa, X[15],  6);
+	GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
+	GGG(eee, aaa, bbb, ccc, ddd, X[ 5],  6);
+	GGG(ddd, eee, aaa, bbb, ccc, X[12],  9);
+	GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
+	GGG(bbb, ccc, ddd, eee, aaa, X[13],  9);
+	GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
+	GGG(eee, aaa, bbb, ccc, ddd, X[ 7],  5);
+	GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
+	GGG(ccc, ddd, eee, aaa, bbb, X[14],  8);
+
+	/* parallel round 5 */
+	FFF(bbb, ccc, ddd, eee, aaa, X[12] ,  8);
+	FFF(aaa, bbb, ccc, ddd, eee, X[15] ,  5);
+	FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
+	FFF(ddd, eee, aaa, bbb, ccc, X[ 4] ,  9);
+	FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
+	FFF(bbb, ccc, ddd, eee, aaa, X[ 5] ,  5);
+	FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
+	FFF(eee, aaa, bbb, ccc, ddd, X[ 7] ,  6);
+	FFF(ddd, eee, aaa, bbb, ccc, X[ 6] ,  8);
+	FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
+	FFF(bbb, ccc, ddd, eee, aaa, X[13] ,  6);
+	FFF(aaa, bbb, ccc, ddd, eee, X[14] ,  5);
+	FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
+	FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
+	FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
+	FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
+
+	/* combine results */
+	ddd += cc + MDbuf[1];               /* final result for MDbuf[0] */
+	MDbuf[1] = MDbuf[2] + dd + eee;
+	MDbuf[2] = MDbuf[3] + ee + aaa;
+	MDbuf[3] = MDbuf[4] + aa + bbb;
+	MDbuf[4] = MDbuf[0] + bb + ccc;
+	MDbuf[0] = ddd;
+
+	return;
+}
+
+void MDfinish(uint32_t *MDbuf, byte const *strptr, uint32_t lswlen, uint32_t mswlen)
+{
+	unsigned int i;                                 /* counter       */
+	uint32_t        X[16];                             /* message words */
+
+	memset(X, 0, 16*sizeof(uint32_t));
+
+	/* put bytes from strptr into X */
+	for (i=0; i<(lswlen&63); i++) {
+		/* byte i goes into word X[i div 4] at pos.  8*(i mod 4)  */
+		X[i>>2] ^= (uint32_t) *strptr++ << (8 * (i&3));
+	}
+
+	/* append the bit m_n == 1 */
+	X[(lswlen>>2)&15] ^= (uint32_t)1 << (8*(lswlen&3) + 7);
+
+	if ((lswlen & 63) > 55) {
+		/* length goes to next block */
+		MDcompress(MDbuf, X);
+		memset(X, 0, 16*sizeof(uint32_t));
+	}
+
+	/* append length in bits*/
+	X[14] = lswlen << 3;
+	X[15] = (lswlen >> 29) | (mswlen << 3);
+	MDcompress(MDbuf, X);
+
+	return;
+}
+
+#undef ROL
+#undef F
+#undef G
+#undef H
+#undef I
+#undef J
+#undef FF
+#undef GG
+#undef HH
+#undef II
+#undef JJ
+#undef FFF
+#undef GGG
+#undef HHH
+#undef III
+#undef JJJ
+
+}
+
+/*
+ * @returns RMD(_input)
+ */
+h160 ripemd160(bytesConstRef _input)
+{
+	h160 hashcode;
+	uint32_t buffer[RMDsize / 32];		// contains (A, B, C, D(, E))
+	uint32_t current[16];				// current 16-word chunk
+
+	// initialize
+	rmd160::MDinit(buffer);
+	byte const* message = _input.data();
+	uint32_t remaining = _input.size();	// # of bytes not yet processed
+
+	// process message in 16x 4-byte chunks
+	for (; remaining >= 64; remaining -= 64)
+	{
+		for (unsigned i = 0; i < 16; i++)
+		{
+			current[i] = BYTES_TO_DWORD(message);
+			message += 4;
+		}
+		rmd160::MDcompress(buffer, current);
+	}
+	// length mod 64 bytes left
+
+	// finish:
+	rmd160::MDfinish(buffer, message, _input.size(), 0);
+
+	for (unsigned i = 0; i < RMDsize / 8; i += 4)
+	{
+		hashcode[i] = buffer[i >> 2];				//  implicit cast to byte
+		hashcode[i + 1] = (buffer[i >> 2] >> 8);	//extracts the 8 least
+		hashcode[i + 2] = (buffer[i >> 2] >> 16);	// significant bits.
+		hashcode[i + 3] = (buffer[i >> 2] >> 24);
+	}
+
+	return hashcode;
+}
+
+#undef BYTES_TO_DWORD
+#undef RMDsize
+
+}
diff --git a/src/ringdht/eth/libdevcore/Hash.h b/src/ringdht/eth/libdevcore/Hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4401014f91daf1b596824f2572eb120de5b684b
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Hash.h
@@ -0,0 +1,38 @@
+/*
+	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 Hash.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * The FixedHash fixed-size "hash" container type.
+ */
+
+#pragma once
+
+#include <string>
+#include "FixedHash.h"
+#include "vector_ref.h"
+#include "SHA3.h"
+
+namespace dev
+{
+
+h256 sha256(bytesConstRef _input);
+
+h160 ripemd160(bytesConstRef _input);
+
+}
diff --git a/src/ringdht/eth/libdevcore/Makefile.am b/src/ringdht/eth/libdevcore/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..24aebec25bc27f76f3642fc9d49a91b9bd5a674c
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/Makefile.am
@@ -0,0 +1,21 @@
+include $(top_srcdir)/globals.mak
+
+noinst_LTLIBRARIES = libdevcore.la
+libdevcore_la_CPPFLAGS = @CPPFLAGS@ -DBOOST_SYSTEM_NO_DEPRECATED
+libdevcore_la_CXXFLAGS = @CXXFLAGS@
+
+libdevcore_la_SOURCES = FixedHash.cpp \
+	Hash.cpp \
+	Guards.cpp \
+	Common.cpp \
+	RLP.cpp \
+	SHA3.cpp \
+	CommonData.cpp
+
+noinst_HEADERS = FixedHash.h \
+	Hash.h \
+	Guards.h \
+	Common.h \
+	RLP.h \
+	SHA3.h \
+	CommonData.h
diff --git a/src/ringdht/eth/libdevcore/RLP.cpp b/src/ringdht/eth/libdevcore/RLP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..45b3a2db0e16bd888250c370cbdaf51bfcfc092e
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/RLP.cpp
@@ -0,0 +1,378 @@
+/*
+	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 RLP.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "RLP.h"
+using namespace std;
+using namespace dev;
+
+bytes dev::RLPNull = rlp("");
+bytes dev::RLPEmptyList = rlpList();
+
+RLP::RLP(bytesConstRef _d, Strictness _s):
+	m_data(_d)
+{
+	if ((_s & FailIfTooBig) && actualSize() < _d.size())
+	{
+		if (_s & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(OversizeRLP());
+		else
+			m_data.reset();
+	}
+	if ((_s & FailIfTooSmall) && actualSize() > _d.size())
+	{
+		if (_s & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(UndersizeRLP());
+		else
+			m_data.reset();
+	}
+}
+
+RLP::iterator& RLP::iterator::operator++()
+{
+	if (m_remaining)
+	{
+		m_currentItem.retarget(m_currentItem.next().data(), m_remaining);
+		m_currentItem = m_currentItem.cropped(0, sizeAsEncoded(m_currentItem));
+		m_remaining -= std::min<size_t>(m_remaining, m_currentItem.size());
+	}
+	else
+		m_currentItem.retarget(m_currentItem.next().data(), 0);
+	return *this;
+}
+
+RLP::iterator::iterator(RLP const& _parent, bool _begin)
+{
+	if (_begin && _parent.isList())
+	{
+		auto pl = _parent.payload();
+		m_currentItem = pl.cropped(0, sizeAsEncoded(pl));
+		m_remaining = pl.size() - m_currentItem.size();
+	}
+	else
+	{
+		m_currentItem = _parent.data().cropped(_parent.data().size());
+		m_remaining = 0;
+	}
+}
+
+RLP RLP::operator[](size_t _i) const
+{
+	if (_i < m_lastIndex)
+	{
+		m_lastEnd = sizeAsEncoded(payload());
+		m_lastItem = payload().cropped(0, m_lastEnd);
+		m_lastIndex = 0;
+	}
+	for (; m_lastIndex < _i && m_lastItem.size(); ++m_lastIndex)
+	{
+		m_lastItem = payload().cropped(m_lastEnd);
+		m_lastItem = m_lastItem.cropped(0, sizeAsEncoded(m_lastItem));
+		m_lastEnd += m_lastItem.size();
+	}
+	return RLP(m_lastItem, ThrowOnFail | FailIfTooSmall);
+}
+
+RLPs RLP::toList(int _flags) const
+{
+	RLPs ret;
+	if (!isList())
+	{
+		if (_flags & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(BadCast());
+		else
+			return ret;
+	}
+	for (auto const& i: *this)
+		ret.push_back(i);
+	return ret;
+}
+
+size_t RLP::actualSize() const
+{
+	if (isNull())
+		return 0;
+	if (isSingleByte())
+		return 1;
+	if (isData() || isList())
+		return payloadOffset() + length();
+	return 0;
+}
+
+void RLP::requireGood() const
+{
+	if (isNull())
+		BOOST_THROW_EXCEPTION(BadRLP());
+	byte n = m_data[0];
+	if (n != c_rlpDataImmLenStart + 1)
+		return;
+	if (m_data.size() < 2)
+		BOOST_THROW_EXCEPTION(BadRLP());
+	if (m_data[1] < c_rlpDataImmLenStart)
+		BOOST_THROW_EXCEPTION(BadRLP());
+}
+
+bool RLP::isInt() const
+{
+	if (isNull())
+		return false;
+	requireGood();
+	byte n = m_data[0];
+	if (n < c_rlpDataImmLenStart)
+		return !!n;
+	else if (n == c_rlpDataImmLenStart)
+		return true;
+	else if (n <= c_rlpDataIndLenZero)
+	{
+		if (m_data.size() <= 1)
+			BOOST_THROW_EXCEPTION(BadRLP());
+		return m_data[1] != 0;
+	}
+	else if (n < c_rlpListStart)
+	{
+		if (m_data.size() <= size_t(1 + n - c_rlpDataIndLenZero))
+			BOOST_THROW_EXCEPTION(BadRLP());
+		return m_data[1 + n - c_rlpDataIndLenZero] != 0;
+	}
+	else
+		return false;
+	return false;
+}
+
+size_t RLP::length() const
+{
+	if (isNull())
+		return 0;
+	requireGood();
+	size_t ret = 0;
+	byte const n = m_data[0];
+	if (n < c_rlpDataImmLenStart)
+		return 1;
+	else if (n <= c_rlpDataIndLenZero)
+		return n - c_rlpDataImmLenStart;
+	else if (n < c_rlpListStart)
+	{
+		if (m_data.size() <= size_t(n - c_rlpDataIndLenZero))
+			BOOST_THROW_EXCEPTION(BadRLP());
+		if (m_data.size() > 1)
+			if (m_data[1] == 0)
+				BOOST_THROW_EXCEPTION(BadRLP());
+		unsigned lengthSize = n - c_rlpDataIndLenZero;
+		if (lengthSize > sizeof(ret))
+			// We did not check, but would most probably not fit in our memory.
+			BOOST_THROW_EXCEPTION(UndersizeRLP());
+		// No leading zeroes.
+		if (!m_data[1])
+			BOOST_THROW_EXCEPTION(BadRLP());
+		for (unsigned i = 0; i < lengthSize; ++i)
+			ret = (ret << 8) | m_data[i + 1];
+		// Must be greater than the limit.
+		if (ret < c_rlpListStart - c_rlpDataImmLenStart - c_rlpMaxLengthBytes)
+			BOOST_THROW_EXCEPTION(BadRLP());
+	}
+	else if (n <= c_rlpListIndLenZero)
+		return n - c_rlpListStart;
+	else
+	{
+		unsigned lengthSize = n - c_rlpListIndLenZero;
+		if (m_data.size() <= lengthSize)
+			BOOST_THROW_EXCEPTION(BadRLP());
+		if (m_data.size() > 1)
+			if (m_data[1] == 0)
+				BOOST_THROW_EXCEPTION(BadRLP());
+		if (lengthSize > sizeof(ret))
+			// We did not check, but would most probably not fit in our memory.
+			BOOST_THROW_EXCEPTION(UndersizeRLP());
+		if (!m_data[1])
+			BOOST_THROW_EXCEPTION(BadRLP());
+		for (unsigned i = 0; i < lengthSize; ++i)
+			ret = (ret << 8) | m_data[i + 1];
+		if (ret < 0x100 - c_rlpListStart - c_rlpMaxLengthBytes)
+			BOOST_THROW_EXCEPTION(BadRLP());
+	}
+	// We have to be able to add payloadOffset to length without overflow.
+	// This rejects roughly 4GB-sized RLPs on some platforms.
+	if (ret >= std::numeric_limits<size_t>::max() - 0x100)
+		BOOST_THROW_EXCEPTION(UndersizeRLP());
+	return ret;
+}
+
+size_t RLP::items() const
+{
+	if (isList())
+	{
+		bytesConstRef d = payload();
+		size_t i = 0;
+		for (; d.size(); ++i)
+			d = d.cropped(sizeAsEncoded(d));
+		return i;
+	}
+	return 0;
+}
+
+RLPStream& RLPStream::appendRaw(bytesConstRef _s, size_t _itemCount)
+{
+	m_out.insert(m_out.end(), _s.begin(), _s.end());
+	noteAppended(_itemCount);
+	return *this;
+}
+
+void RLPStream::noteAppended(size_t _itemCount)
+{
+	if (!_itemCount)
+		return;
+//	cdebug << "noteAppended(" << _itemCount << ")";
+	while (m_listStack.size())
+	{
+		if (m_listStack.back().first < _itemCount)
+			BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large") << RequirementError((bigint)m_listStack.back().first, (bigint)_itemCount));
+		m_listStack.back().first -= _itemCount;
+		if (m_listStack.back().first)
+			break;
+		else
+		{
+			auto p = m_listStack.back().second;
+			m_listStack.pop_back();
+			size_t s = m_out.size() - p;		// list size
+			auto brs = bytesRequired(s);
+			unsigned encodeSize = s < c_rlpListImmLenCount ? 1 : (1 + brs);
+//			cdebug << "s: " << s << ", p: " << p << ", m_out.size(): " << m_out.size() << ", encodeSize: " << encodeSize << " (br: " << brs << ")";
+			auto os = m_out.size();
+			m_out.resize(os + encodeSize);
+			memmove(m_out.data() + p + encodeSize, m_out.data() + p, os - p);
+			if (s < c_rlpListImmLenCount)
+				m_out[p] = (byte)(c_rlpListStart + s);
+			else if (c_rlpListIndLenZero + brs <= 0xff)
+			{
+				m_out[p] = (byte)(c_rlpListIndLenZero + brs);
+				byte* b = &(m_out[p + brs]);
+				for (; s; s >>= 8)
+					*(b--) = (byte)s;
+			}
+			else
+				BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large for RLP"));
+		}
+		_itemCount = 1;	// for all following iterations, we've effectively appended a single item only since we completed a list.
+	}
+}
+
+RLPStream& RLPStream::appendList(size_t _items)
+{
+//	cdebug << "appendList(" << _items << ")";
+	if (_items)
+		m_listStack.push_back(std::make_pair(_items, m_out.size()));
+	else
+		appendList(bytes());
+	return *this;
+}
+
+RLPStream& RLPStream::appendList(bytesConstRef _rlp)
+{
+	if (_rlp.size() < c_rlpListImmLenCount)
+		m_out.push_back((byte)(_rlp.size() + c_rlpListStart));
+	else
+		pushCount(_rlp.size(), c_rlpListIndLenZero);
+	appendRaw(_rlp, 1);
+	return *this;
+}
+
+RLPStream& RLPStream::append(bytesConstRef _s, bool _compact)
+{
+	size_t s = _s.size();
+	byte const* d = _s.data();
+	if (_compact)
+		for (size_t i = 0; i < _s.size() && !*d; ++i, --s, ++d) {}
+
+	if (s == 1 && *d < c_rlpDataImmLenStart)
+		m_out.push_back(*d);
+	else
+	{
+		if (s < c_rlpDataImmLenCount)
+			m_out.push_back((byte)(s + c_rlpDataImmLenStart));
+		else
+			pushCount(s, c_rlpDataIndLenZero);
+		appendRaw(bytesConstRef(d, s), 0);
+	}
+	noteAppended();
+	return *this;
+}
+
+RLPStream& RLPStream::append(bigint _i)
+{
+	if (!_i)
+		m_out.push_back(c_rlpDataImmLenStart);
+	else if (_i < c_rlpDataImmLenStart)
+		m_out.push_back((byte)_i);
+	else
+	{
+		unsigned br = bytesRequired(_i);
+		if (br < c_rlpDataImmLenCount)
+			m_out.push_back((byte)(br + c_rlpDataImmLenStart));
+		else
+		{
+			auto brbr = bytesRequired(br);
+			if (c_rlpDataIndLenZero + brbr > 0xff)
+				BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Number too large for RLP"));
+			m_out.push_back((byte)(c_rlpDataIndLenZero + brbr));
+			pushInt(br, brbr);
+		}
+		pushInt(_i, br);
+	}
+	noteAppended();
+	return *this;
+}
+
+void RLPStream::pushCount(size_t _count, byte _base)
+{
+	auto br = bytesRequired(_count);
+	if (int(br) + _base > 0xff)
+		BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("Count too large for RLP"));
+	m_out.push_back((byte)(br + _base));	// max 8 bytes.
+	pushInt(_count, br);
+}
+
+static void streamOut(std::ostream& _out, dev::RLP const& _d, unsigned _depth = 0)
+{
+	if (_depth > 64)
+		_out << "<max-depth-reached>";
+	else if (_d.isNull())
+		_out << "null";
+	else if (_d.isInt())
+		_out << std::showbase << std::hex << std::nouppercase << _d.toInt<bigint>(RLP::LaissezFaire) << dec;
+	else if (_d.isData())
+		_out << escaped(_d.toString(), false);
+	else if (_d.isList())
+	{
+		_out << "[";
+		int j = 0;
+		for (auto i: _d)
+		{
+			_out << (j++ ? ", " : " ");
+			streamOut(_out, i, _depth + 1);
+		}
+		_out << " ]";
+	}
+}
+
+std::ostream& dev::operator<<(std::ostream& _out, RLP const& _d)
+{
+	streamOut(_out, _d);
+	return _out;
+}
diff --git a/src/ringdht/eth/libdevcore/RLP.h b/src/ringdht/eth/libdevcore/RLP.h
new file mode 100644
index 0000000000000000000000000000000000000000..1416c4acd49c05ed482a345462376cfcc39edeb4
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/RLP.h
@@ -0,0 +1,487 @@
+/*
+	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 RLP.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * RLP (de-)serialisation.
+ */
+
+#pragma once
+
+#include <vector>
+#include <array>
+#include <exception>
+#include <iostream>
+#include <iomanip>
+#include "vector_ref.h"
+#include "Common.h"
+#include "Exceptions.h"
+#include "FixedHash.h"
+
+namespace dev
+{
+
+class RLP;
+using RLPs = std::vector<RLP>;
+
+template <class _T> struct intTraits { static const unsigned maxSize = sizeof(_T); };
+template <> struct intTraits<u160> { static const unsigned maxSize = 20; };
+template <> struct intTraits<u256> { static const unsigned maxSize = 32; };
+template <> struct intTraits<bigint> { static const unsigned maxSize = ~(unsigned)0; };
+
+static const byte c_rlpMaxLengthBytes = 8;
+static const byte c_rlpDataImmLenStart = 0x80;
+static const byte c_rlpListStart = 0xc0;
+
+static const byte c_rlpDataImmLenCount = c_rlpListStart - c_rlpDataImmLenStart - c_rlpMaxLengthBytes;
+static const byte c_rlpDataIndLenZero = c_rlpDataImmLenStart + c_rlpDataImmLenCount - 1;
+static const byte c_rlpListImmLenCount = 256 - c_rlpListStart - c_rlpMaxLengthBytes;
+static const byte c_rlpListIndLenZero = c_rlpListStart + c_rlpListImmLenCount - 1;
+
+template <class T> struct Converter { static T convert(RLP const&, int) { BOOST_THROW_EXCEPTION(BadCast()); } };
+
+/**
+ * @brief Class for interpreting Recursive Linear-Prefix Data.
+ * @by Gav Wood, 2013
+ *
+ * Class for reading byte arrays of data in RLP format.
+ */
+class RLP
+{
+public:
+	/// Conversion flags
+	enum
+	{
+		AllowNonCanon = 1,
+		ThrowOnFail = 4,
+		FailIfTooBig = 8,
+		FailIfTooSmall = 16,
+		Strict = ThrowOnFail | FailIfTooBig,
+		VeryStrict = ThrowOnFail | FailIfTooBig | FailIfTooSmall,
+		LaissezFaire = AllowNonCanon
+	};
+
+	using Strictness = int;
+
+	/// Construct a null node.
+	RLP() {}
+
+	/// Construct a node of value given in the bytes.
+	explicit RLP(bytesConstRef _d, Strictness _s = VeryStrict);
+
+	/// Construct a node of value given in the bytes.
+	explicit RLP(bytes const& _d, Strictness _s = VeryStrict): RLP(&_d, _s) {}
+
+	/// Construct a node to read RLP data in the bytes given.
+	RLP(byte const* _b, unsigned _s, Strictness _st = VeryStrict): RLP(bytesConstRef(_b, _s), _st) {}
+
+	/// Construct a node to read RLP data in the string.
+	explicit RLP(std::string const& _s, Strictness _st = VeryStrict): RLP(bytesConstRef((byte const*)_s.data(), _s.size()), _st) {}
+
+	/// The bare data of the RLP.
+	bytesConstRef data() const { return m_data; }
+
+	/// @returns true if the RLP is non-null.
+	explicit operator bool() const { return !isNull(); }
+
+	/// No value.
+	bool isNull() const { return m_data.size() == 0; }
+
+	/// Contains a zero-length string or zero-length list.
+	bool isEmpty() const { return !isNull() && (m_data[0] == c_rlpDataImmLenStart || m_data[0] == c_rlpListStart); }
+
+	/// String value.
+	bool isData() const { return !isNull() && m_data[0] < c_rlpListStart; }
+
+	/// List value.
+	bool isList() const { return !isNull() && m_data[0] >= c_rlpListStart; }
+
+	/// Integer value. Must not have a leading zero.
+	bool isInt() const;
+
+	/// @returns the number of items in the list, or zero if it isn't a list.
+	size_t itemCount() const { return isList() ? items() : 0; }
+	size_t itemCountStrict() const { if (!isList()) BOOST_THROW_EXCEPTION(BadCast()); return items(); }
+
+	/// @returns the number of bytes in the data, or zero if it isn't data.
+	size_t size() const { return isData() ? length() : 0; }
+	size_t sizeStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return length(); }
+
+	/// Equality operators; does best-effort conversion and checks for equality.
+	bool operator==(char const* _s) const { return isData() && toString() == _s; }
+	bool operator!=(char const* _s) const { return isData() && toString() != _s; }
+	bool operator==(std::string const& _s) const { return isData() && toString() == _s; }
+	bool operator!=(std::string const& _s) const { return isData() && toString() != _s; }
+	template <unsigned N> bool operator==(FixedHash<N> const& _h) const { return isData() && toHash<N>() == _h; }
+	template <unsigned N> bool operator!=(FixedHash<N> const& _s) const { return isData() && toHash<N>() != _s; }
+	bool operator==(unsigned const& _i) const { return isInt() && toInt<unsigned>() == _i; }
+	bool operator!=(unsigned const& _i) const { return isInt() && toInt<unsigned>() != _i; }
+	bool operator==(u256 const& _i) const { return isInt() && toInt<u256>() == _i; }
+	bool operator!=(u256 const& _i) const { return isInt() && toInt<u256>() != _i; }
+	bool operator==(bigint const& _i) const { return isInt() && toInt<bigint>() == _i; }
+	bool operator!=(bigint const& _i) const { return isInt() && toInt<bigint>() != _i; }
+
+	/// Subscript operator.
+	/// @returns the list item @a _i if isList() and @a _i < listItems(), or RLP() otherwise.
+	/// @note if used to access items in ascending order, this is efficient.
+	RLP operator[](size_t _i) const;
+
+	using element_type = RLP;
+
+	/// @brief Iterator class for iterating through items of RLP list.
+	class iterator
+	{
+		friend class RLP;
+
+	public:
+		using value_type = RLP;
+		using element_type = RLP;
+
+		iterator& operator++();
+		iterator operator++(int) { auto ret = *this; operator++(); return ret; }
+		RLP operator*() const { return RLP(m_currentItem); }
+		bool operator==(iterator const& _cmp) const { return m_currentItem == _cmp.m_currentItem; }
+		bool operator!=(iterator const& _cmp) const { return !operator==(_cmp); }
+
+	private:
+		iterator() {}
+		iterator(RLP const& _parent, bool _begin);
+
+		size_t m_remaining = 0;
+		bytesConstRef m_currentItem;
+	};
+
+	/// @brief Iterator into beginning of sub-item list (valid only if we are a list).
+	iterator begin() const { return iterator(*this, true); }
+
+	/// @brief Iterator into end of sub-item list (valid only if we are a list).
+	iterator end() const { return iterator(*this, false); }
+
+	template <class T> inline T convert(int _flags) const;
+
+	/// Best-effort conversion operators.
+	explicit operator std::string() const { return toString(); }
+	explicit operator bytes() const { return toBytes(); }
+	explicit operator RLPs() const { return toList(); }
+	explicit operator uint8_t() const { return toInt<uint8_t>(); }
+	explicit operator uint16_t() const { return toInt<uint16_t>(); }
+	explicit operator uint32_t() const { return toInt<uint32_t>(); }
+	explicit operator uint64_t() const { return toInt<uint64_t>(); }
+	explicit operator u160() const { return toInt<u160>(); }
+	explicit operator u256() const { return toInt<u256>(); }
+	explicit operator bigint() const { return toInt<bigint>(); }
+	template <unsigned N> explicit operator FixedHash<N>() const { return toHash<FixedHash<N>>(); }
+	template <class T, class U> explicit operator std::pair<T, U>() const { return toPair<T, U>(); }
+	template <class T> explicit operator std::vector<T>() const { return toVector<T>(); }
+	template <class T> explicit operator std::set<T>() const { return toSet<T>(); }
+	template <class T, size_t N> explicit operator std::array<T, N>() const { return toArray<T, N>(); }
+
+	/// Converts to bytearray. @returns the empty byte array if not a string.
+	bytes toBytes(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return bytes(); } return bytes(payload().data(), payload().data() + length()); }
+	/// Converts to bytearray. @returns the empty byte array if not a string.
+	bytesConstRef toBytesConstRef(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return bytesConstRef(); } return payload().cropped(0, length()); }
+	/// Converts to string. @returns the empty string if not a string.
+	std::string toString(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return std::string(); } return payload().cropped(0, length()).toString(); }
+	/// Converts to string. @throws BadCast if not a string.
+	std::string toStringStrict() const { return toString(Strict); }
+
+	template <class T>
+	std::vector<T> toVector(int _flags = LaissezFaire) const
+	{
+		std::vector<T> ret;
+		if (isList())
+		{
+			ret.reserve(itemCount());
+			for (auto const& i: *this)
+				ret.push_back(i.convert<T>(_flags));
+		 }
+		else if (_flags & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(BadCast());
+		 return ret;
+	}
+
+	template <class T>
+	std::set<T> toSet(int _flags = LaissezFaire) const
+	{
+		std::set<T> ret;
+		if (isList())
+			for (auto const& i: *this)
+				ret.insert(i.convert<T>(_flags));
+		else if (_flags & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(BadCast());
+		return ret;
+	}
+
+	template <class T>
+	std::unordered_set<T> toUnorderedSet(int _flags = LaissezFaire) const
+	{
+		std::unordered_set<T> ret;
+		if (isList())
+			for (auto const& i: *this)
+				ret.insert(i.convert<T>(_flags));
+		else if (_flags & ThrowOnFail)
+			BOOST_THROW_EXCEPTION(BadCast());
+		return ret;
+	}
+
+	template <class T, class U>
+	std::pair<T, U> toPair(int _flags = Strict) const
+	{
+		std::pair<T, U> ret;
+		if (itemCountStrict() != 2)
+		{
+			if (_flags & ThrowOnFail)
+				BOOST_THROW_EXCEPTION(BadCast());
+			else
+				return ret;
+		}
+		ret.first = (*this)[0].convert<T>(_flags);
+		ret.second = (*this)[1].convert<U>(_flags);
+		return ret;
+	}
+
+	template <class T, size_t N>
+	std::array<T, N> toArray(int _flags = LaissezFaire) const
+	{
+		if (itemCountStrict() != N)
+		{
+			if (_flags & ThrowOnFail)
+				BOOST_THROW_EXCEPTION(BadCast());
+			else
+				return std::array<T, N>();
+		}
+		std::array<T, N> ret;
+		for (size_t i = 0; i < N; ++i)
+			ret[i] = operator[](i).convert<T>(_flags);
+		return ret;
+	}
+
+	/// Converts to int of type given; if isString(), decodes as big-endian bytestream. @returns 0 if not an int or string.
+	template <class T = unsigned> T toInt(int _flags = Strict) const
+	{
+		requireGood();
+		if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull())
+		{
+			if (_flags & ThrowOnFail)
+				BOOST_THROW_EXCEPTION(BadCast());
+			else
+				return 0;
+		}
+
+		auto p = payload();
+		if (p.size() > intTraits<T>::maxSize && (_flags & FailIfTooBig))
+		{
+			if (_flags & ThrowOnFail)
+				BOOST_THROW_EXCEPTION(BadCast());
+			else
+				return 0;
+		}
+
+		return fromBigEndian<T>(p);
+	}
+
+	template <class N> N toHash(int _flags = Strict) const
+	{
+		requireGood();
+		auto p = payload();
+		auto l = p.size();
+		if (!isData() || (l > N::size && (_flags & FailIfTooBig)) || (l < N::size && (_flags & FailIfTooSmall)))
+		{
+			if (_flags & ThrowOnFail)
+				BOOST_THROW_EXCEPTION(BadCast());
+			else
+				return N();
+		}
+
+		N ret;
+		size_t s = std::min<size_t>(N::size, l);
+		memcpy(ret.data() + N::size - s, p.data(), s);
+		return ret;
+	}
+
+	/// Converts to RLPs collection object. Useful if you need random access to sub items or will iterate over multiple times.
+	RLPs toList(int _flags = Strict) const;
+
+	/// @returns the data payload. Valid for all types.
+	bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP()); return m_data.cropped(payloadOffset(), l); }
+
+	/// @returns the theoretical size of this item as encoded in the data.
+	/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
+	size_t actualSize() const;
+
+private:
+	/// Disable construction from rvalue
+	explicit RLP(bytes const&&) {}
+
+	/// Throws if is non-canonical data (i.e. single byte done in two bytes that could be done in one).
+	void requireGood() const;
+
+	/// Single-byte data payload.
+	bool isSingleByte() const { return !isNull() && m_data[0] < c_rlpDataImmLenStart; }
+
+	/// @returns the amount of bytes used to encode the length of the data. Valid for all types.
+	unsigned lengthSize() const { if (isData() && m_data[0] > c_rlpDataIndLenZero) return m_data[0] - c_rlpDataIndLenZero; if (isList() && m_data[0] > c_rlpListIndLenZero) return m_data[0] - c_rlpListIndLenZero; return 0; }
+
+	/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.
+	size_t length() const;
+
+	/// @returns the number of bytes into the data that the payload starts.
+	size_t payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); }
+
+	/// @returns the number of data items.
+	size_t items() const;
+
+	/// @returns the size encoded into the RLP in @a _data and throws if _data is too short.
+	static size_t sizeAsEncoded(bytesConstRef _data) { return RLP(_data, ThrowOnFail | FailIfTooSmall).actualSize(); }
+
+	/// Our byte data.
+	bytesConstRef m_data;
+
+	/// The list-indexing cache.
+	mutable size_t m_lastIndex = (size_t)-1;
+	mutable size_t m_lastEnd = 0;
+	mutable bytesConstRef m_lastItem;
+};
+
+template <> struct Converter<std::string> { static std::string convert(RLP const& _r, int _flags) { return _r.toString(_flags); } };
+template <> struct Converter<bytes> { static bytes convert(RLP const& _r, int _flags) { return _r.toBytes(_flags); } };
+template <> struct Converter<RLPs> { static RLPs convert(RLP const& _r, int _flags) { return _r.toList(_flags); } };
+template <> struct Converter<uint8_t> { static uint8_t convert(RLP const& _r, int _flags) { return _r.toInt<uint8_t>(_flags); } };
+template <> struct Converter<uint16_t> { static uint16_t convert(RLP const& _r, int _flags) { return _r.toInt<uint16_t>(_flags); } };
+template <> struct Converter<uint32_t> { static uint32_t convert(RLP const& _r, int _flags) { return _r.toInt<uint32_t>(_flags); } };
+template <> struct Converter<uint64_t> { static uint64_t convert(RLP const& _r, int _flags) { return _r.toInt<uint64_t>(_flags); } };
+template <> struct Converter<u160> { static u160 convert(RLP const& _r, int _flags) { return _r.toInt<u160>(_flags); } };
+template <> struct Converter<u256> { static u256 convert(RLP const& _r, int _flags) { return _r.toInt<u256>(_flags); } };
+template <> struct Converter<bigint> { static bigint convert(RLP const& _r, int _flags) { return _r.toInt<bigint>(_flags); } };
+template <unsigned N> struct Converter<FixedHash<N>> { static FixedHash<N> convert(RLP const& _r, int _flags) { return _r.toHash<FixedHash<N>>(_flags); } };
+template <class T, class U> struct Converter<std::pair<T, U>> { static std::pair<T, U> convert(RLP const& _r, int _flags) { return _r.toPair<T, U>(_flags); } };
+template <class T> struct Converter<std::vector<T>> { static std::vector<T> convert(RLP const& _r, int _flags) { return _r.toVector<T>(_flags); } };
+template <class T> struct Converter<std::set<T>> { static std::set<T> convert(RLP const& _r, int _flags) { return _r.toSet<T>(_flags); } };
+template <class T> struct Converter<std::unordered_set<T>> { static std::unordered_set<T> convert(RLP const& _r, int _flags) { return _r.toUnorderedSet<T>(_flags); } };
+template <class T, size_t N> struct Converter<std::array<T, N>> { static std::array<T, N> convert(RLP const& _r, int _flags) { return _r.toArray<T, N>(_flags); } };
+
+template <class T> inline T RLP::convert(int _flags) const { return Converter<T>::convert(*this, _flags); }
+
+/**
+ * @brief Class for writing to an RLP bytestream.
+ */
+class RLPStream
+{
+public:
+	/// Initializes empty RLPStream.
+	RLPStream() {}
+
+	/// Initializes the RLPStream as a list of @a _listItems items.
+	explicit RLPStream(size_t _listItems) { appendList(_listItems); }
+
+	~RLPStream() {}
+
+	/// Append given datum to the byte stream.
+	RLPStream& append(unsigned _s) { return append(bigint(_s)); }
+	RLPStream& append(u160 _s) { return append(bigint(_s)); }
+	RLPStream& append(u256 _s) { return append(bigint(_s)); }
+	RLPStream& append(bigint _s);
+	RLPStream& append(bytesConstRef _s, bool _compact = false);
+	RLPStream& append(bytes const& _s) { return append(bytesConstRef(&_s)); }
+	RLPStream& append(std::string const& _s) { return append(bytesConstRef(_s)); }
+	RLPStream& append(char const* _s) { return append(std::string(_s)); }
+	template <unsigned N> RLPStream& append(FixedHash<N> _s, bool _compact = false, bool _allOrNothing = false) { return _allOrNothing && !_s ? append(bytesConstRef()) : append(_s.ref(), _compact); }
+
+	/// Appends an arbitrary RLP fragment - this *must* be a single item unless @a _itemCount is given.
+	RLPStream& append(RLP const& _rlp, size_t _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); }
+
+	/// Appends a sequence of data to the stream as a list.
+	template <class _T> RLPStream& append(std::vector<_T> const& _s) { return appendVector(_s); }
+	template <class _T> RLPStream& appendVector(std::vector<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
+	template <class _T, size_t S> RLPStream& append(std::array<_T, S> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
+	template <class _T> RLPStream& append(std::set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
+	template <class _T> RLPStream& append(std::unordered_set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
+	template <class T, class U> RLPStream& append(std::pair<T, U> const& _s) { appendList(2); append(_s.first); append(_s.second); return *this; }
+
+	/// Appends a list.
+	RLPStream& appendList(size_t _items);
+	RLPStream& appendList(bytesConstRef _rlp);
+	RLPStream& appendList(bytes const& _rlp) { return appendList(&_rlp); }
+	RLPStream& appendList(RLPStream const& _s) { return appendList(&_s.out()); }
+
+	/// Appends raw (pre-serialised) RLP data. Use with caution.
+	RLPStream& appendRaw(bytesConstRef _rlp, size_t _itemCount = 1);
+	RLPStream& appendRaw(bytes const& _rlp, size_t _itemCount = 1) { return appendRaw(&_rlp, _itemCount); }
+
+	/// Shift operators for appending data items.
+	template <class T> RLPStream& operator<<(T _data) { return append(_data); }
+
+	/// Clear the output stream so far.
+	void clear() { m_out.clear(); m_listStack.clear(); }
+
+	/// Read the byte stream.
+	bytes const& out() const { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return m_out; }
+
+	/// Invalidate the object and steal the output byte stream.
+	bytes&& invalidate() { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return std::move(m_out); }
+
+	/// Swap the contents of the output stream out for some other byte array.
+	void swapOut(bytes& _dest) { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); swap(m_out, _dest); }
+
+private:
+	void noteAppended(size_t _itemCount = 1);
+
+	/// Push the node-type byte (using @a _base) along with the item count @a _count.
+	/// @arg _count is number of characters for strings, data-bytes for ints, or items for lists.
+	void pushCount(size_t _count, byte _offset);
+
+	/// Push an integer as a raw big-endian byte-stream.
+	template <class _T> void pushInt(_T _i, size_t _br)
+	{
+		m_out.resize(m_out.size() + _br);
+		byte* b = &m_out.back();
+		for (; _i; _i >>= 8)
+			*(b--) = (byte)_i;
+	}
+
+	/// Our output byte stream.
+	bytes m_out;
+
+	std::vector<std::pair<size_t, size_t>> m_listStack;
+};
+
+template <class _T> void rlpListAux(RLPStream& _out, _T _t) { _out << _t; }
+template <class _T, class ... _Ts> void rlpListAux(RLPStream& _out, _T _t, _Ts ... _ts) { rlpListAux(_out << _t, _ts...); }
+
+/// Export a single item in RLP format, returning a byte array.
+template <class _T> bytes rlp(_T _t) { return (RLPStream() << _t).out(); }
+
+/// Export a list of items in RLP format, returning a byte array.
+inline bytes rlpList() { return RLPStream(0).out(); }
+template <class ... _Ts> bytes rlpList(_Ts ... _ts)
+{
+	RLPStream out(sizeof ...(_Ts));
+	rlpListAux(out, _ts...);
+	return out.out();
+}
+
+/// The empty string in RLP format.
+extern bytes RLPNull;
+
+/// The empty list in RLP format.
+extern bytes RLPEmptyList;
+
+/// Human readable version of RLP.
+std::ostream& operator<<(std::ostream& _out, dev::RLP const& _d);
+
+}
diff --git a/src/ringdht/eth/libdevcore/SHA3.cpp b/src/ringdht/eth/libdevcore/SHA3.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5072cc2110ffe44c904b28a5d999d439da36d596
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/SHA3.cpp
@@ -0,0 +1,227 @@
+/*
+	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 SHA3.cpp
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "SHA3.h"
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include "RLP.h"
+#include "picosha2.h"
+using namespace std;
+using namespace dev;
+
+namespace dev
+{
+
+h256 EmptySHA3 = sha3(bytesConstRef());
+h256 EmptyListSHA3 = sha3(rlpList());
+
+namespace keccak
+{
+
+/** libkeccak-tiny
+ *
+ * A single-file implementation of SHA-3 and SHAKE.
+ *
+ * Implementor: David Leon Gil
+ * License: CC0, attribution kindly requested. Blame taken too,
+ * but not liability.
+ */
+
+#define decshake(bits) \
+  int shake##bits(uint8_t*, size_t, const uint8_t*, size_t);
+
+#define decsha3(bits) \
+  int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t);
+
+decshake(128)
+decshake(256)
+decsha3(224)
+decsha3(256)
+decsha3(384)
+decsha3(512)
+
+/******** The Keccak-f[1600] permutation ********/
+
+/*** Constants. ***/
+static const uint8_t rho[24] = \
+  { 1,  3,   6, 10, 15, 21,
+	28, 36, 45, 55,  2, 14,
+	27, 41, 56,  8, 25, 43,
+	62, 18, 39, 61, 20, 44};
+static const uint8_t pi[24] = \
+  {10,  7, 11, 17, 18, 3,
+	5, 16,  8, 21, 24, 4,
+   15, 23, 19, 13, 12, 2,
+   20, 14, 22,  9, 6,  1};
+static const uint64_t RC[24] = \
+  {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
+   0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
+   0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
+   0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
+   0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
+   0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
+
+/*** Helper macros to unroll the permutation. ***/
+#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
+#define REPEAT6(e) e e e e e e
+#define REPEAT24(e) REPEAT6(e e e e)
+#define REPEAT5(e) e e e e e
+#define FOR5(v, s, e) \
+  v = 0;            \
+  REPEAT5(e; v += s;)
+
+/*** Keccak-f[1600] ***/
+static inline void keccakf(void* state) {
+  uint64_t* a = (uint64_t*)state;
+  uint64_t b[5] = {0};
+  uint64_t t = 0;
+  uint8_t x, y;
+
+  for (int i = 0; i < 24; i++) {
+	// Theta
+	FOR5(x, 1,
+		 b[x] = 0;
+		 FOR5(y, 5,
+			  b[x] ^= a[x + y]; ))
+	FOR5(x, 1,
+		 FOR5(y, 5,
+			  a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
+	// Rho and pi
+	t = a[1];
+	x = 0;
+	REPEAT24(b[0] = a[pi[x]];
+			 a[pi[x]] = rol(t, rho[x]);
+			 t = b[0];
+			 x++; )
+	// Chi
+	FOR5(y,
+	   5,
+	   FOR5(x, 1,
+			b[x] = a[y + x];)
+	   FOR5(x, 1,
+			a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
+	// Iota
+	a[0] ^= RC[i];
+  }
+}
+
+/******** The FIPS202-defined functions. ********/
+
+/*** Some helper macros. ***/
+
+#define _(S) do { S } while (0)
+#define FOR(i, ST, L, S) \
+  _(for (size_t i = 0; i < L; i += ST) { S; })
+#define mkapply_ds(NAME, S)                                          \
+  static inline void NAME(uint8_t* dst,                              \
+						  const uint8_t* src,                        \
+						  size_t len) {                              \
+	FOR(i, 1, len, S);                                               \
+  }
+#define mkapply_sd(NAME, S)                                          \
+  static inline void NAME(const uint8_t* src,                        \
+						  uint8_t* dst,                              \
+						  size_t len) {                              \
+	FOR(i, 1, len, S);                                               \
+  }
+
+mkapply_ds(xorin, dst[i] ^= src[i])  // xorin
+mkapply_sd(setout, dst[i] = src[i])  // setout
+
+#define P keccakf
+#define Plen 200
+
+// Fold P*F over the full blocks of an input.
+#define foldP(I, L, F) \
+  while (L >= rate) {  \
+	F(a, I, rate);     \
+	P(a);              \
+	I += rate;         \
+	L -= rate;         \
+  }
+
+/** The sponge-based hash construction. **/
+static inline int hash(uint8_t* out, size_t outlen,
+					   const uint8_t* in, size_t inlen,
+					   size_t rate, uint8_t delim) {
+  if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
+	return -1;
+  }
+  uint8_t a[Plen] = {0};
+  // Absorb input.
+  foldP(in, inlen, xorin);
+  // Xor in the DS and pad frame.
+  a[inlen] ^= delim;
+  a[rate - 1] ^= 0x80;
+  // Xor in the last block.
+  xorin(a, in, inlen);
+  // Apply P
+  P(a);
+  // Squeeze output.
+  foldP(out, outlen, setout);
+  setout(a, out, outlen);
+  memset(a, 0, 200);
+  return 0;
+}
+
+/*** Helper macros to define SHA3 and SHAKE instances. ***/
+#define defshake(bits)                                            \
+  int shake##bits(uint8_t* out, size_t outlen,                    \
+				  const uint8_t* in, size_t inlen) {              \
+	return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f);  \
+  }
+#define defsha3(bits)                                             \
+  int sha3_##bits(uint8_t* out, size_t outlen,                    \
+				  const uint8_t* in, size_t inlen) {              \
+	if (outlen > (bits/8)) {                                      \
+	  return -1;                                                  \
+	}                                                             \
+	return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01);  \
+  }
+
+/*** FIPS202 SHAKE VOFs ***/
+defshake(128)
+defshake(256)
+
+/*** FIPS202 SHA3 FOFs ***/
+defsha3(224)
+defsha3(256)
+defsha3(384)
+defsha3(512)
+
+}
+
+unsigned g_sha3Counter = 0;
+
+bool sha3(bytesConstRef _input, bytesRef o_output)
+{
+	// FIXME: What with unaligned memory?
+	if (o_output.size() != 32)
+		return false;
+	++g_sha3Counter;
+	keccak::sha3_256(o_output.data(), 32, _input.data(), _input.size());
+//	keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size());
+	return true;
+}
+
+}
diff --git a/src/ringdht/eth/libdevcore/SHA3.h b/src/ringdht/eth/libdevcore/SHA3.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ceb6f890d548fe7a32a7f09cea7fbe00df1c264
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/SHA3.h
@@ -0,0 +1,73 @@
+/*
+	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 SHA3.h
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * The FixedHash fixed-size "hash" container type.
+ */
+
+#pragma once
+
+#include <string>
+#include "FixedHash.h"
+#include "vector_ref.h"
+
+namespace dev
+{
+
+// SHA-3 convenience routines.
+
+/// Calculate SHA3-256 hash of the given input and load it into the given output.
+/// @returns false if o_output.size() != 32.
+bool sha3(bytesConstRef _input, bytesRef o_output);
+
+/// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash.
+inline h256 sha3(bytesConstRef _input) { h256 ret; sha3(_input, ret.ref()); return ret; }
+inline SecureFixedHash<32> sha3Secure(bytesConstRef _input) { SecureFixedHash<32> ret; sha3(_input, ret.writable().ref()); return ret; }
+
+/// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash.
+inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef(&_input)); }
+inline SecureFixedHash<32> sha3Secure(bytes const& _input) { return sha3Secure(bytesConstRef(&_input)); }
+
+/// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
+inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
+inline SecureFixedHash<32> sha3Secure(std::string const& _input) { return sha3Secure(bytesConstRef(_input)); }
+
+/// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
+template<unsigned N> inline h256 sha3(FixedHash<N> const& _input) { return sha3(_input.ref()); }
+template<unsigned N> inline SecureFixedHash<32> sha3Secure(FixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
+
+/// Fully secure variants are equivalent for sha3 and sha3Secure.
+inline SecureFixedHash<32> sha3(bytesSec const& _input) { return sha3Secure(_input.ref()); }
+inline SecureFixedHash<32> sha3Secure(bytesSec const& _input) { return sha3Secure(_input.ref()); }
+template<unsigned N> inline SecureFixedHash<32> sha3(SecureFixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
+template<unsigned N> inline SecureFixedHash<32> sha3Secure(SecureFixedHash<N> const& _input) { return sha3Secure(_input.ref()); }
+
+/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data.
+inline std::string sha3(std::string const& _input, bool _isNibbles) { return asString((_isNibbles ? sha3(fromHex(_input)) : sha3(bytesConstRef(&_input))).asBytes()); }
+
+/// Calculate SHA3-256 MAC
+inline void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) { sha3(_secret.toBytes() + _plain.toBytes()).ref().populate(_output); }
+
+extern h256 EmptySHA3;
+
+extern h256 EmptyListSHA3;
+
+extern unsigned g_sha3Counter;
+
+}
diff --git a/src/ringdht/eth/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp b/src/ringdht/eth/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..dae591dfb884121584f2816abf979c60562ffc0c
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp
@@ -0,0 +1,520 @@
+
+// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58. 
+
+#ifdef BOOST_MP_COMPARE_HPP
+#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp 
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+//  Copyright 2012 John Maddock. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MP_COMPARE_HPP
+#define BOOST_MP_COMPARE_HPP
+
+// A copy of boost/multiprecision/traits/is_backend.hpp
+#ifndef BOOST_MP_IS_BACKEND_HPP
+#define BOOST_MP_IS_BACKEND_HPP
+
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/generic_interconvert.hpp>
+
+namespace boost{ namespace multiprecision{  namespace detail{
+
+   BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types)
+   BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types)
+   BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types)
+
+   template <class T>
+   struct is_backend
+   {
+      static const bool value = has_signed_types<T>::value && has_unsigned_types<T>::value && has_float_types<T>::value;
+   };
+
+   template <class Backend>
+   struct other_backend
+   {
+      typedef typename boost::conditional<
+         boost::is_same<number<Backend>, number<Backend, et_on> >::value,
+         number<Backend, et_off>, number<Backend, et_on> >::type type;
+   };
+
+   template <class B, class V>
+   struct number_from_backend
+   {
+      typedef typename boost::conditional <
+         boost::is_convertible<V, number<B> >::value,
+         number<B>,
+         typename other_backend<B>::type > ::type type;
+   };
+
+   template <bool b, class T, class U>
+   struct is_first_backend_imp{ static const bool value = false; };
+   template <class T, class U>
+   struct is_first_backend_imp<true, T, U>{ static const bool value = is_convertible<U, number<T, et_on> >::value || is_convertible<U, number<T, et_off> >::value; };
+
+   template <class T, class U>
+   struct is_first_backend : is_first_backend_imp<is_backend<T>::value, T, U> {};
+
+   template <bool b, class T, class U>
+   struct is_second_backend_imp{ static const bool value = false; };
+   template <class T, class U>
+   struct is_second_backend_imp<true, T, U>{ static const bool value = is_convertible<T, number<U> >::value || is_convertible<T, number<U, et_off> >::value; };
+
+   template <class T, class U>
+   struct is_second_backend : is_second_backend_imp<is_backend<U>::value, T, U> {};
+
+}
+}
+}
+
+#endif // BOOST_MP_IS_BACKEND_HPP
+
+//
+// Comparison operators for number.
+//
+
+namespace boost{ namespace multiprecision{
+
+namespace default_ops{
+
+template <class B>
+inline bool eval_eq(const B& a, const B& b)
+{
+   return a.compare(b) == 0;
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_eq(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
+   return eval_eq(a, t.backend());
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_eq(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+   return eval_eq(t.backend(), b);
+}
+
+template <class B>
+inline bool eval_lt(const B& a, const B& b)
+{
+   return a.compare(b) < 0;
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_lt(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
+   return eval_lt(a, t.backend());
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_lt(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+   return eval_lt(t.backend(), b);
+}
+
+template <class B>
+inline bool eval_gt(const B& a, const B& b)
+{
+   return a.compare(b) > 0;
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_first_backend<T, U>::value, bool>::type eval_gt(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
+   return eval_gt(a, t.backend());
+}
+template <class T, class U>
+inline typename enable_if_c<boost::multiprecision::detail::is_second_backend<T, U>::value, bool>::type eval_gt(const T& a, const U& b)
+{
+   typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+   return eval_gt(t.backend(), b);
+}
+
+} // namespace default_ops
+
+namespace detail{
+
+template <class Num, class Val>
+struct is_valid_mixed_compare : public mpl::false_ {};
+
+template <class B, expression_template_option ET, class Val>
+struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> > {};
+
+template <class B, expression_template_option ET>
+struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {};
+
+template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > 
+   : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
+struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > 
+   : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+
+template <class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
+{
+   return false;
+}
+template <class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
+{
+   using default_ops::eval_fpclassify;
+   return eval_fpclassify(a.backend()) == FP_NAN;
+}
+
+template <class Arithmetic>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
+{
+   return false;
+}
+template <class Arithmetic>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value == number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic& a)
+{
+   return (boost::math::isnan)(a);
+}
+
+template <class T, class U>
+inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b)
+{
+   return is_unordered_value(a) || is_unordered_value(b);
+}
+
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_eq(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_eq;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return false;
+   return eval_eq(t.backend(), result_type::canonical_value(a));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_eq;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return false;
+   return eval_eq(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_eq;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return false;
+   return eval_eq(t.backend(), t2.backend());
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return true;
+   return !eval_eq(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return true;
+   return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_eq;
+   if(detail::is_unordered_comparison(a, b)) return true;
+   return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_eq;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return true;
+   return !eval_eq(t.backend(), result_type::canonical_value(a));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_eq;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return true;
+   return !eval_eq(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_eq;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return true;
+   return !eval_eq(t.backend(), t2.backend());
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_lt(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_gt;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return false;
+   return eval_gt(t.backend(), result_type::canonical_value(a));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_lt;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return false;
+   return eval_lt(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_lt;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return false;
+   return eval_lt(t.backend(), t2.backend());
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_gt(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_lt;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return false;
+   return a > t;
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_gt;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return false;
+   return t > b;
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_gt;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return false;
+   return t > t2;
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_gt(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_lt;
+   if(detail::is_unordered_value(a) || detail::is_unordered_value(b))
+      return false;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return false;
+   return !eval_lt(t.backend(), result_type::canonical_value(a));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_gt;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return false;
+   return !eval_gt(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_gt;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return false;
+   return !eval_gt(t.backend(), t2.backend());
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_lt(a.backend(), b.backend());
+}
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+   using default_ops::eval_lt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
+}
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type 
+   operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+   using default_ops::eval_gt;
+   if(detail::is_unordered_comparison(a, b)) return false;
+   return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
+}
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_gt;
+   result_type t(b);
+   if(detail::is_unordered_comparison(a, t)) return false;
+   return !eval_gt(t.backend(), result_type::canonical_value(a));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type 
+   operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
+{
+   typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
+   using default_ops::eval_lt;
+   result_type t(a);
+   if(detail::is_unordered_comparison(t, b)) return false;
+   return !eval_lt(t.backend(), result_type::canonical_value(b));
+}
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type 
+   operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
+{
+   using default_ops::eval_lt;
+   typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
+   typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+   if(detail::is_unordered_comparison(t, t2)) return false;
+   return !eval_lt(t.backend(), t2.backend());
+}
+
+
+}} // namespaces
+
+#endif // BOOST_MP_COMPARE_HPP
diff --git a/src/ringdht/eth/libdevcore/picosha2.h b/src/ringdht/eth/libdevcore/picosha2.h
new file mode 100644
index 0000000000000000000000000000000000000000..44b6bee5947a69500c199d7f5fb4e193ed7ffee1
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/picosha2.h
@@ -0,0 +1,360 @@
+/*
+The MIT License (MIT)
+
+Copyright (C) 2014 okdshin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef PICOSHA2_H
+#define PICOSHA2_H
+//picosha2:20140213
+#include <cstdint>
+#include <iostream>
+#include <vector>
+#include <iterator>
+#include <cassert>
+#include <sstream>
+#include <algorithm>
+
+namespace picosha2
+{
+
+namespace detail 
+{
+
+inline uint8_t mask_8bit(uint8_t x){
+	return x&0xff;
+}
+
+inline uint32_t mask_32bit(uint32_t x){
+	return x&0xffffffff;
+}
+
+static const uint32_t add_constant[64] = {
+	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static const uint32_t initial_message_digest[8] = {
+	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 
+	0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+};
+
+inline uint32_t ch(uint32_t x, uint32_t y, uint32_t z){
+	return (x&y)^((~x)&z);
+}
+
+inline uint32_t maj(uint32_t x, uint32_t y, uint32_t z){
+	return (x&y)^(x&z)^(y&z);
+}
+
+inline uint32_t rotr(uint32_t x, std::size_t n){
+	assert(n < 32);
+	return mask_32bit((x>>n)|(x<<(32-n)));
+}
+
+inline uint32_t bsig0(uint32_t x){
+	return rotr(x, 2)^rotr(x, 13)^rotr(x, 22);
+}
+
+inline uint32_t bsig1(uint32_t x){
+	return rotr(x, 6)^rotr(x, 11)^rotr(x, 25);
+}
+
+inline uint32_t shr(uint32_t x, std::size_t n){
+	assert(n < 32);
+	return x >> n;
+}
+
+inline uint32_t ssig0(uint32_t x){
+	return rotr(x, 7)^rotr(x, 18)^shr(x, 3);
+}
+
+inline uint32_t ssig1(uint32_t x){
+	return rotr(x, 17)^rotr(x, 19)^shr(x, 10);
+}
+
+template<typename RaIter1, typename RaIter2>
+void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last){
+	(void)last; // FIXME: check this is valid
+	uint32_t w[64];
+	std::fill(w, w+64, 0);
+	for(std::size_t i = 0; i < 16; ++i){
+		w[i] = (static_cast<uint32_t>(mask_8bit(*(first+i*4)))<<24)
+			|(static_cast<uint32_t>(mask_8bit(*(first+i*4+1)))<<16)
+			|(static_cast<uint32_t>(mask_8bit(*(first+i*4+2)))<<8)
+			|(static_cast<uint32_t>(mask_8bit(*(first+i*4+3))));
+	}
+	for(std::size_t i = 16; i < 64; ++i){
+		w[i] = mask_32bit(ssig1(w[i-2])+w[i-7]+ssig0(w[i-15])+w[i-16]);
+	}
+	
+	uint32_t a = *message_digest;
+	uint32_t b = *(message_digest+1);
+	uint32_t c = *(message_digest+2);
+	uint32_t d = *(message_digest+3);
+	uint32_t e = *(message_digest+4);
+	uint32_t f = *(message_digest+5);
+	uint32_t g = *(message_digest+6);
+	uint32_t h = *(message_digest+7);
+	
+	for(std::size_t i = 0; i < 64; ++i){
+		uint32_t temp1 = h+bsig1(e)+ch(e,f,g)+add_constant[i]+w[i];
+		uint32_t temp2 = bsig0(a)+maj(a,b,c);
+		h = g;
+		g = f;
+		f = e;
+		e = mask_32bit(d+temp1);
+		d = c;
+		c = b;
+		b = a;
+		a = mask_32bit(temp1+temp2);
+	}
+	*message_digest += a;
+	*(message_digest+1) += b;
+	*(message_digest+2) += c;
+	*(message_digest+3) += d;
+	*(message_digest+4) += e;
+	*(message_digest+5) += f;
+	*(message_digest+6) += g;
+	*(message_digest+7) += h;
+	for(std::size_t i = 0; i < 8; ++i){
+		*(message_digest+i) = mask_32bit(*(message_digest+i));
+	}
+}
+
+}//namespace detail
+
+template<typename InIter>
+void output_hex(InIter first, InIter last, std::ostream& os){
+	os.setf(std::ios::hex, std::ios::basefield);
+	while(first != last){
+		os.width(2);
+		os.fill('0');
+		os << static_cast<unsigned int>(*first);
+		++first;
+	}	
+	os.setf(std::ios::dec, std::ios::basefield);
+}
+
+template<typename InIter>
+void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str){
+	std::ostringstream oss;
+	output_hex(first, last, oss);
+	hex_str.assign(oss.str());
+}
+
+template<typename InContainer>
+void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str){
+	bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
+}
+
+template<typename InIter>
+std::string bytes_to_hex_string(InIter first, InIter last){
+	std::string hex_str;
+	bytes_to_hex_string(first, last, hex_str);
+	return hex_str;
+}
+
+template<typename InContainer>
+std::string bytes_to_hex_string(const InContainer& bytes){
+	std::string hex_str;
+	bytes_to_hex_string(bytes, hex_str);
+	return hex_str;
+}
+
+class hash256_one_by_one {
+public:
+	hash256_one_by_one(){
+		init();
+	}
+
+	void init(){
+		buffer_.clear();
+		std::fill(data_length_digits_, data_length_digits_+4, 0);
+		std::copy(detail::initial_message_digest, detail::initial_message_digest+8, h_);
+	}
+
+	template<typename RaIter>
+	void process(RaIter first, RaIter last){
+		add_to_data_length(std::distance(first, last));
+		std::copy(first, last, std::back_inserter(buffer_));
+		std::size_t i = 0;
+		for(;i+64 <= buffer_.size(); i+=64){
+			detail::hash256_block(h_, buffer_.begin()+i, buffer_.begin()+i+64);	
+		}
+		buffer_.erase(buffer_.begin(), buffer_.begin()+i);
+	}
+
+	void finish(){
+		uint8_t temp[64];
+		std::fill(temp, temp+64, 0);
+		std::size_t remains = buffer_.size();
+		std::copy(buffer_.begin(), buffer_.end(), temp);
+		temp[remains] = 0x80;
+
+		if(remains > 55){
+			std::fill(temp+remains+1, temp+64, 0);
+			detail::hash256_block(h_, temp, temp+64);
+			std::fill(temp, temp+64-4, 0);
+		}
+		else {
+			std::fill(temp+remains+1, temp+64-4, 0);
+		}
+
+		write_data_bit_length(&(temp[56]));
+		detail::hash256_block(h_, temp, temp+64);
+	}
+
+	template<typename OutIter>
+	void get_hash_bytes(OutIter first, OutIter last)const{
+		for(const uint32_t* iter = h_; iter != h_+8; ++iter){
+			for(std::size_t i = 0; i < 4 && first != last; ++i){
+				*(first++) = detail::mask_8bit(static_cast<uint8_t>((*iter >> (24-8*i))));
+			}
+		}
+	}
+
+private:
+	void add_to_data_length(uint32_t n) {
+		uint32_t carry = 0;
+		data_length_digits_[0] += n;
+		for(std::size_t i = 0; i < 4; ++i) {
+			data_length_digits_[i] += carry;
+			if(data_length_digits_[i] >= 65536u) {
+				data_length_digits_[i] -= 65536u;
+				carry = 1;
+			}
+			else {
+				break;
+			}
+		}
+	}
+	void write_data_bit_length(uint8_t* begin) {
+		uint32_t data_bit_length_digits[4];
+		std::copy(
+			data_length_digits_, data_length_digits_+4, 
+			data_bit_length_digits
+		);
+
+		// convert byte length to bit length (multiply 8 or shift 3 times left)
+		uint32_t carry = 0;
+		for(std::size_t i = 0; i < 4; ++i) {
+			uint32_t before_val = data_bit_length_digits[i];
+			data_bit_length_digits[i] <<= 3;
+			data_bit_length_digits[i] |= carry;
+			data_bit_length_digits[i] &= 65535u;
+			carry = (before_val >> (16-3)) & 65535u;
+		}
+
+		// write data_bit_length
+		for(int i = 3; i >= 0; --i) {
+			(*begin++) = static_cast<uint8_t>(data_bit_length_digits[i] >> 8);
+			(*begin++) = static_cast<uint8_t>(data_bit_length_digits[i]);
+		}
+	}
+	std::vector<uint8_t> buffer_;
+	uint32_t data_length_digits_[4]; //as 64bit integer (16bit x 4 integer)
+	uint32_t h_[8];
+};
+
+inline void get_hash_hex_string(const hash256_one_by_one& hasher, std::string& hex_str){
+	uint8_t hash[32];
+	hasher.get_hash_bytes(hash, hash+32);
+	return bytes_to_hex_string(hash, hash+32, hex_str);
+}
+
+inline std::string get_hash_hex_string(const hash256_one_by_one& hasher){
+	std::string hex_str;
+	get_hash_hex_string(hasher, hex_str);
+	return hex_str;
+}
+
+template<typename RaIter, typename OutIter>
+void hash256(RaIter first, RaIter last, OutIter first2, OutIter last2){
+	hash256_one_by_one hasher;
+	//hasher.init();
+	hasher.process(first, last);
+	hasher.finish();
+	hasher.get_hash_bytes(first2, last2);
+}
+
+template<typename RaIter, typename OutContainer>
+void hash256(RaIter first, RaIter last, OutContainer& dst){
+	hash256(first, last, dst.begin(), dst.end());
+}
+
+template<typename RaContainer, typename OutIter>
+void hash256(const RaContainer& src, OutIter first, OutIter last){
+	hash256(src.begin(), src.end(), first, last);
+}
+
+template<typename RaContainer, typename OutContainer>
+void hash256(const RaContainer& src, OutContainer& dst){
+	hash256(src.begin(), src.end(), dst.begin(), dst.end());
+}
+
+
+template<typename RaIter>
+void hash256_hex_string(RaIter first, RaIter last, std::string& hex_str){
+	uint8_t hashed[32];
+	hash256(first, last, hashed, hashed+32);
+	std::ostringstream oss;
+	output_hex(hashed, hashed+32, oss);
+	hex_str.assign(oss.str());
+}
+
+template<typename RaIter>
+std::string hash256_hex_string(RaIter first, RaIter last){
+	std::string hex_str;
+	hash256_hex_string(first, last, hex_str);
+	return hex_str;
+}
+
+inline void hash256_hex_string(const std::string& src, std::string& hex_str){
+	hash256_hex_string(src.begin(), src.end(), hex_str);
+}
+
+template<typename RaContainer>
+void hash256_hex_string(const RaContainer& src, std::string& hex_str){
+	hash256_hex_string(src.begin(), src.end(), hex_str);
+}
+
+template<typename RaContainer>
+std::string hash256_hex_string(const RaContainer& src){
+	return hash256_hex_string(src.begin(), src.end());
+}
+
+}//namespace picosha2
+
+#endif //PICOSHA2_H
diff --git a/src/ringdht/eth/libdevcore/vector_ref.h b/src/ringdht/eth/libdevcore/vector_ref.h
new file mode 100644
index 0000000000000000000000000000000000000000..46d06946299f3bd6434818652eae21b482fd6e63
--- /dev/null
+++ b/src/ringdht/eth/libdevcore/vector_ref.h
@@ -0,0 +1,120 @@
+#pragma once
+
+#include <cstring>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+#include <string>
+
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:597) //will not be called for implicit or explicit conversions
+#endif
+
+namespace dev
+{
+
+/**
+ * A modifiable reference to an existing object or vector in memory.
+ */
+template <class _T>
+class vector_ref
+{
+public:
+	using value_type = _T;
+	using element_type = _T;
+	using mutable_value_type = typename std::conditional<std::is_const<_T>::value, typename std::remove_const<_T>::type, _T>::type;
+
+	static_assert(std::is_pod<value_type>::value, "vector_ref can only be used with PODs due to its low-level treatment of data.");
+
+	vector_ref(): m_data(nullptr), m_count(0) {}
+	/// Creates a new vector_ref to point to @a _count elements starting at @a _data.
+	vector_ref(_T* _data, size_t _count): m_data(_data), m_count(_count) {}
+	/// Creates a new vector_ref pointing to the data part of a string (given as pointer).
+	vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const*, std::string*>::type _data): m_data(reinterpret_cast<_T*>(_data->data())), m_count(_data->size() / sizeof(_T)) {}
+	/// Creates a new vector_ref pointing to the data part of a vector (given as pointer).
+	vector_ref(typename std::conditional<std::is_const<_T>::value, std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data): m_data(_data->data()), m_count(_data->size()) {}
+	/// Creates a new vector_ref pointing to the data part of a string (given as reference).
+	vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type _data): m_data(reinterpret_cast<_T*>(_data.data())), m_count(_data.size() / sizeof(_T)) {}
+#if DEV_LDB
+	vector_ref(ldb::Slice const& _s): m_data(reinterpret_cast<_T*>(_s.data())), m_count(_s.size() / sizeof(_T)) {}
+#endif
+	explicit operator bool() const { return m_data && m_count; }
+
+	bool contentsEqual(std::vector<mutable_value_type> const& _c) const { if (!m_data || m_count == 0) return _c.empty(); else return _c.size() == m_count && !memcmp(_c.data(), m_data, m_count * sizeof(_T)); }
+	std::vector<mutable_value_type> toVector() const { return std::vector<mutable_value_type>(m_data, m_data + m_count); }
+	std::vector<unsigned char> toBytes() const { return std::vector<unsigned char>(reinterpret_cast<unsigned char const*>(m_data), reinterpret_cast<unsigned char const*>(m_data) + m_count * sizeof(_T)); }
+	std::string toString() const { return std::string((char const*)m_data, ((char const*)m_data) + m_count * sizeof(_T)); }
+
+	template <class _T2> explicit operator vector_ref<_T2>() const { assert(m_count * sizeof(_T) / sizeof(_T2) * sizeof(_T2) / sizeof(_T) == m_count); return vector_ref<_T2>(reinterpret_cast<_T2*>(m_data), m_count * sizeof(_T) / sizeof(_T2)); }
+	operator vector_ref<_T const>() const { return vector_ref<_T const>(m_data, m_count); }
+
+	_T* data() const { return m_data; }
+	/// @returns the number of elements referenced (not necessarily number of bytes).
+	size_t count() const { return m_count; }
+	/// @returns the number of elements referenced (not necessarily number of bytes).
+	size_t size() const { return m_count; }
+	bool empty() const { return !m_count; }
+	/// @returns a new vector_ref pointing at the next chunk of @a size() elements.
+	vector_ref<_T> next() const { if (!m_data) return *this; else return vector_ref<_T>(m_data + m_count, m_count); }
+	/// @returns a new vector_ref which is a shifted and shortened view of the original data.
+	/// If this goes out of bounds in any way, returns an empty vector_ref.
+	/// If @a _count is ~size_t(0), extends the view to the end of the data.
+	vector_ref<_T> cropped(size_t _begin, size_t _count) const { if (m_data && _begin <= m_count && _count <= m_count && _begin + _count <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); }
+	/// @returns a new vector_ref which is a shifted view of the original data (not going beyond it).
+	vector_ref<_T> cropped(size_t _begin) const { if (m_data && _begin <= m_count) return vector_ref<_T>(m_data + _begin, m_count - _begin); else return vector_ref<_T>(); }
+	void retarget(_T* _d, size_t _s) { m_data = _d; m_count = _s; }
+	void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); }
+	template <class T> bool overlapsWith(vector_ref<T> _t) const { void const* f1 = data(); void const* t1 = data() + size(); void const* f2 = _t.data(); void const* t2 = _t.data() + _t.size(); return f1 < t2 && t1 > f2; }
+	/// Copies the contents of this vector_ref to the contents of @a _t, up to the max size of @a _t.
+	void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { if (overlapsWith(_t)) memmove(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); else memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
+	/// Copies the contents of this vector_ref to the contents of @a _t, and zeros further trailing elements in @a _t.
+	void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); }
+	/// Securely overwrite the memory.
+	/// @note adapted from OpenSSL's implementation.
+	void cleanse()
+	{
+		static unsigned char s_cleanseCounter = 0;
+		uint8_t* p = (uint8_t*)begin();
+		size_t const len = (uint8_t*)end() - p;
+		size_t loop = len;
+		size_t count = s_cleanseCounter;
+		while (loop--)
+		{
+			*(p++) = (uint8_t)count;
+			count += (17 + ((size_t)p & 0xf));
+		}
+		p = (uint8_t*)memchr((uint8_t*)begin(), (uint8_t)count, len);
+		if (p)
+			count += (63 + (size_t)p);
+		s_cleanseCounter = (uint8_t)count;
+		memset((uint8_t*)begin(), 0, len);
+	}
+
+	_T* begin() { return m_data; }
+	_T* end() { return m_data + m_count; }
+	_T const* begin() const { return m_data; }
+	_T const* end() const { return m_data + m_count; }
+
+	_T& operator[](size_t _i) { assert(m_data); assert(_i < m_count); return m_data[_i]; }
+	_T const& operator[](size_t _i) const { assert(m_data); assert(_i < m_count); return m_data[_i]; }
+
+	bool operator==(vector_ref<_T> const& _cmp) const { return m_data == _cmp.m_data && m_count == _cmp.m_count; }
+	bool operator!=(vector_ref<_T> const& _cmp) const { return !operator==(_cmp); }
+
+#if DEV_LDB
+	operator ldb::Slice() const { return ldb::Slice((char const*)m_data, m_count * sizeof(_T)); }
+#endif
+
+	void reset() { m_data = nullptr; m_count = 0; }
+
+private:
+	_T* m_data;
+	size_t m_count;
+};
+
+template<class _T> vector_ref<_T const> ref(_T const& _t) { return vector_ref<_T const>(&_t, 1); }
+template<class _T> vector_ref<_T> ref(_T& _t) { return vector_ref<_T>(&_t, 1); }
+template<class _T> vector_ref<_T const> ref(std::vector<_T> const& _t) { return vector_ref<_T const>(&_t); }
+template<class _T> vector_ref<_T> ref(std::vector<_T>& _t) { return vector_ref<_T>(&_t); }
+
+}
diff --git a/src/ringdht/eth/libdevcrypto/AES.cpp b/src/ringdht/eth/libdevcrypto/AES.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bec2ba137c7468dfe6dbfbd7fda43cc658592e4f
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/AES.cpp
@@ -0,0 +1,57 @@
+/*
+ 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 AES.cpp
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ */
+
+#include "AES.h"
+#include <libdevcore/Common.h>
+#include "CryptoPP.h"
+using namespace std;
+using namespace dev;
+using namespace dev::crypto;
+using namespace CryptoPP;
+
+bytes dev::aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt)
+{
+	bytes pw = asBytes(_password);
+
+	if (!_salt.size())
+		_salt = &pw;
+
+	bytes target(64);
+	CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256>().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds);
+
+	try
+	{
+		CryptoPP::AES::Decryption aesDecryption(target.data(), 16);
+		auto cipher = _ivCipher.cropped(16);
+		auto iv = _ivCipher.cropped(0, 16);
+		CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
+		std::string decrypted;
+		CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted));
+		stfDecryptor.Put(cipher.data(), cipher.size());
+		stfDecryptor.MessageEnd();
+		return asBytes(decrypted);
+	}
+	catch (exception const& e)
+	{
+		cerr << e.what() << endl;
+		return bytes();
+	}
+}
diff --git a/src/ringdht/eth/libdevcrypto/AES.h b/src/ringdht/eth/libdevcrypto/AES.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f72369f6347bfd995b25b2b71b2b114c9d04ac1
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/AES.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 AES.h
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ *
+ * AES
+ * todo: use openssl
+ */
+
+#pragma once
+
+#include "Common.h"
+
+namespace dev
+{
+
+bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef());
+
+}
diff --git a/src/ringdht/eth/libdevcrypto/Common.cpp b/src/ringdht/eth/libdevcrypto/Common.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aaa6fa917babdce26343e825fe194f069b7672f8
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/Common.cpp
@@ -0,0 +1,327 @@
+/*
+	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 Common.cpp
+ * @author Alex Leverington <nessence@gmail.com>
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ */
+
+#include "Common.h"
+#include <cstdint>
+#include <chrono>
+#include <thread>
+#include <mutex>
+#include <libdevcore/Guards.h>
+#include <libdevcore/SHA3.h>
+#include <libdevcore/RLP.h>
+#if ETH_HAVE_SECP256K1
+#include <secp256k1/include/secp256k1.h>
+#endif
+#include "AES.h"
+#include "CryptoPP.h"
+#include "Exceptions.h"
+using namespace std;
+using namespace dev;
+using namespace dev::crypto;
+
+#ifdef ETH_HAVE_SECP256K1
+class Secp256k1Context
+{
+public:
+	static secp256k1_context_t const* get() { if (!s_this) s_this = new Secp256k1Context; return s_this->m_ctx; }
+
+private:
+	Secp256k1Context() { m_ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); }
+	~Secp256k1Context() { secp256k1_context_destroy(m_ctx); }
+
+	secp256k1_context_t* m_ctx;
+
+	static Secp256k1Context* s_this;
+};
+Secp256k1Context* Secp256k1Context::s_this = nullptr;
+#endif
+
+bool dev::SignatureStruct::isValid() const noexcept
+{
+	if (v > 1 ||
+		r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
+		s >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
+		s < h256(1) ||
+		r < h256(1))
+		return false;
+	return true;
+}
+
+Public SignatureStruct::recover(h256 const& _hash) const
+{
+	return dev::recover((Signature)*this, _hash);
+}
+
+Address dev::ZeroAddress = Address();
+
+Public dev::toPublic(Secret const& _secret)
+{
+#ifdef ETH_HAVE_SECP256K1
+	bytes o(65);
+	int pubkeylen;
+	if (!secp256k1_ec_pubkey_create(Secp256k1Context::get(), o.data(), &pubkeylen, _secret.data(), false))
+		return Public();
+	return FixedHash<64>(o.data()+1, Public::ConstructFromPointer);
+#else
+	Public p;
+	Secp256k1PP::get()->toPublic(_secret, p);
+	return p;
+#endif
+}
+
+Address dev::toAddress(Public const& _public)
+{
+	return right160(sha3(_public.ref()));
+}
+
+Address dev::toAddress(Secret const& _secret)
+{
+	Public p;
+	Secp256k1PP::get()->toPublic(_secret, p);
+	return toAddress(p);
+}
+
+Address dev::toAddress(Address const& _from, u256 const& _nonce)
+{
+	return right160(sha3(rlpList(_from, _nonce)));
+}
+
+void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
+{
+	bytes io = _plain.toBytes();
+	Secp256k1PP::get()->encrypt(_k, io);
+	o_cipher = std::move(io);
+}
+
+bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
+{
+	bytes io = _cipher.toBytes();
+	Secp256k1PP::get()->decrypt(_k, io);
+	if (io.empty())
+		return false;
+	o_plaintext = std::move(io);
+	return true;
+}
+
+void dev::encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
+{
+	encryptECIES(_k, bytesConstRef(), _plain, o_cipher);
+}
+
+void dev::encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytesConstRef _plain, bytes& o_cipher)
+{
+	bytes io = _plain.toBytes();
+	Secp256k1PP::get()->encryptECIES(_k, _sharedMacData, io);
+	o_cipher = std::move(io);
+}
+
+bool dev::decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
+{
+	return decryptECIES(_k, bytesConstRef(),  _cipher, o_plaintext);
+}
+
+bool dev::decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytesConstRef _cipher, bytes& o_plaintext)
+{
+	bytes io = _cipher.toBytes();
+	if (!Secp256k1PP::get()->decryptECIES(_k, _sharedMacData, io))
+		return false;
+	o_plaintext = std::move(io);
+	return true;
+}
+
+void dev::encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher)
+{
+	// TOOD: @alex @subtly do this properly.
+	encrypt(KeyPair(_k).pub(), _plain, o_cipher);
+}
+
+bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
+{
+	// TODO: @alex @subtly do this properly.
+	return decrypt(_k, _cipher, o_plain);
+}
+
+std::pair<bytes, h128> dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain)
+{
+	h128 iv(Nonce::get().makeInsecure());
+	return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
+}
+
+bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain)
+{
+	if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32)
+		return bytes();
+	SecByteBlock key(_k.data(), _k.size());
+	try
+	{
+		CTR_Mode<AES>::Encryption e;
+		e.SetKeyWithIV(key, key.size(), _iv.data());
+		bytes ret(_plain.size());
+		e.ProcessData(ret.data(), _plain.data(), _plain.size());
+		return ret;
+	}
+	catch (CryptoPP::Exception& _e)
+	{
+		cerr << _e.what() << endl;
+		return bytes();
+	}
+}
+
+bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher)
+{
+	if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32)
+		return bytesSec();
+	SecByteBlock key(_k.data(), _k.size());
+	try
+	{
+		CTR_Mode<AES>::Decryption d;
+		d.SetKeyWithIV(key, key.size(), _iv.data());
+		bytesSec ret(_cipher.size());
+		d.ProcessData(ret.writable().data(), _cipher.data(), _cipher.size());
+		return ret;
+	}
+	catch (CryptoPP::Exception& _e)
+	{
+		cerr << _e.what() << endl;
+		return bytesSec();
+	}
+}
+
+static const Public c_zeroKey("3f17f1962b36e491b30a40b2405849e597ba5fb5");
+
+Public dev::recover(Signature const& _sig, h256 const& _message)
+{
+	Public ret;
+#ifdef ETH_HAVE_SECP256K1
+	bytes o(65);
+	int pubkeylen;
+	if (_sig[64] > 3 || !secp256k1_ecdsa_recover_compact(Secp256k1Context::get(), _message.data(), _sig.data(), o.data(), &pubkeylen, false, _sig[64]))
+		return Public();
+	ret = FixedHash<64>(o.data() + 1, Public::ConstructFromPointer);
+#else
+	ret = Secp256k1PP::get()->recover(_sig, _message.ref());
+#endif
+	if (ret == c_zeroKey)
+		return Public();
+	return ret;
+}
+
+static const u256 c_secp256k1n("115792089237316195423570985008687907852837564279074904382605163141518161494337");
+
+Signature dev::sign(Secret const& _k, h256 const& _hash)
+{
+	Signature s;
+	SignatureStruct& ss = *reinterpret_cast<SignatureStruct*>(&s);
+
+#ifdef ETH_HAVE_SECP256K1
+	int v;
+	if (!secp256k1_ecdsa_sign_compact(Secp256k1Context::get(), _hash.data(), s.data(), _k.data(), NULL, NULL, &v))
+		return Signature();
+	ss.v = v;
+#else
+	s = Secp256k1PP::get()->sign(_k, _hash);
+#endif
+	if (ss.s > c_secp256k1n / 2)
+	{
+		ss.v = ss.v ^ 1;
+		ss.s = h256(c_secp256k1n - u256(ss.s));
+	}
+	assert(ss.s <= c_secp256k1n / 2);
+	return s;
+}
+
+bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
+{
+	if (!_p)
+		return false;
+#ifdef ETH_HAVE_SECP256K1
+	return _p == recover(_s, _hash);
+#else
+	return Secp256k1PP::get()->verify(_p, _s, _hash.ref(), true);
+#endif
+}
+
+bytesSec dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen)
+{
+	bytesSec ret(_dkLen);
+	if (PKCS5_PBKDF2_HMAC<SHA256>().DeriveKey(
+		ret.writable().data(),
+		_dkLen,
+		0,
+		reinterpret_cast<byte const*>(_pass.data()),
+		_pass.size(),
+		_salt.data(),
+		_salt.size(),
+		_iterations
+	) != _iterations)
+		BOOST_THROW_EXCEPTION(CryptoException() << errinfo_comment("Key derivation failed."));
+	return ret;
+}
+
+void KeyPair::populateFromSecret(Secret const& _sec)
+{
+	m_secret = _sec;
+	if (Secp256k1PP::get()->verifySecret(m_secret, m_public))
+		m_address = toAddress(m_public);
+}
+
+KeyPair KeyPair::create()
+{
+	for (int i = 0; i < 100; ++i)
+	{
+		KeyPair ret(Secret::random());
+		if (ret.address())
+			return ret;
+	}
+	return KeyPair();
+}
+
+KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
+{
+	return KeyPair(Secret(sha3(aesDecrypt(_seed, _password))));
+}
+
+h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
+{
+	// H(H(r||k)^h)
+	h256 s;
+	sha3mac(Secret::random().ref(), _priv.ref(), s.ref());
+	s ^= _hash;
+	sha3(s.ref(), s.ref());
+	
+	if (!s || !_hash || !_priv)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	return s;
+}
+
+Secret Nonce::next()
+{
+	Guard l(x_value);
+	if (!m_value)
+	{
+		m_value = Secret::random();
+		if (!m_value)
+			BOOST_THROW_EXCEPTION(InvalidState());
+	}
+	m_value = sha3Secure(m_value.ref());
+	return sha3(~m_value);
+}
diff --git a/src/ringdht/eth/libdevcrypto/Common.h b/src/ringdht/eth/libdevcrypto/Common.h
new file mode 100644
index 0000000000000000000000000000000000000000..64a6e4c8a58dab58b096018d393ab7251580ec7e
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/Common.h
@@ -0,0 +1,222 @@
+/*
+	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 Common.h
+ * @author Alex Leverington <nessence@gmail.com>
+ * @author Gav Wood <i@gavwood.com>
+ * @date 2014
+ *
+ * Ethereum-specific data structures & algorithms.
+ */
+
+#pragma once
+
+#include <mutex>
+#include "libdevcore/Common.h"
+#include "libdevcore/FixedHash.h"
+#include "libdevcore/Exceptions.h"
+
+namespace dev
+{
+
+using Secret = SecureFixedHash<32>;
+
+/// A public key: 64 bytes.
+/// @NOTE This is not endian-specific; it's just a bunch of bytes.
+using Public = h512;
+
+/// A signature: 65 bytes: r: [0, 32), s: [32, 64), v: 64.
+/// @NOTE This is not endian-specific; it's just a bunch of bytes.
+using Signature = h520;
+
+struct SignatureStruct
+{
+	SignatureStruct() = default;
+	SignatureStruct(Signature const& _s) { *(h520*)this = _s; }
+	SignatureStruct(h256 const& _r, h256 const& _s, byte _v): r(_r), s(_s), v(_v) {}
+	operator Signature() const { return *(h520 const*)this; }
+
+	/// @returns true if r,s,v values are valid, otherwise false
+	bool isValid() const noexcept;
+
+	/// @returns the public part of the key that signed @a _hash to give this sig.
+	Public recover(h256 const& _hash) const;
+
+	h256 r;
+	h256 s;
+	byte v = 0;
+};
+
+/// An Ethereum address: 20 bytes.
+/// @NOTE This is not endian-specific; it's just a bunch of bytes.
+using Address = h160;
+
+/// The zero address.
+extern Address ZeroAddress;
+
+/// A vector of Ethereum addresses.
+using Addresses = h160s;
+
+/// A hash set of Ethereum addresses.
+using AddressHash = std::unordered_set<h160>;
+
+/// A vector of secrets.
+using Secrets = std::vector<Secret>;
+
+/// Convert a secret key into the public key equivalent.
+Public toPublic(Secret const& _secret);
+
+/// Convert a public key to address.
+Address toAddress(Public const& _public);
+
+/// Convert a secret key into address of public key equivalent.
+/// @returns 0 if it's not a valid secret key.
+Address toAddress(Secret const& _secret);
+
+// Convert transaction from and nonce to address.
+Address toAddress(Address const& _from, u256 const& _nonce);
+
+/// Encrypts plain text using Public key.
+void encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
+
+/// Decrypts cipher using Secret key.
+bool decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
+
+/// Symmetric encryption.
+void encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher);
+
+/// Symmetric decryption.
+bool decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
+
+/// Encrypt payload using ECIES standard with AES128-CTR.
+void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
+
+/// Encrypt payload using ECIES standard with AES128-CTR.
+/// @a _sharedMacData is shared authenticated data.
+void encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytesConstRef _plain, bytes& o_cipher);
+
+/// Decrypt payload using ECIES standard with AES128-CTR.
+bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
+
+/// Decrypt payload using ECIES standard with AES128-CTR.
+/// @a _sharedMacData is shared authenticated data.
+bool decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytesConstRef _cipher, bytes& o_plaintext);
+
+/// Encrypts payload with random IV/ctr using AES128-CTR.
+std::pair<bytes, h128> encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain);
+
+/// Encrypts payload with specified IV/ctr using AES128-CTR.
+bytes encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain);
+
+/// Decrypts payload with specified IV/ctr using AES128-CTR.
+bytesSec decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher);
+
+/// Encrypts payload with specified IV/ctr using AES128-CTR.
+inline bytes encryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
+inline bytes encryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _plain) { return encryptAES128CTR(_k.ref(), _iv, _plain); }
+
+/// Decrypts payload with specified IV/ctr using AES128-CTR.
+inline bytesSec decryptSymNoAuth(SecureFixedHash<16> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
+inline bytesSec decryptSymNoAuth(SecureFixedHash<32> const& _k, h128 const& _iv, bytesConstRef _cipher) { return decryptAES128CTR(_k.ref(), _iv, _cipher); }
+
+/// Recovers Public key from signed message hash.
+Public recover(Signature const& _sig, h256 const& _hash);
+	
+/// Returns siganture of message hash.
+Signature sign(Secret const& _k, h256 const& _hash);
+	
+/// Verify signature.
+bool verify(Public const& _k, Signature const& _s, h256 const& _hash);
+
+/// Derive key via PBKDF2.
+bytesSec pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen = 32);
+
+/// Simple class that represents a "key pair".
+/// All of the data of the class can be regenerated from the secret key (m_secret) alone.
+/// Actually stores a tuplet of secret, public and address (the right 160-bits of the public).
+class KeyPair
+{
+public:
+	/// Null constructor.
+	KeyPair() {}
+
+	/// Normal constructor - populates object from the given secret key.
+	KeyPair(Secret const& _k) { populateFromSecret(_k); }
+
+	/// Create a new, randomly generated object.
+	static KeyPair create();
+
+	/// Create from an encrypted seed.
+	static KeyPair fromEncryptedSeed(bytesConstRef _seed, std::string const& _password);
+
+	/// Retrieve the secret key.
+	Secret const& secret() const { return m_secret; }
+	/// Retrieve the secret key.
+	Secret const& sec() const { return m_secret; }
+
+	/// Retrieve the public key.
+	Public const& pub() const { return m_public; }
+
+	/// Retrieve the associated address of the public key.
+	Address const& address() const { return m_address; }
+
+	bool operator==(KeyPair const& _c) const { return m_public == _c.m_public; }
+	bool operator!=(KeyPair const& _c) const { return m_public != _c.m_public; }
+
+private:
+	void populateFromSecret(Secret const& _k);
+
+	Secret m_secret;
+	Public m_public;
+	Address m_address;
+};
+
+namespace crypto
+{
+
+DEV_SIMPLE_EXCEPTION(InvalidState);
+
+/// Key derivation
+h256 kdf(Secret const& _priv, h256 const& _hash);
+
+/**
+ * @brief Generator for non-repeating nonce material.
+ * The Nonce class should only be used when a non-repeating nonce
+ * is required and, in its current form, not recommended for signatures.
+ * This is primarily because the key-material for signatures is 
+ * encrypted on disk whereas the seed for Nonce is not. 
+ * Thus, Nonce's primary intended use at this time is for networking 
+ * where the key is also stored in plaintext.
+ */
+class Nonce
+{
+public:
+	/// Returns the next nonce (might be read from a file).
+	static Secret get() { static Nonce s; return s.next(); }
+
+private:
+	Nonce() = default;
+
+	/// @returns the next nonce.
+	Secret next();
+
+	std::mutex x_value;
+	Secret m_value;
+};
+
+}
+
+}
diff --git a/src/ringdht/eth/libdevcrypto/CryptoPP.cpp b/src/ringdht/eth/libdevcrypto/CryptoPP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d4bb771658e37bdc17b0c9ba1e3b460e6fa403d4
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/CryptoPP.cpp
@@ -0,0 +1,372 @@
+/*
+ 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 CryptoPP.cpp
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ */
+
+#include <libdevcore/Guards.h>
+#include "ECDHE.h"
+/*
+ * At 5.6.3 the ECIES implementation has been deprecated and a warning has
+ * been added. A new implementation will be added in 6.0. Until then and for
+ * -Werror to not fail the build we have to have this warning ignore pragma here
+ * and until the end of the file.
+ * Refer here for more information:
+ * https://www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme#5.6.3_and_6.0_Changes
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#include "CryptoPP.h"
+
+using namespace std;
+using namespace dev;
+using namespace dev::crypto;
+using namespace CryptoPP;
+
+static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
+static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
+static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
+
+Secp256k1PP* Secp256k1PP::s_this = nullptr;
+
+bytes Secp256k1PP::eciesKDF(Secret const& _z, bytes _s1, unsigned kdByteLen)
+{
+	auto reps = ((kdByteLen + 7) * 8) / (CryptoPP::SHA256::BLOCKSIZE * 8);
+	// SEC/ISO/Shoup specify counter size SHOULD be equivalent
+	// to size of hash output, however, it also notes that
+	// the 4 bytes is okay. NIST specifies 4 bytes.
+	bytes ctr({0, 0, 0, 1});
+	bytes k;
+	CryptoPP::SHA256 ctx;
+	for (unsigned i = 0; i <= reps; i++)
+	{
+		ctx.Update(ctr.data(), ctr.size());
+		ctx.Update(_z.data(), Secret::size);
+		ctx.Update(_s1.data(), _s1.size());
+		// append hash to k
+		bytes digest(32);
+		ctx.Final(digest.data());
+		ctx.Restart();
+		
+		k.reserve(k.size() + h256::size);
+		move(digest.begin(), digest.end(), back_inserter(k));
+		
+		if (++ctr[3] || ++ctr[2] || ++ctr[1] || ++ctr[0])
+			continue;
+	}
+	
+	k.resize(kdByteLen);
+	return k;
+}
+
+void Secp256k1PP::encryptECIES(Public const& _k, bytes& io_cipher)
+{
+	encryptECIES(_k, bytesConstRef(), io_cipher);
+}
+
+void Secp256k1PP::encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytes& io_cipher)
+{
+	// interop w/go ecies implementation
+	auto r = KeyPair::create();
+	Secret z;
+	ecdh::agree(r.sec(), _k, z);
+	auto key = eciesKDF(z, bytes(), 32);
+	bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
+	bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16);
+	CryptoPP::SHA256 ctx;
+	ctx.Update(mKeyMaterial.data(), mKeyMaterial.size());
+	bytes mKey(32);
+	ctx.Final(mKey.data());
+	
+	bytes cipherText = encryptSymNoAuth(SecureFixedHash<16>(eKey), h128(), bytesConstRef(&io_cipher));
+	if (cipherText.empty())
+		return;
+
+	bytes msg(1 + Public::size + h128::size + cipherText.size() + 32);
+	msg[0] = 0x04;
+	r.pub().ref().copyTo(bytesRef(&msg).cropped(1, Public::size));
+	bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size + h128::size, cipherText.size());
+	bytesConstRef(&cipherText).copyTo(msgCipherRef);
+	
+	// tag message
+	CryptoPP::HMAC<SHA256> hmacctx(mKey.data(), mKey.size());
+	bytesConstRef cipherWithIV = bytesRef(&msg).cropped(1 + Public::size, h128::size + cipherText.size());
+	hmacctx.Update(cipherWithIV.data(), cipherWithIV.size());
+	hmacctx.Update(_sharedMacData.data(), _sharedMacData.size());
+	hmacctx.Final(msg.data() + 1 + Public::size + cipherWithIV.size());
+	
+	io_cipher.resize(msg.size());
+	io_cipher.swap(msg);
+}
+
+bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text)
+{
+	return decryptECIES(_k, bytesConstRef(), io_text);
+}
+
+bool Secp256k1PP::decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytes& io_text)
+{
+
+	// interop w/go ecies implementation
+	
+	// io_cipher[0] must be 2, 3, or 4, else invalidpublickey
+	if (io_text.empty() || io_text[0] < 2 || io_text[0] > 4)
+		// invalid message: publickey
+		return false;
+	
+	if (io_text.size() < (1 + Public::size + h128::size + 1 + h256::size))
+		// invalid message: length
+		return false;
+
+	Secret z;
+	ecdh::agree(_k, *(Public*)(io_text.data() + 1), z);
+	auto key = eciesKDF(z, bytes(), 64);
+	bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
+	bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16);
+	bytes mKey(32);
+	CryptoPP::SHA256 ctx;
+	ctx.Update(mKeyMaterial.data(), mKeyMaterial.size());
+	ctx.Final(mKey.data());
+	
+	bytes plain;
+	size_t cipherLen = io_text.size() - 1 - Public::size - h128::size - h256::size;
+	bytesConstRef cipherWithIV(io_text.data() + 1 + Public::size, h128::size + cipherLen);
+	bytesConstRef cipherIV = cipherWithIV.cropped(0, h128::size);
+	bytesConstRef cipherNoIV = cipherWithIV.cropped(h128::size, cipherLen);
+	bytesConstRef msgMac(cipherNoIV.data() + cipherLen, h256::size);
+	h128 iv(cipherIV.toBytes());
+	
+	// verify tag
+	CryptoPP::HMAC<SHA256> hmacctx(mKey.data(), mKey.size());
+	hmacctx.Update(cipherWithIV.data(), cipherWithIV.size());
+	hmacctx.Update(_sharedMacData.data(), _sharedMacData.size());
+	h256 mac;
+	hmacctx.Final(mac.data());
+	for (unsigned i = 0; i < h256::size; i++)
+		if (mac[i] != msgMac[i])
+			return false;
+	
+	plain = decryptSymNoAuth(SecureFixedHash<16>(eKey), iv, cipherNoIV).makeInsecure();
+	io_text.resize(plain.size());
+	io_text.swap(plain);
+	
+	return true;
+}
+
+void Secp256k1PP::encrypt(Public const& _k, bytes& io_cipher)
+{
+	ECIES<ECP>::Encryptor e;
+	initializeDLScheme(_k, e);
+
+	size_t plen = io_cipher.size();
+	bytes ciphertext;
+	ciphertext.resize(e.CiphertextLength(plen));
+	
+	{
+		Guard l(x_rng);
+		e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data());
+	}
+	
+	memset(io_cipher.data(), 0, io_cipher.size());
+	io_cipher = std::move(ciphertext);
+}
+
+void Secp256k1PP::decrypt(Secret const& _k, bytes& io_text)
+{
+	CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
+	initializeDLScheme(_k, d);
+
+	if (!io_text.size())
+	{
+		io_text.resize(1);
+		io_text[0] = 0;
+	}
+	
+	size_t clen = io_text.size();
+	bytes plain;
+	plain.resize(d.MaxPlaintextLength(io_text.size()));
+	
+	DecodingResult r;
+	{
+		Guard l(x_rng);
+		r = d.Decrypt(m_rng, io_text.data(), clen, plain.data());
+	}
+	
+	if (!r.isValidCoding)
+	{
+		io_text.clear();
+		return;
+	}
+	
+	io_text.resize(r.messageLength);
+	io_text = std::move(plain);
+}
+
+Signature Secp256k1PP::sign(Secret const& _k, bytesConstRef _message)
+{
+	return sign(_k, sha3(_message));
+}
+
+Signature Secp256k1PP::sign(Secret const& _key, h256 const& _hash)
+{
+	// assumption made by signing alogrithm
+	assert(m_q == m_qs);
+	
+	Signature sig;
+	
+	Integer k(kdf(_key, _hash).data(), 32);
+	if (k == 0)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	k = 1 + (k % (m_qs - 1));
+	
+	ECP::Point rp;
+	Integer r;
+	{
+		Guard l(x_params);
+		rp = m_params.ExponentiateBase(k);
+		r = m_params.ConvertElementToInteger(rp);
+	}
+	sig[64] = 0;
+//	sig[64] = (r >= m_q) ? 2 : 0;
+	
+	Integer kInv = k.InverseMod(m_q);
+	Integer z(_hash.asBytes().data(), 32);
+	Integer s = (kInv * (Integer(_key.data(), 32) * r + z)) % m_q;
+	if (r == 0 || s == 0)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	
+//	if (s > m_qs)
+//	{
+//		s = m_q - s;
+//		if (sig[64])
+//			sig[64] ^= 1;
+//	}
+	
+	sig[64] |= rp.y.IsOdd() ? 1 : 0;
+	r.Encode(sig.data(), 32);
+	s.Encode(sig.data() + 32, 32);
+	return sig;
+}
+
+bool Secp256k1PP::verify(Signature const& _signature, bytesConstRef _message)
+{
+	return !!recover(_signature, _message);
+}
+
+bool Secp256k1PP::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
+{
+	// todo: verify w/o recovery (if faster)
+	return _p == (_hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref()));
+}
+
+Public Secp256k1PP::recover(Signature _signature, bytesConstRef _message)
+{
+	Public recovered;
+	
+	Integer r(_signature.data(), 32);
+	Integer s(_signature.data()+32, 32);
+	// cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28
+	byte encodedpoint[33];
+	encodedpoint[0] = _signature[64] | 2;
+	memcpy(&encodedpoint[1], _signature.data(), 32);
+	
+	ECP::Element x;
+	{
+		m_curve.DecodePoint(x, encodedpoint, 33);
+		if (!m_curve.VerifyPoint(x))
+			return recovered;
+	}
+	
+//	if (_signature[64] & 2)
+//	{
+//		r += m_q;
+//		Guard l(x_params);
+//		if (r >= m_params.GetMaxExponent())
+//			return recovered;
+//	}
+	
+	Integer z(_message.data(), 32);
+	Integer rn = r.InverseMod(m_q);
+	Integer u1 = m_q - (rn.Times(z)).Modulo(m_q);
+	Integer u2 = (rn.Times(s)).Modulo(m_q);
+	
+	ECP::Point p;
+	byte recoveredbytes[65];
+	{
+		// todo: make generator member
+		p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
+		if (p.identity)
+			return Public();
+		m_curve.EncodePoint(recoveredbytes, p, false);
+	}
+	memcpy(recovered.data(), &recoveredbytes[1], 64);
+	return recovered;
+}
+
+bool Secp256k1PP::verifySecret(Secret const& _s, Public& _p)
+{
+	DL_PrivateKey_EC<ECP> k;
+	k.Initialize(m_params, secretToExponent(_s));
+	if (!k.Validate(m_rng, 3))
+		return false;
+	
+	DL_PublicKey_EC<CryptoPP::ECP> pub;
+	k.MakePublicKey(pub);
+	if (!k.Validate(m_rng, 3))
+		return false;
+
+	exportPublicKey(pub, _p);
+	return true;
+}
+
+void Secp256k1PP::agree(Secret const& _s, Public const& _r, Secret& o_s)
+{
+	// TODO: mutex ASN1::secp256k1() singleton
+	// Creating Domain is non-const for m_oid and m_oid is not thread-safe
+	ECDH<ECP>::Domain d(ASN1::secp256k1());
+	assert(d.AgreedValueLength() == sizeof(o_s));
+	byte remote[65] = {0x04};
+	memcpy(&remote[1], _r.data(), 64);
+	d.Agree(o_s.writable().data(), _s.data(), remote);
+}
+
+void Secp256k1PP::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& o_p)
+{
+	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
+	
+	{
+		Guard l(x_params);
+		m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
+		assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
+	}
+
+	memcpy(o_p.data(), &prefixedKey[1], Public::size);
+}
+
+void Secp256k1PP::exponentToPublic(Integer const& _e, Public& o_p)
+{
+	CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
+	
+	{
+		Guard l(x_params);
+		pk.Initialize(m_params, m_params.ExponentiateBase(_e));
+	}
+	
+	exportPublicKey(pk, o_p);
+}
+#pragma GCC diagnostic pop
diff --git a/src/ringdht/eth/libdevcrypto/CryptoPP.h b/src/ringdht/eth/libdevcrypto/CryptoPP.h
new file mode 100644
index 0000000000000000000000000000000000000000..329edfaf70813fc0c80e4ce044eb2de6916e18eb
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/CryptoPP.h
@@ -0,0 +1,154 @@
+/*
+ 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 CryptoPP.h
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ *
+ * CryptoPP headers and primitive helper methods
+ */
+
+#pragma once
+
+#include <mutex>
+// need to leave this one disabled for link-time. blame cryptopp.
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma warning(push)
+#pragma warning(disable:4100 4244)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
+#pragma GCC diagnostic ignored "-Wextra"
+#include <cryptopp/sha.h>
+//#include <cryptopp/sha3.h>
+#include <cryptopp/ripemd.h>
+#include <cryptopp/aes.h>
+#include <cryptopp/pwdbased.h>
+#include <cryptopp/modes.h>
+#include <cryptopp/filters.h>
+#include <cryptopp/eccrypto.h>
+#include <cryptopp/ecp.h>
+#include <cryptopp/files.h>
+#include <cryptopp/osrng.h>
+#include <cryptopp/oids.h>
+#include <cryptopp/dsa.h>
+#pragma warning(pop)
+#pragma GCC diagnostic pop
+#include "libdevcore/SHA3.h"
+#include "Common.h"
+
+namespace dev
+{
+namespace crypto
+{
+
+using namespace CryptoPP;
+
+inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return ECP::Point(x,y); }
+
+inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
+
+/// Amount of bytes added when encrypting with encryptECIES.
+static const unsigned c_eciesOverhead = 113;
+
+/**
+ * CryptoPP secp256k1 algorithms.
+ * @todo Collect ECIES methods into class.
+ */
+class Secp256k1PP
+{	
+public:
+	static Secp256k1PP* get() { if (!s_this) s_this = new Secp256k1PP; return s_this; }
+
+	void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); }
+	
+	/// Encrypts text (replace input). (ECIES w/XOR-SHA1)
+	void encrypt(Public const& _k, bytes& io_cipher);
+	
+	/// Decrypts text (replace input). (ECIES w/XOR-SHA1)
+	void decrypt(Secret const& _k, bytes& io_text);
+	
+	/// Encrypts text (replace input). (ECIES w/AES128-CTR-SHA256)
+	void encryptECIES(Public const& _k, bytes& io_cipher);
+	
+	/// Encrypts text (replace input). (ECIES w/AES128-CTR-SHA256)
+	void encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytes& io_cipher);
+	
+	/// Decrypts text (replace input). (ECIES w/AES128-CTR-SHA256)
+	bool decryptECIES(Secret const& _k, bytes& io_text);
+	
+	/// Decrypts text (replace input). (ECIES w/AES128-CTR-SHA256)
+	bool decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytes& io_text);
+	
+	/// Key derivation function used by encryptECIES and decryptECIES.
+	bytes eciesKDF(Secret const& _z, bytes _s1, unsigned kdBitLen = 256);
+	
+	/// @returns siganture of message.
+	Signature sign(Secret const& _k, bytesConstRef _message);
+	
+	/// @returns compact siganture of provided hash.
+	Signature sign(Secret const& _k, h256 const& _hash);
+	
+	/// Verify compact signature (public key is extracted from signature).
+	bool verify(Signature const& _signature, bytesConstRef _message);
+	
+	/// Verify signature.
+	bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false);
+	
+	/// Recovers public key from compact signature. Uses libsecp256k1.
+	Public recover(Signature _signature, bytesConstRef _message);
+	
+	/// Verifies _s is a valid secret key and returns corresponding public key in o_p.
+	bool verifySecret(Secret const& _s, Public& o_p);
+	
+	void agree(Secret const& _s, Public const& _r, Secret& o_s);
+	
+protected:
+	void exportPrivateKey(DL_PrivateKey_EC<ECP> const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.writable().data(), Secret::size); }
+	
+	void exportPublicKey(DL_PublicKey_EC<ECP> const& _k, Public& o_p);
+	
+	void exponentToPublic(Integer const& _e, Public& o_p);
+	
+	template <class T> void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard<std::mutex> l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); }
+	
+	template <class T> void initializeDLScheme(Public const& _p, T& io_operator) { std::lock_guard<std::mutex> l(x_params); io_operator.AccessKey().Initialize(m_params, publicToPoint(_p)); }
+	
+private:
+	Secp256k1PP(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {}
+
+	OID m_oid;
+	
+	std::mutex x_rng;
+	AutoSeededRandomPool m_rng;
+	
+	std::mutex x_params;
+	DL_GroupParameters_EC<ECP> m_params;
+	
+	std::mutex x_curve;
+	DL_GroupParameters_EC<ECP>::EllipticCurve m_curve;
+	
+	Integer m_q;
+	Integer m_qs;
+
+	static Secp256k1PP* s_this;
+};
+
+}
+}
+
diff --git a/src/ringdht/eth/libdevcrypto/ECDHE.cpp b/src/ringdht/eth/libdevcrypto/ECDHE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bf7139a48d2aa8f00538195da45450f788fc1022
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/ECDHE.cpp
@@ -0,0 +1,44 @@
+/*
+ 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 ECDHE.cpp
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ */
+
+#include "ECDHE.h"
+#include <libdevcore/SHA3.h>
+#include "CryptoPP.h"
+
+using namespace std;
+using namespace dev;
+using namespace dev::crypto;
+
+void dev::crypto::ecdh::agree(Secret const& _s, Public const& _r, Secret& o_s)
+{
+	Secp256k1PP::get()->agree(_s, _r, o_s);
+}
+
+void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) const
+{
+	if (m_remoteEphemeral)
+		// agreement can only occur once
+		BOOST_THROW_EXCEPTION(InvalidState());
+	
+	m_remoteEphemeral = _remote;
+	Secp256k1PP::get()->agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
+}
+
diff --git a/src/ringdht/eth/libdevcrypto/ECDHE.h b/src/ringdht/eth/libdevcrypto/ECDHE.h
new file mode 100644
index 0000000000000000000000000000000000000000..3658caf3d7f08a46d3dbfd46335ff4897db18810
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/ECDHE.h
@@ -0,0 +1,81 @@
+/*
+ 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 ECDHE.h
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2014
+ *
+ * Elliptic curve Diffie-Hellman ephemeral key exchange
+ */
+
+#pragma once
+
+#include "AES.h"
+
+namespace dev
+{
+namespace crypto
+{
+	
+/// Public key of remote and corresponding shared secret.
+using AliasSession = std::pair<Public,h256>;
+	
+/**
+ * @brief An addressable EC key pair.
+ */
+class Alias
+{
+public:
+	Alias(Secret const& _s): m_secret(_s) {};
+	
+	AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); }
+	
+private:
+	std::map<Address,AliasSession> m_sessions;
+	Secret m_secret;
+};
+
+namespace ecdh
+{
+void agree(Secret const& _s, Public const& _r, Secret& o_s);
+}
+	
+/**
+ * @brief Derive DH shared secret from EC keypairs.
+ * As ephemeral keys are single-use, agreement is limited to a single occurence.
+ */
+class ECDHE
+{
+public:
+	/// Constructor (pass public key for ingress exchange).
+	ECDHE(): m_ephemeral(KeyPair::create()) {};
+
+	/// Public key sent to remote.
+	Public pubkey() { return m_ephemeral.pub(); }
+	
+	Secret seckey() { return m_ephemeral.sec(); }
+	
+	/// Input public key for dh agreement, output generated shared secret.
+	void agree(Public const& _remoteEphemeral, Secret& o_sharedSecret) const;
+	
+protected:
+	KeyPair m_ephemeral;					///< Ephemeral keypair; generated.
+	mutable Public m_remoteEphemeral;		///< Public key of remote; parameter. Set once when agree is called, otherwise immutable.
+};
+
+}
+}
+
diff --git a/src/ringdht/eth/libdevcrypto/Exceptions.h b/src/ringdht/eth/libdevcrypto/Exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..858374bda8adfd98240c21fbd29aefc19e1be3b7
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/Exceptions.h
@@ -0,0 +1,35 @@
+/*
+	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 Exceptions.h
+ * @author Christian <c@ethdev.com>
+ * @date 2016
+ */
+
+#pragma once
+
+#include <libdevcore/Exceptions.h>
+
+namespace dev
+{
+namespace crypto
+{
+
+/// Rare malfunction of cryptographic functions.
+DEV_SIMPLE_EXCEPTION(CryptoException);
+
+}
+}
diff --git a/src/ringdht/eth/libdevcrypto/Makefile.am b/src/ringdht/eth/libdevcrypto/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..b94f7ce16c42c311b4bf497372183a8960552332
--- /dev/null
+++ b/src/ringdht/eth/libdevcrypto/Makefile.am
@@ -0,0 +1,11 @@
+include $(top_srcdir)/globals.mak
+
+AM_CPPFLAGS += -I../
+noinst_LTLIBRARIES = libdevcrypto.la
+libdevcrypto_la_CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/src/ringdht/eth -DBOOST_SYSTEM_NO_DEPRECATED
+libdevcrypto_la_CXXFLAGS = @CXXFLAGS@
+
+libdevcrypto_la_SOURCES = AES.cpp \
+	ECDHE.cpp \
+	Common.cpp \
+	CryptoPP.cpp