diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 8fe76e24b..280a70fe1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -353,8 +353,16 @@ void Main::on_enableOptimizer_triggered() on_data_textChanged(); } +QString Main::contents(QString _s) +{ + return QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); +} + void Main::load(QString _s) { + QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); + ui->webView->page()->currentFrame()->evaluateJavaScript(contents); + /* QFile fin(_s); if (!fin.open(QFile::ReadOnly)) return; @@ -375,7 +383,7 @@ void Main::load(QString _s) //eval(line); line.clear(); } - } + }*/ } void Main::on_loadJS_triggered() @@ -679,7 +687,7 @@ void Main::on_importKeyFile_triggered() try { js::mValue val; - json_spirit::read_string(asString(contents(s.toStdString())), val); + json_spirit::read_string(asString(dev::contents(s.toStdString())), val); auto obj = val.get_obj(); if (obj["encseed"].type() == js::str_type) { @@ -948,7 +956,7 @@ void Main::refreshBlockCount() cwatch << "refreshBlockCount()"; auto d = ethereum()->blockChain().details(); auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty; - ui->blockCount->setText(QString("%6 #%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); + ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); } static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 _h, BlockChain const& _bc) @@ -1258,9 +1266,10 @@ void Main::on_blocks_currentItemChanged() s << "
Coinbase: " << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress; s << "
Nonce: " << info.nonce << ""; s << "
Parent: " << info.parentHash << ""; - s << "
Bloom: " << details.bloom << ""; +// s << "
Bloom: " << details.bloom << ""; s << "
Log Bloom: " << info.logBloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; + s << "
Receipts: @" << info.receiptsRoot << ":"; s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; for (auto u: block[2]) { @@ -1283,6 +1292,7 @@ void Main::on_blocks_currentItemChanged() Transaction tx(block[1][txi].data()); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce())); + auto receipt = ethereum()->blockChain().receipts(h).receipts[txi]; s << "

" << th << "

"; s << "

" << h << "[" << txi << "]

"; s << "
From: " << pretty(ss).toHtmlEscaped().toStdString() << " " << ss; @@ -1298,6 +1308,10 @@ void Main::on_blocks_currentItemChanged() s << "
R: " << hex << nouppercase << tx.signature().r << ""; s << "
S: " << hex << nouppercase << tx.signature().s << ""; s << "
Msg: " << tx.sha3(eth::WithoutSignature) << ""; + s << "
Hex: " << toHex(block[1][txi].data()) << "
"; + auto r = receipt.rlp(); + s << "
Receipt: " << toString(RLP(r)) << "
"; + s << "
Receipt-Hex: " << toHex(receipt.rlp()) << "
"; if (tx.isCreation()) { if (tx.data().size()) @@ -1602,15 +1616,15 @@ void Main::on_data_textChanged() } else if (src.substr(0, 8) == "contract") // improve this heuristic { - shared_ptr scanner = make_shared(); + dev::solidity::CompilerStack compiler; try { - m_data = dev::solidity::CompilerStack::compile(src, scanner, m_enableOptimizer); + m_data = compiler.compile(src, m_enableOptimizer); } catch (dev::Exception const& exception) { ostringstream error; - solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", *scanner); + solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner()); solidity = "

Solidity

" + QString::fromStdString(error.str()).toHtmlEscaped() + "
"; } catch (...) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 57f9c5ebd..14877f610 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -85,6 +85,7 @@ public slots: void note(QString _entry); void debug(QString _entry); void warn(QString _entry); + QString contents(QString _file); void onKeysChanged(); @@ -154,6 +155,7 @@ private slots: void on_newIdentity_triggered(); void refreshWhisper(); + void refreshBlockChain(); void addNewId(QString _ids); signals: @@ -214,7 +216,6 @@ private: void refreshPending(); void refreshAccounts(); void refreshDestination(); - void refreshBlockChain(); void refreshBlockCount(); void refreshBalances(); diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 78dbed65b..ae073b9b1 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.9"; +char const* Version = "0.7.10"; } diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 87cc069b3..198119f24 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -59,6 +59,7 @@ using bytesConstRef = vector_ref; // Numeric types. using bigint = boost::multiprecision::number>; +using u128 = boost::multiprecision::number>; using u256 = boost::multiprecision::number>; using s256 = boost::multiprecision::number>; using u160 = boost::multiprecision::number>; diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index bfcbc5e2e..bd7841402 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -29,14 +29,20 @@ using namespace dev; std::string dev::escaped(std::string const& _s, bool _all) { + static const map prettyEscapes{{'\r', 'r'}, {'\n', 'n'}, {'\t', 't'}, {'\v', 'v'}}; std::string ret; - ret.reserve(_s.size()); + 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)) + { + ret += '\\'; + ret += prettyEscapes.find(i)->second; + } else if (i < ' ' || _all) { ret += "\\x"; diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 3d2eccf13..8fc4fedb3 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -30,7 +30,7 @@ string dev::memDump(bytes const& _b, unsigned _w, bool _html) { stringstream ret; if (_html) - ret << "
";
+		ret << "
";
 	for (unsigned i = 0; i < _b.size(); i += _w)
 	{
 		ret << hex << setw(4) << setfill('0') << i << " ";
diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp
index 96f4b1896..c09a5b565 100644
--- a/libdevcore/CommonJS.cpp
+++ b/libdevcore/CommonJS.cpp
@@ -38,31 +38,20 @@ bytes jsToBytes(std::string const& _s)
 		return bytes();
 }
 
-std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r)
+bytes padded(bytes _b, unsigned _l)
 {
-	bytes b = jsToBytes(_s);
-	while (b.size() < _l)
-		b.insert(b.begin(), 0);
-	while (b.size() < _r)
-		b.push_back(0);
-	return asString(b).substr(b.size() - std::max(_l, _r));
+	while (_b.size() < _l)
+		_b.insert(_b.begin(), 0);
+	while (_b.size() < _l)
+		_b.push_back(0);
+	return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l)));
 }
 
-std::string jsPadded(std::string const& _s, unsigned _l)
+bytes unpadded(bytes _b)
 {
-	if (_s.substr(0, 2) == "0x" || _s.find_first_not_of("0123456789") == std::string::npos)
-		// Numeric: pad to right
-		return jsPadded(_s, _l, _l);
-	else
-		// Text: pad to the left
-		return jsPadded(_s, 0, _l);
-}
-
-std::string jsUnpadded(std::string _s)
-{
-	auto p = _s.find_last_not_of((char)0);
-	_s.resize(p == std::string::npos ? 0 : (p + 1));
-	return _s;
+	auto p = asString(_b).find_last_not_of((char)0);
+	_b.resize(p == std::string::npos ? 0 : (p + 1));
+	return _b;
 }
 
 }
diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h
index be98c2372..80e1a9ca1 100644
--- a/libdevcore/CommonJS.h
+++ b/libdevcore/CommonJS.h
@@ -47,9 +47,8 @@ inline std::string toJS(dev::bytes const& _n)
 }
 
 bytes jsToBytes(std::string const& _s);
-std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r);
-std::string jsPadded(std::string const& _s, unsigned _l);
-std::string jsUnpadded(std::string _s);
+bytes padded(bytes _b, unsigned _l);
+bytes unpadded(bytes _s);
 
 template  FixedHash jsToFixed(std::string const& _s)
 {
@@ -61,7 +60,7 @@ template  FixedHash jsToFixed(std::string const& _s)
 		return (typename FixedHash::Arith)(_s);
 	else
 		// Binary
-		return FixedHash(asBytes(jsPadded(_s, N)));
+		return FixedHash();	// FAIL
 }
 
 inline std::string jsToFixed(double _s)
@@ -79,7 +78,7 @@ template  boost::multiprecision::number>(_s);
 	else
 		// Binary
-		return fromBigEndian>>(asBytes(jsPadded(_s, N)));
+		return 0;			// FAIL
 }
 
 inline Address jsToAddress(std::string const& _s) { return jsToFixed(_s); }
@@ -89,7 +88,7 @@ inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); }
 
 inline std::string jsToBinary(std::string const& _s)
 {
-	return jsUnpadded(dev::toString(jsToBytes(_s)));
+	return dev::toString(unpadded(jsToBytes(_s)));
 }
 
 inline std::string jsToDecimal(std::string const& _s)
diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h
index bbc928da4..5d03c195f 100644
--- a/libdevcore/Exceptions.h
+++ b/libdevcore/Exceptions.h
@@ -45,7 +45,7 @@ struct FileError: virtual Exception {};
 typedef boost::error_info errinfo_invalidSymbol;
 typedef boost::error_info errinfo_wrongAddress;
 typedef boost::error_info errinfo_comment;
-typedef boost::error_info errinfo_required;
-typedef boost::error_info errinfo_got;
+typedef boost::error_info errinfo_required;
+typedef boost::error_info errinfo_got;
 typedef boost::tuple RequirementError;
 }
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 2353a100c..0e387ab8a 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -240,6 +240,7 @@ using h520 = FixedHash<65>;
 using h512 = FixedHash<64>;
 using h256 = FixedHash<32>;
 using h160 = FixedHash<20>;
+using h128 = FixedHash<16>;
 using h512s = std::vector;
 using h256s = std::vector;
 using h160s = std::vector;
diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h
index afedc68da..3101f63d6 100644
--- a/libdevcore/RLP.h
+++ b/libdevcore/RLP.h
@@ -158,6 +158,7 @@ public:
 
 	/// 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(); }
 	explicit operator uint16_t() const { return toInt(); }
@@ -341,7 +342,7 @@ public:
 	RLPStream& append(char const* _s) { return append(std::string(_s)); }
 	template  RLPStream& append(FixedHash _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.
+	/// Appends an arbitrary RLP fragment - this *must* be a single item unless @a _itemCount is given.
 	RLPStream& append(RLP const& _rlp, unsigned _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); }
 
 	/// Appends a sequence of data to the stream as a list.
diff --git a/libdevcrypto/SHA3MAC.cpp b/libdevcrypto/AES.cpp
similarity index 64%
rename from libdevcrypto/SHA3MAC.cpp
rename to libdevcrypto/AES.cpp
index 9498ef87b..56885ae36 100644
--- a/libdevcrypto/SHA3MAC.cpp
+++ b/libdevcrypto/AES.cpp
@@ -1,40 +1,60 @@
 /*
  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 .
  */
-/** @file SHA3MAC.cpp
+/** @file AES.cpp
  * @author Alex Leverington 
  * @date 2014
- *
- * SHA3 MAC
  */
 
 #include "CryptoPP.h"
-#include "SHA3MAC.h"
+#include "AES.h"
 
+using namespace std;
 using namespace dev;
 using namespace dev::crypto;
+using namespace dev::crypto::aes;
 using namespace CryptoPP;
 
-void crypto::sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
+struct aes::Aes128Ctr
+{
+	Aes128Ctr(h128 _k)
+	{
+		mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data());
+	}
+	CTR_Mode::Encryption mode;
+};
+
+Stream::Stream(StreamType, h128 _ckey):
+	m_cSecret(_ckey)
+{
+	cryptor = new Aes128Ctr(_ckey);
+}
+
+Stream::~Stream()
+{
+	delete cryptor;
+}
+
+void Stream::update(bytesRef)
+{
+
+}
+
+size_t Stream::streamOut(bytes&)
 {
-	CryptoPP::SHA3_256 ctx;
-	assert(_secret.size() > 0);
-	ctx.Update((byte*)_secret.data(), _secret.size());
-	ctx.Update((byte*)_plain.data(), _plain.size());
-	assert(_output.size() >= 32);
-	ctx.Final(_output.data());
+	return 0;
 }
 
diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h
new file mode 100644
index 000000000..f0646eb85
--- /dev/null
+++ b/libdevcrypto/AES.h
@@ -0,0 +1,89 @@
+/*
+ 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 .
+ */
+/** @file AES.h
+ * @author Alex Leverington 
+ * @date 2014
+ *
+ * AES
+ * todo: use openssl
+ */
+
+#pragma once
+
+#include 
+#include "Common.h"
+
+namespace dev
+{
+namespace crypto
+{
+namespace aes
+{
+
+struct Aes128Ctr;
+enum StreamType { Encrypt, Decrypt };
+	
+/**
+ * @brief Encrypted stream
+ */
+class Stream
+{
+public:
+	// streamtype maybe irrelevant w/ctr
+	Stream(StreamType _t, h128 _ckey);
+	~Stream();
+	
+	virtual void update(bytesRef io_bytes);
+	
+	/// Move ciphertext to _bytes.
+	virtual size_t streamOut(bytes& o_bytes);
+	
+private:
+	Stream(Stream const&) = delete;
+	Stream& operator=(Stream const&) = delete;
+	
+	h128 m_cSecret;
+	bytes m_text;
+
+	Aes128Ctr* cryptor;
+};
+	
+
+/**
+ * @brief Encrypted stream with inband SHA3 mac at specific interval.
+ */
+class AuthenticatedStream: public Stream
+{
+public:
+	AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; }
+	
+	AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>((byte const*)_s.data()+16,h128::ConstructFromPointer)) { m_macInterval = _interval; }
+	
+	/// Adjust mac interval. Next mac will be xored with value.
+	void adjustInterval(unsigned _interval) { m_macInterval = _interval; }
+	
+private:
+	AuthenticatedStream(AuthenticatedStream const&) = delete;
+	AuthenticatedStream& operator=(AuthenticatedStream const&) = delete;
+	
+	std::atomic m_macInterval;
+	h128 m_macSecret;
+};
+
+}
+}
+}
\ No newline at end of file
diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h
index db6d7c615..9070725e9 100644
--- a/libdevcrypto/All.h
+++ b/libdevcrypto/All.h
@@ -1,12 +1,8 @@
 #pragma once
 
 #include "Common.h"
-#include "CryptoPP.h"
-#include "EC.h"
+#include "AES.h"
+#include "ECDHE.h"
 #include "FileSystem.h"
-#include "MemoryDB.h"
-#include "OverlayDB.h"
 #include "SHA3.h"
-#include "SHA3MAC.h"
-#include "TrieCommon.h"
 #include "TrieDB.h"
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index 2db65aae3..fa5a544a1 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -23,89 +23,104 @@
 #include 
 #include 
 #include 
-#include "EC.h"
 #include "SHA3.h"
 #include "FileSystem.h"
+#include "CryptoPP.h"
 #include "Common.h"
 using namespace std;
 using namespace dev;
-using namespace crypto;
+using namespace dev::crypto;
 
-//#define ETH_ADDRESS_DEBUG 1
+static Secp256k1 s_secp256k1;
 
-Address dev::toAddress(Secret _secret)
+Public dev::toPublic(Secret const& _secret)
 {
-	return KeyPair(_secret).address();
+	Public p;
+	s_secp256k1.toPublic(_secret, p);
+	return std::move(p);
 }
 
-KeyPair KeyPair::create()
+Address dev::toAddress(Public const& _public)
 {
-	static mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
-	uniform_int_distribution d(0, 255);
-
-	for (int i = 0; i < 100; ++i)
-	{
-		h256 sec;
-		for (unsigned i = 0; i < 32; ++i)
-			sec[i] = (byte)d(s_eng);
-
-		KeyPair ret(sec);
-		if (ret.address())
-			return ret;
-	}
-	return KeyPair();
+	return s_secp256k1.toAddress(_public);
 }
 
-KeyPair::KeyPair(h256 _sec):
-	m_secret(_sec)
+Address dev::toAddress(Secret const& _secret)
 {
-	toPublic(m_secret, m_public);
-	if (verifySecret(m_secret, m_public))
-		m_address = right160(dev::sha3(m_public.ref()));
-	
-#if ETH_ADDRESS_DEBUG
-	cout << "---- ADDRESS -------------------------------" << endl;
-	cout << "SEC: " << m_secret << endl;
-	cout << "PUB: " << m_public << endl;
-	cout << "ADR: " << m_address << endl;
-#endif
+	Public p;
+	s_secp256k1.toPublic(_secret, p);
+	return s_secp256k1.toAddress(p);
 }
 
-KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
-{
-	return KeyPair(sha3(aesDecrypt(_seed, _password)));
-}
-
-void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher)
+void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
 {
 	bytes io = _plain.toBytes();
-	crypto::encrypt(_k, io);
+	s_secp256k1.encrypt(_k, io);
 	o_cipher = std::move(io);
 }
 
-bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
+bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
 {
 	bytes io = _cipher.toBytes();
-	crypto::decrypt(_k, io);
+	s_secp256k1.decrypt(_k, io);
 	if (io.empty())
 		return false;
 	o_plaintext = std::move(io);
 	return true;
 }
 
-Public dev::recover(Signature _sig, h256 _message)
+Public dev::recover(Signature const& _sig, h256 const& _message)
+{
+	return s_secp256k1.recover(_sig, _message.ref());
+}
+
+Signature dev::sign(Secret const& _k, h256 const& _hash)
+{
+	return s_secp256k1.sign(_k, _hash);
+}
+
+bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
 {
-	return crypto::recover(_sig, _message.ref());
+	return s_secp256k1.verify(_p, _s, _hash.ref(), true);
 }
 
-Signature dev::sign(Secret _k, h256 _hash)
+KeyPair KeyPair::create()
 {
-	return crypto::sign(_k, _hash);
+	static mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
+	uniform_int_distribution d(0, 255);
+
+	for (int i = 0; i < 100; ++i)
+	{
+		KeyPair ret(FixedHash<32>::random(s_eng));
+		if (ret.address())
+			return ret;
+	}
+	return KeyPair();
 }
 
-bool dev::verify(Public _p, Signature _s, h256 _hash)
+KeyPair::KeyPair(h256 _sec):
+	m_secret(_sec)
+{
+	if (s_secp256k1.verifySecret(m_secret, m_public))
+		m_address = s_secp256k1.toAddress(m_public);
+}
+
+KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
 {
-	return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
+	return KeyPair(sha3(aesDecrypt(_seed, _password)));
+}
+
+h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
+{
+	// H(H(r||k)^h)
+	h256 s;
+	sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
+	s ^= _hash;
+	sha3(s.ref(), s.ref());
+	
+	if (!s || !_hash || !_priv)
+		BOOST_THROW_EXCEPTION(InvalidState());
+	return std::move(s);
 }
 
 h256 Nonce::get(bool _commit)
@@ -125,7 +140,7 @@ h256 Nonce::get(bool _commit)
 		else
 		{
 			// todo: replace w/entropy from user and system
-			std::mt19937_64 s_eng(time(0));
+			std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count());
 			std::uniform_int_distribution d(0, 255);
 			for (unsigned i = 0; i < 32; ++i)
 				s_seed[i] = (byte)d(s_eng);
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index e95eefa40..2ec332d8d 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -52,30 +52,36 @@ using Address = h160;
 /// A vector of Ethereum addresses.
 using Addresses = h160s;
 
-/// A vector of Ethereum addresses.
+/// A set of Ethereum addresses.
 using AddressSet = std::set;
 
 /// A vector of secrets.
 using Secrets = h256s;
 
 /// 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 _secret);
+Address toAddress(Secret const& _secret);
 
 /// Encrypts plain text using Public key.
-void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher);
+void encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
 
 /// Decrypts cipher using Secret key.
-bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext);
+bool decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
 	
 /// Recovers Public key from signed message hash.
-Public recover(Signature _sig, h256 _hash);
+Public recover(Signature const& _sig, h256 const& _hash);
 	
 /// Returns siganture of message hash.
-Signature sign(Secret _k, h256 _hash);
+Signature sign(Secret const& _k, h256 const& _hash);
 	
 /// Verify signature.
-bool verify(Public _k, Signature _s, h256 _hash);
+bool verify(Public const& _k, Signature const& _s, h256 const& _hash);
 
 /// Simple class that represents a "key pair".
 /// All of the data of the class can be regenerated from the secret key (m_secret) alone.
@@ -119,6 +125,9 @@ namespace crypto
 {
 struct InvalidState: public dev::Exception {};
 
+/// Key derivation
+h256 kdf(Secret const& _priv, h256 const& _hash);
+	
 /**
  * @brief Generator for nonce material
  */
diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp
index 1b51d5bd5..858fd53ff 100644
--- a/libdevcrypto/CryptoPP.cpp
+++ b/libdevcrypto/CryptoPP.cpp
@@ -21,25 +21,206 @@
 
 #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.");
 
-/// Integer and Point Conversion:
+void Secp256k1::encrypt(Public const& _k, bytes& io_cipher)
+{
+	ECIES::Encryptor e;
+	initializeDLScheme(_k, e);
+
+	size_t plen = io_cipher.size();
+	bytes ciphertext;
+	ciphertext.resize(e.CiphertextLength(plen));
+	
+	{
+		lock_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 Secp256k1::decrypt(Secret const& _k, bytes& io_text)
+{
+	CryptoPP::ECIES::Decryptor d;
+	initializeDLScheme(_k, d);
+	
+	size_t clen = io_text.size();
+	bytes plain;
+	plain.resize(d.MaxPlaintextLength(io_text.size()));
+	
+	DecodingResult r;
+	{
+		lock_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 Secp256k1::sign(Secret const& _k, bytesConstRef _message)
+{
+	return sign(_k, sha3(_message));
+}
+
+Signature Secp256k1::sign(Secret const& _key, h256 const& _hash)
+{
+	// assumption made by signing alogrithm
+	asserts(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;
+	{
+		lock_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.asBytes().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 Secp256k1::verify(Signature const& _signature, bytesConstRef _message)
+{
+	return !!recover(_signature, _message);
+}
 
-void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p)
+bool Secp256k1::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 Secp256k1::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;
+	{
+		lock_guard l(x_curve);
+		m_curve.DecodePoint(x, encodedpoint, 33);
+		if (!m_curve.VerifyPoint(x))
+			return recovered;
+	}
+	
+//	if (_signature[64] & 2)
+//	{
+//		r += m_q;
+//		lock_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];
+	{
+		lock_guard l(x_curve);
+		// todo: make generator member
+		p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
+		m_curve.EncodePoint(recoveredbytes, p, false);
+	}
+	memcpy(recovered.data(), &recoveredbytes[1], 64);
+	return recovered;
+}
+
+bool Secp256k1::verifySecret(Secret const& _s, Public& _p)
+{
+	DL_PrivateKey_EC k;
+	k.Initialize(m_params, secretToExponent(_s));
+	if (!k.Validate(m_rng, 3))
+		return false;
+	
+	DL_PublicKey_EC pub;
+	k.MakePublicKey(pub);
+	if (!k.Validate(m_rng, 3))
+		return false;
+
+	exportPublicKey(pub, _p);
+	return true;
+}
+
+void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
+{
+	ECDH::Domain d(m_oid);
+	assert(d.AgreedValueLength() == sizeof(o_s));
+	byte remote[65] = {0x04};
+	memcpy(&remote[1], _r.data(), 64);
+	assert(d.Agree(o_s.data(), _s.data(), remote));
+}
+
+void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& o_p)
 {
 	bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
-	secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
+	
+	{
+		lock_guard l(x_params);
+		m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
+		assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
+	}
 
-	assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
-	memcpy(_p.data(), &prefixedKey[1], Public::size);
+	memcpy(o_p.data(), &prefixedKey[1], Public::size);
 }
 
-void pp::exponentToPublic(Integer const& _e, Public& _p)
+void Secp256k1::exponentToPublic(Integer const& _e, Public& o_p)
 {
 	CryptoPP::DL_PublicKey_EC pk;
-	pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e));
-	pp::exportPublicKey(pk, _p);
-}
\ No newline at end of file
+	
+	{
+		lock_guard l(x_params);
+		pk.Initialize(m_params, m_params.ExponentiateBase(_e));
+	}
+	
+	exportPublicKey(pk, o_p);
+}
+
diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h
index 4f9725ad8..7ec95c552 100644
--- a/libdevcrypto/CryptoPP.h
+++ b/libdevcrypto/CryptoPP.h
@@ -23,6 +23,7 @@
 
 #pragma once
 
+#include 
 // need to leave this one disabled for link-time. blame cryptopp.
 #pragma GCC diagnostic ignored "-Wunused-function"
 #pragma warning(push)
@@ -48,42 +49,85 @@
 #include 
 #pragma warning(pop)
 #pragma GCC diagnostic pop
+#include "SHA3.h"
 #include "Common.h"
 
 namespace dev
 {
 namespace crypto
 {
-namespace pp
-{
-	
+
 using namespace CryptoPP;
+
+inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
+
+inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
+	
+/**
+ * CryptoPP secp256k1 algorithms.
+ */
+class Secp256k1
+{	
+public:
+	Secp256k1(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {}
 	
-/// CryptoPP random number pool
-static CryptoPP::AutoSeededRandomPool PRNG;
+	Address toAddress(Public const& _p) { return right160(sha3(_p.ref())); }
 	
-/// CryptoPP EC Cruve
-static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1();
+	void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); }
 	
-static const CryptoPP::DL_GroupParameters_EC secp256k1Params(secp256k1Curve);
+	/// Encrypts text (replace input).
+	void encrypt(Public const& _k, bytes& io_cipher);
 	
-static ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
+	/// Decrypts text (replace input).
+	void decrypt(Secret const& _k, bytes& io_text);
 	
-static Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
-
-void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p);
-
-static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
+	/// @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);
 	
-void exponentToPublic(Integer const& _e, Public& _p);
+	/// Recovers public key from compact signature. Uses libsecp256k1.
+	Public recover(Signature _signature, bytesConstRef _message);
 	
-template 
-void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); }
+	/// Verifies _s is a valid secret key and returns corresponding public key in o_p.
+	bool verifySecret(Secret const& _s, Public& o_p);
 	
-template 
-void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); }
+	void agree(Secret const& _s, Public const& _r, h256& o_s);
+	
+protected:
+	void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.data(), Secret::size); }
+	
+	void exportPublicKey(DL_PublicKey_EC const& _k, Public& o_p);
+	
+	void exponentToPublic(Integer const& _e, Public& o_p);
+	
+	template  void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); }
+	
+	template  void initializeDLScheme(Public const& _p, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, publicToPoint(_p)); }
+	
+private:
+	OID m_oid;
+	
+	std::mutex x_rng;
+	AutoSeededRandomPool m_rng;
+	
+	std::mutex x_params;
+	DL_GroupParameters_EC m_params;
+	
+	std::mutex x_curve;
+	DL_GroupParameters_EC::EllipticCurve m_curve;
+	
+	Integer m_q;
+	Integer m_qs;
+};
 
 }
 }
-}
 
diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp
deleted file mode 100644
index bdbe10dd2..000000000
--- a/libdevcrypto/EC.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- 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 .
- */
-/** 
- * @file EC.cpp
- * @author Alex Leverington 
- * @date 2014
- *
- * ECDSA, ECIES
- */
-
-#include 
-#include "CryptoPP.h"
-#include "SHA3.h"
-#include "SHA3MAC.h"
-#include "EC.h"
-
-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.");
-
-using namespace std;
-using namespace dev;
-using namespace dev::crypto;
-using namespace CryptoPP;
-using namespace pp;
-
-void crypto::toPublic(Secret const& _s, Public& o_public)
-{
-	exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public);
-}
-
-h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
-{
-	// H(H(r||k)^h)
-	h256 s;
-	sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
-	s ^= _hash;
-	sha3(s.ref(), s.ref());
-	
-	if (!s || !_hash || !_priv)
-		BOOST_THROW_EXCEPTION(InvalidState());
-	return std::move(s);
-}
-
-void crypto::encrypt(Public const& _k, bytes& io_cipher)
-{
-	ECIES::Encryptor e;
-	initializeDLScheme(_k, e);
-	size_t plen = io_cipher.size();
-	bytes c;
-	c.resize(e.CiphertextLength(plen));
-	// todo: use StringSource with io_cipher as input and output.
-	e.Encrypt(PRNG, io_cipher.data(), plen, c.data());
-	memset(io_cipher.data(), 0, io_cipher.size());
-	io_cipher = std::move(c);
-}
-
-void crypto::decrypt(Secret const& _k, bytes& io_text)
-{
-	CryptoPP::ECIES::Decryptor d;
-	initializeDLScheme(_k, d);
-	size_t clen = io_text.size();
-	bytes p;
-	p.resize(d.MaxPlaintextLength(io_text.size()));
-	// todo: use StringSource with io_text as input and output.
-	DecodingResult r = d.Decrypt(PRNG, io_text.data(), clen, p.data());
-	if (!r.isValidCoding)
-	{
-		io_text.clear();
-		return;
-	}
-	io_text.resize(r.messageLength);
-	io_text = std::move(p);
-}
-
-Signature crypto::sign(Secret const& _k, bytesConstRef _message)
-{
-	return crypto::sign(_k, sha3(_message));
-}
-
-Signature crypto::sign(Secret const& _key, h256 const& _hash)
-{
-	ECDSA::Signer signer;
-	initializeDLScheme(_key, signer);
-
-	Integer const& q = secp256k1Params.GetGroupOrder();
-	Integer const& qs = secp256k1Params.GetSubgroupOrder();
-	Integer e(_hash.asBytes().data(), 32);
-
-	Integer k(kdf(_key, _hash).data(), 32);
-	if (k == 0)
-		BOOST_THROW_EXCEPTION(InvalidState());
-	k = 1 + (k % (qs - 1));
-	
-	ECP::Point rp = secp256k1Params.ExponentiateBase(k);
-	Integer r = secp256k1Params.ConvertElementToInteger(rp);
-	int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
-	
-	Integer kInv = k.InverseMod(q);
-	Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + e)) % q;
-	assert(!!r && !!s);
-	
-	if (s > qs)
-	{
-		s = q - s;
-		if (recid)
-			recid ^= 1;
-	}
-	
-	Signature sig;
-	r.Encode(sig.data(), 32);
-	s.Encode(sig.data() + 32, 32);
-	sig[64] = recid;
-	return sig;
-}
-
-bool crypto::verify(Signature const& _signature, bytesConstRef _message)
-{
-	return crypto::verify(crypto::recover(_signature, _message), _signature, _message);
-}
-
-bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
-{
-	static size_t derMaxEncodingLength = 72;
-	if (_hashed)
-	{
-		assert(_message.size() == 32);
-		byte encpub[65] = {0x04};
-		memcpy(&encpub[1], _p.data(), 64);
-		byte dersig[derMaxEncodingLength];
-		size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
-		assert(cssz <= derMaxEncodingLength);
-		return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65));
-	}
-	
-	ECDSA::Verifier verifier;
-	initializeDLScheme(_p, verifier);
-	return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1);
-}
-
-Public crypto::recover(Signature _signature, bytesConstRef _message)
-{
-	secp256k1_start();
-	
-	int pubkeylen = 65;
-	byte pubkey[pubkeylen];
-	if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64]))
-		return Public();
-	
-#if ETH_CRYPTO_TRACE
-	h256* sig = (h256 const*)_signature.data();
-	cout << "---- RECOVER -------------------------------" << endl;
-	cout << "MSG: " << _message << endl;
-	cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_signature[64] - 27) << "+27" << endl;
-	cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
-#endif
-	
-	Public ret;
-	memcpy(&ret, &(pubkey[1]), sizeof(Public));
-	return ret;
-}
-
-bool crypto::verifySecret(Secret const& _s, Public const& _p)
-{
-	secp256k1_start();
-	int ok = secp256k1_ecdsa_seckey_verify(_s.data());
-	if (!ok)
-		return false;
-	
-	int pubkeylen = 65;
-	byte pubkey[pubkeylen];
-	ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0);
-	if (!ok || pubkeylen != 65)
-		return false;
-	
-	ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
-	if (!ok)
-		return false;
-	
-	for (int i = 0; i < 32; i++)
-		if (pubkey[i+1]!=_p[i])
-			return false;
-
-	return true;
-}
-
diff --git a/libdevcrypto/EC.h b/libdevcrypto/EC.h
deleted file mode 100644
index 2a4155edf..000000000
--- a/libdevcrypto/EC.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- 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 .
- */
-/** @file EC.h
- * @author Alex Leverington 
- * @date 2014
- *
- * ECDSA, ECIES
- */
-
-#pragma once
-
-#include "Common.h"
-
-namespace dev
-{
-namespace crypto
-{
-
-void toPublic(Secret const& _s, Public& o_public);
-h256 kdf(Secret const& _priv, h256 const& _hash);
-	
-/// Encrypts text (in place).
-void encrypt(Public const& _k, bytes& io_cipher);
-
-/// Decrypts text (in place).
-void decrypt(Secret const& _k, bytes& io_text);
-
-/// Returns siganture of message.
-Signature sign(Secret const& _k, bytesConstRef _message);
-	
-/// Returns compact siganture of message hash.
-Signature sign(Secret const& _k, h256 const& _hash);
-
-/// Verify compact signature (public key is extracted from message).
-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);
-
-bool verifySecret(Secret const& _s, Public const& _p);
-	
-}
-	
-}
-
diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp
new file mode 100644
index 000000000..dd72e8176
--- /dev/null
+++ b/libdevcrypto/ECDHE.cpp
@@ -0,0 +1,100 @@
+/*
+ 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 .
+ */
+/** @file ECDHE.cpp
+ * @author Alex Leverington 
+ * @date 2014
+ */
+
+#include "SHA3.h"
+#include "CryptoPP.h"
+#include "ECDHE.h"
+
+using namespace std;
+using namespace dev;
+using namespace dev::crypto;
+
+static Secp256k1 s_secp256k1;
+
+void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
+{
+	if (m_remoteEphemeral)
+		// agreement can only occur once
+		BOOST_THROW_EXCEPTION(InvalidState());
+	
+	m_remoteEphemeral = _remote;
+	s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
+}
+
+void ECDHEKeyExchange::agree(Public const& _remoteEphemeral)
+{
+	s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret);
+}
+
+void ECDHEKeyExchange::exchange(bytes& o_exchange)
+{
+	if (!m_ephemeralSecret)
+		// didn't agree on public remote
+		BOOST_THROW_EXCEPTION(InvalidState());
+
+	// The key exchange payload is in two parts and is encrypted
+	// using ephemeral keypair.
+	//
+	// The first part is the 'prefix' which is a zero-knowledge proof
+	// allowing the remote to resume or emplace a previous session.
+	// If a session previously exists:
+	//	prefix is sha3(token) // todo: ephemeral entropy from both sides
+	// If a session doesn't exist:
+	//	prefix is sha3(m_ephemeralSecret)
+	//
+	// The second part is encrypted using the public key which relates to the prefix.
+	
+	Public encpk = m_known.first ? m_known.first : m_remoteEphemeral;
+	bytes exchange(encpk.asBytes());
+	
+	// This is the public key which we would like the remote to use,
+	// which maybe different than the previously-known public key.
+	//
+	// Here we should pick an appropriate alias or generate a new one,
+	// but for now, we use static alias passed to constructor.
+	//
+	Public p = toPublic(m_alias.m_secret);
+	exchange.resize(exchange.size() + sizeof(p));
+	memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p));
+	
+	// protocol parameters; should be fixed size
+	bytes v({0x80});
+	exchange.resize(exchange.size() + v.size());
+	memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size());
+	
+	h256 auth;
+	sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref());
+	Signature sig = s_secp256k1.sign(m_alias.m_secret, auth);
+	exchange.resize(exchange.size() + sizeof(sig));
+	memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig));
+	
+	aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0);
+	h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral));
+	aes.update(prefix.ref());
+	
+	s_secp256k1.encrypt(encpk, exchange);
+	aes.update(&exchange);
+
+	aes.streamOut(o_exchange);
+}
+
+
+
diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h
new file mode 100644
index 000000000..f77f7fcff
--- /dev/null
+++ b/libdevcrypto/ECDHE.h
@@ -0,0 +1,109 @@
+/*
+ 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 .
+ */
+/** @file ECDHE.h
+ * @author Alex Leverington 
+ * @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.
+typedef std::pair AliasSession;
+	
+/**
+ * @brief An addressable EC key pair.
+ */
+class Alias
+{
+	friend class ECDHEKeyExchange; // todo: remove
+public:
+	Alias(Secret _s): m_secret(_s) {};
+	
+	AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); }
+	
+private:
+	std::map m_sessions;
+	Secret m_secret;
+};
+	
+/**
+ * @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(); }
+	
+	/// Input public key for dh agreement, output generated shared secret.
+	void agree(Public const& _remoteEphemeral, Secret& o_sharedSecret);
+	
+protected:
+	KeyPair m_ephemeral;			///< Ephemeral keypair; generated.
+	Public m_remoteEphemeral;		///< Public key of remote; parameter.
+};
+
+/**
+ * @brief Secure exchange of static keys.
+ * Key exchange is encrypted with public key of remote and then encrypted by block cipher. For a blind remote the ecdhe public key is used to encrypt exchange, and for a known remote the known public key is used. The block cipher key is derived from ecdhe shared secret.
+ *
+ * Usage: Agree -> Exchange -> Authenticate
+ */
+class ECDHEKeyExchange: private ECDHE
+{
+public:
+	/// Exchange with unknown remote (pass public key for ingress exchange)
+	ECDHEKeyExchange(Alias& _k): m_alias(_k) {};
+
+	/// Exchange with known remote
+	ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {};
+
+	/// Provide public key for dh agreement to generate shared secret.
+	void agree(Public const& _remoteEphemeral);
+	
+	/// @returns encrypted payload of key exchange
+	void exchange(bytes& o_exchange);
+	
+	/// Decrypt payload, check mac, check trust, decrypt exchange, authenticate exchange, verify version, verify signature, and if no failure occurs, update or creats trust and derive session-shared-secret.
+	bool authenticate(bytes _exchangeIn);
+
+private:
+	Secret m_ephemeralSecret;
+	Alias m_alias;
+	AliasSession m_known;
+	Secret m_sharedAliasSecret;
+
+	FixedHash<16> m_sharedC;
+	FixedHash<16> m_sharedM;
+};
+
+}
+}
+
diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp
index 4a0cd469e..1fc9be950 100644
--- a/libdevcrypto/SHA3.cpp
+++ b/libdevcrypto/SHA3.cpp
@@ -86,6 +86,16 @@ h256 sha3(bytesConstRef _input)
 	sha3(_input, bytesRef(&ret[0], 32));
 	return ret;
 }
+	
+void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
+{
+	CryptoPP::SHA3_256 ctx;
+	assert(_secret.size() > 0);
+	ctx.Update((byte*)_secret.data(), _secret.size());
+	ctx.Update((byte*)_plain.data(), _plain.size());
+	assert(_output.size() >= 32);
+	ctx.Final(_output.data());
+}
 
 bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt)
 {
diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h
index 7aa4db246..f27e378ba 100644
--- a/libdevcrypto/SHA3.h
+++ b/libdevcrypto/SHA3.h
@@ -55,6 +55,9 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
 
 /// 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)); }
+	
+/// Calculate SHA3-256 MAC
+void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output);
 
 /// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
 template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); }
diff --git a/libdevcrypto/SHA3MAC.h b/libdevcrypto/SHA3MAC.h
deleted file mode 100644
index 4b2d06eac..000000000
--- a/libdevcrypto/SHA3MAC.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- 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 .
- */
-/** @file SHA3MAC.h
- * @author Alex Leverington 
- * @date 2014
- *
- * SHA3 MAC
- */
-
-#pragma once
-
-#include 
-#include 
-
-namespace dev
-{
-namespace crypto
-{
-
-void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output);
-
-}
-}
-
diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp
index 8e21884ee..21bdaba2e 100644
--- a/libethcore/CommonEth.cpp
+++ b/libethcore/CommonEth.cpp
@@ -28,13 +28,12 @@ using namespace std;
 using namespace dev;
 using namespace dev::eth;
 
-//#define ETH_ADDRESS_DEBUG 1
 namespace dev
 {
 namespace eth
 {
 
-const unsigned c_protocolVersion = 39;
+const unsigned c_protocolVersion = 42;
 const unsigned c_databaseVersion = 4;
 
 static const vector> g_units =
@@ -84,30 +83,4 @@ std::string formatBalance(u256 _b)
 	return ret.str();
 }
 
-Address toAddress(Secret _private)
-{
-	secp256k1_start();
-
-	byte pubkey[65];
-	int pubkeylen = 65;
-	int ok = secp256k1_ecdsa_seckey_verify(_private.data());
-	if (!ok)
-		return Address();
-	ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0);
-	assert(pubkeylen == 65);
-	if (!ok)
-		return Address();
-	ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
-	if (!ok)
-		return Address();
-	auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
-#if ETH_ADDRESS_DEBUG
-	cout << "---- ADDRESS -------------------------------" << endl;
-	cout << "SEC: " << _private << endl;
-	cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
-	cout << "ADR: " << ret << endl;
-#endif
-	return ret;
-}
-
 }}
diff --git a/libethcore/CryptoHeaders.h b/libethcore/CryptoHeaders.h
deleted file mode 100644
index 4ff63f1d7..000000000
--- a/libethcore/CryptoHeaders.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-	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 .
-*/
-/** @file CryptoHeaders.h
- * @author Tim Hughes 
- * @date 2014
- */
-#pragma once
-
-// need to leave this one disabled
-#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"
-#include 
-#include 
-#include 
-#include 
-#pragma warning(pop)
-#pragma GCC diagnostic pop
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index fb89eb21e..c3a8b2a80 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -71,7 +71,7 @@ bool Executive::setup(bytesConstRef _rlp)
 	if (m_t.gas() < gasCost)
 	{
 		clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas();
-		BOOST_THROW_EXCEPTION(OutOfGas());
+		BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasCost, (bigint)m_t.gas()));
 	}
 
 	u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice();
@@ -80,14 +80,14 @@ bool Executive::setup(bytesConstRef _rlp)
 	if (m_s.balance(m_sender) < cost)
 	{
 		clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender);
-		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((int)cost, (int)m_s.balance(m_sender)));
+		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender)));
 	}
 
 	u256 startGasUsed = m_s.gasUsed();
 	if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit)
 	{
 		clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas();
-		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((int)(m_s.m_currentBlock.gasLimit - startGasUsed), (int)m_t.gas()));
+		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
 	}
 
 	// Increment associated nonce for sender.
@@ -123,11 +123,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
 		m_ext = new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms);
 	}
 	else
-	{
 		m_endGas = _gas;
-		if (m_ext)
-			m_ext->sub.logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes()));
-	}
 	return !m_ext;
 }
 
@@ -177,7 +173,10 @@ bool Executive::go(OnOpFunc const& _onOp)
 		{
 			m_out = m_vm->go(*m_ext, _onOp);
 			if (m_ext)
+			{
 				m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds);
+				m_logs = m_ext->sub.logs;
+			}
 			m_endGas = m_vm->gas();
 		}
 		catch (StepsDone const&)
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 5eb315439..69faf983c 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -21,9 +21,10 @@
 
 #include "State.h"
 
-#include 
-#include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -113,8 +114,6 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db):
 	m_ourAddress(_coinbaseAddress),
 	m_blockReward(c_blockReward)
 {
-	secp256k1_start();
-
 	// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
 	m_state.init();
 
@@ -138,8 +137,6 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h):
 	m_state(&m_db),
 	m_blockReward(c_blockReward)
 {
-	secp256k1_start();
-
 	// TODO THINK: is this necessary?
 	m_state.init();
 
@@ -325,8 +322,8 @@ StateDiff State::diff(State const& _c) const
 	for (auto i: _c.m_cache)
 		ads.insert(i.first);
 
-	cnote << *this;
-	cnote << _c;
+//	cnote << *this;
+//	cnote << _c;
 
 	for (auto i: ads)
 	{
@@ -553,10 +550,12 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged)
 				try
 				{
 					uncommitToMine();
+//					boost::timer t;
 					execute(i.second);
 					ret.push_back(m_receipts.back().changes().bloom());
 					_tq.noteGood(i);
 					++goodTxs;
+//					cnote << "TX took:" << t.elapsed() * 1000;
 				}
 				catch (InvalidNonce const& in)
 				{
@@ -792,8 +791,6 @@ h256 State::oldBloom() const
 LogBloom State::logBloom() const
 {
 	LogBloom ret;
-	auto sa = sha3(m_currentBlock.coinbaseAddress.ref());
-	ret.shiftBloom<3>(sa);
 	for (TransactionReceipt const& i: m_receipts)
 		ret |= i.bloom();
 	return ret;
@@ -1242,12 +1239,6 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA
 
 		return !revert;
 	}
-	else
-	{
-		// non-contract call
-		if (o_sub)
-			o_sub->logs.push_back(LogEntry(_receiveAddress, {u256((u160)_senderAddress) + 1}, bytes()));
-	}
 	return true;
 }
 
diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h
index 26539c4a9..e24c224e7 100644
--- a/libethereum/TransactionReceipt.h
+++ b/libethereum/TransactionReceipt.h
@@ -55,6 +55,8 @@ public:
 			l.streamRLP(_s);
 	}
 
+	bytes rlp() const { RLPStream s; streamRLP(s); return s.out(); }
+
 private:
 	h256 m_stateRoot;
 	u256 m_gasUsed;
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 8a6b2edc9..65761e410 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -49,7 +49,7 @@ using LogBloom = h512;
 struct LogEntry
 {
 	LogEntry() {}
-	LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = (bytes)_r[2]; }
+	LogEntry(RLP const& _r) { address = (Address)_r[0]; topics = (h256Set)_r[1]; data = _r[2].toBytes(); }
 	LogEntry(Address const& _address, h256s const& _ts, bytes&& _d): address(_address), topics(toSet(_ts)), data(std::move(_d)) {}
 
 	void streamRLP(RLPStream& _s) const { _s.appendList(3) << address << topics << data; }
diff --git a/libevm/FeeStructure.cpp b/libevm/FeeStructure.cpp
index 47236b506..6d868cac5 100644
--- a/libevm/FeeStructure.cpp
+++ b/libevm/FeeStructure.cpp
@@ -37,3 +37,6 @@ u256 const dev::eth::c_callGas = 20;
 u256 const dev::eth::c_memoryGas = 1;
 u256 const dev::eth::c_txDataGas = 5;
 u256 const dev::eth::c_txGas = 500;
+u256 const dev::eth::c_logGas = 32;
+u256 const dev::eth::c_logDataGas = 1;
+u256 const dev::eth::c_logTopicGas = 32;
diff --git a/libevm/FeeStructure.h b/libevm/FeeStructure.h
index 84a2551d9..e57f7ccf8 100644
--- a/libevm/FeeStructure.h
+++ b/libevm/FeeStructure.h
@@ -40,6 +40,9 @@ extern u256 const c_callGas;			///< Once per CALL operation & message call trans
 extern u256 const c_memoryGas;			///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
 extern u256 const c_txDataGas;			///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions.
 extern u256 const c_txGas;				///< Per transaction. NOTE: Not payable on data of calls between transactions.
+extern u256 const c_logGas;				///< Per LOG* operation.
+extern u256 const c_logDataGas;			///< Per byte in a LOG* operation's data.
+extern u256 const c_logTopicGas;		///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
 
 }
 }
diff --git a/libevm/VM.h b/libevm/VM.h
index a35b3f005..487c8cd1a 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -71,7 +71,7 @@ public:
 	template 
 	bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1);
 
-	void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError(int(_n), m_stack.size())); }
+	void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError((bigint)_n, (bigint)m_stack.size())); }
 	void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
 	u256 gas() const { return m_gas; }
 	u256 curPC() const { return m_curPC; }
@@ -206,14 +206,15 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 		{
 			unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
 			require(n + 2);
-			newTempSize = memNeed(m_stack[m_stack.size() - 1 - n], m_stack[m_stack.size() - 2 - n]);
+			runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
+			newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
 			break;
 		}
 
 		case Instruction::CALL:
 		case Instruction::CALLCODE:
 			require(7);
-			runGas = c_callGas + m_stack[m_stack.size() - 1];
+			runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
 			newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
 			break;
 
@@ -743,18 +744,38 @@ template  dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
 			break;*/
 		case Instruction::LOG0:
 			_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
+			m_stack.pop_back();
+			m_stack.pop_back();
 			break;
 		case Instruction::LOG1:
 			_ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
 			break;
 		case Instruction::LOG2:
 			_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
 			break;
 		case Instruction::LOG3:
 			_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
 			break;
 		case Instruction::LOG4:
 			_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
+			m_stack.pop_back();
 			break;
 		case Instruction::CREATE:
 		{
diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp
index 5d94a22ca..9062fd8ed 100644
--- a/libevmcore/Instruction.cpp
+++ b/libevmcore/Instruction.cpp
@@ -282,11 +282,11 @@ static const std::map c_instructionInfo =
 	{ Instruction::SWAP14,		{ "SWAP14",			0, 15, 15, false } },
 	{ Instruction::SWAP15,		{ "SWAP15",			0, 16, 16, false } },
 	{ Instruction::SWAP16,		{ "SWAP16",			0, 17, 17, false } },
-	{ Instruction::LOG0,		{ "LOG0",			0, 1, 0, true } },
-	{ Instruction::LOG1,		{ "LOG1",			0, 2, 0, true } },
-	{ Instruction::LOG2,		{ "LOG2",			0, 3, 0, true } },
-	{ Instruction::LOG3,		{ "LOG3",			0, 4, 0, true } },
-	{ Instruction::LOG4,		{ "LOG4",			0, 5, 0, true } },
+	{ Instruction::LOG0,		{ "LOG0",			0, 2, 0, true } },
+	{ Instruction::LOG1,		{ "LOG1",			0, 3, 0, true } },
+	{ Instruction::LOG2,		{ "LOG2",			0, 4, 0, true } },
+	{ Instruction::LOG3,		{ "LOG3",			0, 5, 0, true } },
+	{ Instruction::LOG4,		{ "LOG4",			0, 6, 0, true } },
 	{ Instruction::CREATE,		{ "CREATE",			0, 3, 1, true } },
 	{ Instruction::CALL,		{ "CALL",			0, 7, 1, true } },
 	{ Instruction::CALLCODE,	{ "CALLCODE",		0, 7, 1, true } },
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index bf8d96506..996e219db 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -385,8 +385,8 @@ void Host::populateAddresses()
 shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId)
 {
 	RecursiveGuard l(x_peers);
-	if (_a.port() < 30300 || _a.port() > 30303)
-		cwarn << "Wierd port being recorded!";
+	if (_a.port() < 30300 || _a.port() > 30305)
+		cwarn << "Weird port being recorded: " << _a.port();
 
 	if (_a.port() >= /*49152*/32768)
 	{
@@ -778,7 +778,7 @@ bytes Host::saveNodes() const
 		{
 			Node const& n = *(i.second);
 			// TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 &&
-			if (!n.dead && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address()))
+			if (!n.dead && chrono::system_clock::now() - n.lastConnected < chrono::seconds(3600 * 48) && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address()))
 			{
 				nodes.appendList(10);
 				if (n.address.address().is_v4())
@@ -786,8 +786,8 @@ bytes Host::saveNodes() const
 				else
 					nodes << n.address.address().to_v6().to_bytes();
 				nodes << n.address.port() << n.id << (int)n.idOrigin
-					<< std::chrono::duration_cast(n.lastConnected.time_since_epoch()).count()
-					<< std::chrono::duration_cast(n.lastAttempted.time_since_epoch()).count()
+					<< chrono::duration_cast(n.lastConnected.time_since_epoch()).count()
+					<< chrono::duration_cast(n.lastAttempted.time_since_epoch()).count()
 					<< n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating;
 				count++;
 			}
diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h
index 4f276b7e1..0824b0139 100644
--- a/libqethereum/QEthereum.h
+++ b/libqethereum/QEthereum.h
@@ -83,6 +83,7 @@ private:
 { \
 	_frame->disconnect(); \
 	_frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \
+	_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/main.js")); \
 	_frame->evaluateJavaScript(contentsOfQResource(":/js/qt.js")); \
diff --git a/libserpent/compiler.cpp b/libserpent/compiler.cpp
index 623ab3950..30628fbc9 100644
--- a/libserpent/compiler.cpp
+++ b/libserpent/compiler.cpp
@@ -131,8 +131,7 @@ programData opcodeify(Node node,
         }
         // Declare variable
         else {
-            Node nodelist[] = { };
-            return pd(aux, multiToken(nodelist, 0, m), 0);
+			return pd(aux, multiToken(nullptr, 0, m), 0);
         }
     }
     // Define functions (TODO: eventually move to rewriter.cpp, keep
diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp
index 565560adc..70af8f98e 100644
--- a/libsolidity/AST.cpp
+++ b/libsolidity/AST.cpp
@@ -263,6 +263,21 @@ TypeError ASTNode::createTypeError(string const& _description)
 	return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description);
 }
 
+vector ContractDefinition::getInterfaceFunctions() const
+{
+	vector exportedFunctions;
+	for (ASTPointer const& f: m_definedFunctions)
+		if (f->isPublic() && f->getName() != getName())
+			exportedFunctions.push_back(f.get());
+	auto compareNames = [](FunctionDefinition const* _a, FunctionDefinition const* _b)
+	{
+		return _a->getName().compare(_b->getName()) < 0;
+	};
+
+	sort(exportedFunctions.begin(), exportedFunctions.end(), compareNames);
+	return exportedFunctions;
+}
+
 void Block::checkTypeRequirements()
 {
 	for (shared_ptr const& statement: m_statements)
diff --git a/libsolidity/AST.h b/libsolidity/AST.h
index 19328e5f7..7b266f132 100644
--- a/libsolidity/AST.h
+++ b/libsolidity/AST.h
@@ -120,6 +120,8 @@ public:
 	std::vector> const& getStateVariables() const { return m_stateVariables; }
 	std::vector> const& getDefinedFunctions() const { return m_definedFunctions; }
 
+	/// Returns the functions that make up the calling interface in the intended order.
+	std::vector getInterfaceFunctions() const;
 private:
 	std::vector> m_definedStructs;
 	std::vector> m_stateVariables;
diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp
index eb9d92f08..987ad11cc 100644
--- a/libsolidity/ASTPrinter.cpp
+++ b/libsolidity/ASTPrinter.cpp
@@ -30,8 +30,8 @@ namespace dev
 namespace solidity
 {
 
-ASTPrinter::ASTPrinter(ASTPointer const& _ast, string const& _source):
-	m_indentation(0), m_source(_source), m_ast(_ast)
+ASTPrinter::ASTPrinter(ASTNode& _ast, string const& _source):
+	m_indentation(0), m_source(_source), m_ast(&_ast)
 {
 }
 
@@ -430,8 +430,8 @@ void ASTPrinter::printSourcePart(ASTNode const& _node)
 	if (!m_source.empty())
 	{
 		Location const& location(_node.getLocation());
-		*m_ostream << getIndentation() << "   Source: |"
-				   << m_source.substr(location.start, location.end - location.start) << "|" << endl;
+		*m_ostream << getIndentation() << "   Source: "
+				   << escaped(m_source.substr(location.start, location.end - location.start), false) << endl;
 	}
 }
 
diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h
index e87b2ba3b..e0757fbc4 100644
--- a/libsolidity/ASTPrinter.h
+++ b/libsolidity/ASTPrinter.h
@@ -38,7 +38,7 @@ class ASTPrinter: public ASTVisitor
 public:
 	/// Create a printer for the given abstract syntax tree. If the source is specified,
 	/// the corresponding parts of the source are printed with each node.
-	ASTPrinter(ASTPointer const& _ast, std::string const& _source = std::string());
+	ASTPrinter(ASTNode& _ast, std::string const& _source = std::string());
 	/// Output the string representation of the AST to _stream.
 	void print(std::ostream& _stream);
 
@@ -114,7 +114,7 @@ private:
 
 	int m_indentation;
 	std::string m_source;
-	ASTPointer m_ast;
+	ASTNode* m_ast;
 	std::ostream* m_ostream;
 };
 
diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp
index ed2b1f45f..da28ba8a3 100644
--- a/libsolidity/Compiler.cpp
+++ b/libsolidity/Compiler.cpp
@@ -81,36 +81,34 @@ void Compiler::appendFunctionSelector(vector> con
 	if (publicFunctions.size() > 255)
 		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract."));
 
-	//@todo check for calldatasize?
-	// retrieve the first byte of the call data
-	m_context << u256(0) << eth::Instruction::CALLDATALOAD << u256(0) << eth::Instruction::BYTE;
-	// check that it is not too large
-	m_context << eth::Instruction::DUP1 << u256(publicFunctions.size() - 1) << eth::Instruction::LT;
-	eth::AssemblyItem returnTag = m_context.appendConditionalJump();
-
-	// otherwise, jump inside jump table (each entry of the table has size 4)
-	m_context << u256(4) << eth::Instruction::MUL;
-	eth::AssemblyItem jumpTableStart = m_context.pushNewTag();
-	m_context << eth::Instruction::ADD << eth::Instruction::JUMP;
-
-	// jump table, tell the optimizer not to remove the JUMPDESTs
-	m_context << eth::AssemblyItem(eth::NoOptimizeBegin) << jumpTableStart;
+	// retrieve the first byte of the call data, which determines the called function
+	// @todo This code had a jump table in a previous version which was more efficient but also
+	// error prone (due to the optimizer and variable length tag addresses)
+	m_context << u256(1) << u256(0) // some constants
+			  << eth::dupInstruction(1) << eth::Instruction::CALLDATALOAD
+			  << eth::dupInstruction(2) << eth::Instruction::BYTE
+			  << eth::dupInstruction(2);
+
+	// stack here: 1 0  0, stack top will be counted up until it matches funid
 	for (pair> const& f: publicFunctions)
-		m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST;
-	m_context << eth::AssemblyItem(eth::NoOptimizeEnd);
-
-	m_context << returnTag << eth::Instruction::STOP;
+	{
+		eth::AssemblyItem const& callDataUnpackerEntry = f.second.second;
+		m_context << eth::dupInstruction(2) << eth::dupInstruction(2) << eth::Instruction::EQ;
+		m_context.appendConditionalJumpTo(callDataUnpackerEntry);
+		m_context << eth::dupInstruction(4) << eth::Instruction::ADD;
+		//@todo avoid the last ADD (or remove it in the optimizer)
+	}
+	m_context << eth::Instruction::STOP; // function not found
 
 	for (pair> const& f: publicFunctions)
 	{
 		FunctionDefinition const& function = *f.second.first;
-		m_context << f.second.second;
-
+		eth::AssemblyItem const& callDataUnpackerEntry = f.second.second;
+		m_context << callDataUnpackerEntry;
 		eth::AssemblyItem returnTag = m_context.pushNewTag();
 		appendCalldataUnpacker(function);
 		m_context.appendJumpTo(m_context.getFunctionEntryLabel(function));
 		m_context << returnTag;
-
 		appendReturnValuePacker(function);
 	}
 }
diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp
index c991171a5..d87c27916 100644
--- a/libsolidity/CompilerStack.cpp
+++ b/libsolidity/CompilerStack.cpp
@@ -34,17 +34,101 @@ namespace dev
 namespace solidity
 {
 
-bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr _scanner,
-							 bool _optimize)
+void CompilerStack::setSource(string const& _sourceCode)
 {
-	if (!_scanner)
-		_scanner = make_shared();
-	_scanner->reset(CharStream(_sourceCode));
+	reset();
+	m_scanner = make_shared(CharStream(_sourceCode));
+}
+
+void CompilerStack::parse()
+{
+	if (!m_scanner)
+		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
+	m_contractASTNode = Parser().parse(m_scanner);
+	NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode);
+	m_parseSuccessful = true;
+}
+
+void CompilerStack::parse(string const& _sourceCode)
+{
+	setSource(_sourceCode);
+	parse();
+}
+
+bytes const& CompilerStack::compile(bool _optimize)
+{
+	if (!m_parseSuccessful)
+		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+	m_bytecode.clear();
+	m_compiler = make_shared();
+	m_compiler->compileContract(*m_contractASTNode);
+	return m_bytecode = m_compiler->getAssembledBytecode(_optimize);
+}
 
-	ASTPointer contract = Parser().parse(_scanner);
-	NameAndTypeResolver().resolveNamesAndTypes(*contract);
-	return Compiler::compile(*contract, _optimize);
+bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize)
+{
+	parse(_sourceCode);
+	return compile(_optimize);
 }
 
+void CompilerStack::streamAssembly(ostream& _outStream)
+{
+	if (!m_compiler || m_bytecode.empty())
+		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
+	m_compiler->streamAssembly(_outStream);
+}
+
+string const& CompilerStack::getInterface()
+{
+	if (!m_parseSuccessful)
+		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+	if (m_interface.empty())
+	{
+		stringstream interface;
+		interface << '[';
+		vector exportedFunctions = m_contractASTNode->getInterfaceFunctions();
+		unsigned functionsCount = exportedFunctions.size();
+		for (FunctionDefinition const* f: exportedFunctions)
+		{
+			auto streamVariables = [&](vector> const& _vars)
+			{
+				unsigned varCount = _vars.size();
+				for (ASTPointer const& var: _vars)
+				{
+					interface << "{"
+							  << "\"name\":" << escaped(var->getName(), false) << ","
+							  << "\"type\":" << escaped(var->getType()->toString(), false)
+							  << "}";
+					if (--varCount > 0)
+						interface << ",";
+				}
+			};
+
+			interface << '{'
+					  << "\"name\":" << escaped(f->getName(), false) << ","
+					  << "\"inputs\":[";
+			streamVariables(f->getParameters());
+			interface << "],"
+					  << "\"outputs\":[";
+			streamVariables(f->getReturnParameters());
+			interface << "]"
+					  << "}";
+			if (--functionsCount > 0)
+				interface << ",";
+		}
+		interface << ']';
+		m_interface = interface.str();
+	}
+	return m_interface;
+}
+
+bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize)
+{
+	CompilerStack stack;
+	return stack.compile(_sourceCode, _optimize);
+}
+
+
+
 }
 }
diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h
index b003745d2..2fb505897 100644
--- a/libsolidity/CompilerStack.h
+++ b/libsolidity/CompilerStack.h
@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include 
 #include 
 #include 
 #include 
@@ -30,13 +31,51 @@ namespace dev {
 namespace solidity {
 
 class Scanner; // forward
+class ContractDefinition; // forward
+class Compiler; // forward
 
+/**
+ * Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
+ * It holds state and can be used to either step through the compilation stages (and abort e.g.
+ * before compilation to bytecode) or run the whole compilation in one call.
+ */
 class CompilerStack
 {
 public:
+	CompilerStack() {}
+	void reset() {  *this = CompilerStack(); }
+	void setSource(std::string const& _sourceCode);
+	void parse();
+	void parse(std::string const& _sourceCode);
+	/// Compiles the contract that was previously parsed.
+	bytes const& compile(bool _optimize = false);
+	/// Parses and compiles the given source code.
+	bytes const& compile(std::string const& _sourceCode, bool _optimize = false);
+
+	bytes const& getBytecode() const { return m_bytecode; }
+	/// Streams a verbose version of the assembly to @a _outStream.
+	/// Prerequisite: Successful compilation.
+	void streamAssembly(std::ostream& _outStream);
+
+	/// Returns a string representing the contract interface in JSON.
+	/// Prerequisite: Successful call to parse or compile.
+	std::string const& getInterface();
+
+	/// Returns the previously used scanner, useful for counting lines during error reporting.
+	Scanner const& getScanner() const { return *m_scanner; }
+	ContractDefinition& getAST() const { return *m_contractASTNode; }
+
 	/// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for
 	/// scanning the source code - this is useful for printing exception information.
-	static bytes compile(std::string const& _sourceCode, std::shared_ptr _scanner = std::shared_ptr(), bool _optimize = false);
+	static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false);
+
+private:
+	std::shared_ptr m_scanner;
+	std::shared_ptr m_contractASTNode;
+	bool m_parseSuccessful;
+	std::string m_interface;
+	std::shared_ptr m_compiler;
+	bytes m_bytecode;
 };
 
 }
diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp
index 3849fb4a8..5b362cde5 100644
--- a/libweb3jsonrpc/WebThreeStubServer.cpp
+++ b/libweb3jsonrpc/WebThreeStubServer.cpp
@@ -240,7 +240,7 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m,
 
 static pair toWatch(Json::Value const& _json)
 {
-	shh::BuildTopicMask bt(shh::BuildTopicMask::Empty);
+	shh::BuildTopicMask bt;
 	Public to;
 
 	if (!_json["to"].empty())
@@ -252,12 +252,8 @@ static pair toWatch(Json::Value const& _json)
 			bt.shift(jsToBytes(_json["topic"].asString()));
 		else if (_json["topic"].isArray())
 			for (auto i: _json["topic"])
-			{
 				if (i.isString())
 					bt.shift(jsToBytes(i.asString()));
-				else
-					bt.shift();
-			}
 	}
 	return make_pair(bt.toTopicMask(), to);
 }
@@ -271,14 +267,13 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message
 	res["ttl"] = (int)_e.ttl();
 	res["workProved"] = (int)_e.workProved();
 	for (auto const& t: _e.topics())
-		res["topics"].append(toJS((u256)t));
+		res["topics"].append(toJS(t));
 	res["payload"] = toJS(_m.payload());
 	res["from"] = toJS(_m.from());
 	res["to"] = toJS(_m.to());
 	return res;
 }
 
-
 WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3, std::vector const& _accounts):
 	AbstractWebThreeStubServer(_conn),
 	m_web3(_web3)
@@ -375,10 +370,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json)
 			ret.data = jsToBytes(_json["code"].asString());
 		else if (_json["data"].isArray())
 			for (auto i: _json["data"])
-				dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
+				dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32));
 		else if (_json["code"].isArray())
 			for (auto i: _json["code"])
-				dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32)));
+				dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32));
 		else if (_json["dataclose"].isArray())
 			for (auto i: _json["dataclose"])
 				dev::operator +=(ret.data, jsToBytes(i.asString()));
@@ -512,7 +507,7 @@ std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string
 
 std::string WebThreeStubServer::shh_newIdentity()
 {
-	cnote << this << m_ids;
+//	cnote << this << m_ids;
 	KeyPair kp = KeyPair::create();
 	m_ids[kp.pub()] = kp.secret();
 	return toJS(kp.pub());
@@ -540,7 +535,7 @@ int WebThreeStubServer::eth_peerCount()
 
 bool WebThreeStubServer::shh_post(Json::Value const& _json)
 {
-	cnote << this << m_ids;
+//	cnote << this << m_ids;
 	shh::Message m = toMessage(_json);
 	Secret from;
 
diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp
index 8f58ae994..0d54af089 100644
--- a/libwhisper/Common.cpp
+++ b/libwhisper/Common.cpp
@@ -33,7 +33,7 @@ Topic BuildTopic::toTopic() const
 	Topic ret;
 	ret.reserve(m_parts.size());
 	for (auto const& h: m_parts)
-		ret.push_back((TopicPart)u256(h));
+		ret.push_back(TopicPart(h));
 	return ret;
 }
 
@@ -69,7 +69,7 @@ TopicMask BuildTopicMask::toTopicMask() const
 	TopicMask ret;
 	ret.reserve(m_parts.size());
 	for (auto const& h: m_parts)
-		ret.push_back(make_pair((TopicPart)u256(h), h ? ~(uint32_t)0 : 0));
+		ret.push_back(make_pair(TopicPart(h), ~TopicPart()));
 	return ret;
 }
 
diff --git a/libwhisper/Common.h b/libwhisper/Common.h
index f47778afe..5ce7d3b1c 100644
--- a/libwhisper/Common.h
+++ b/libwhisper/Common.h
@@ -59,7 +59,7 @@ enum WhisperPacket
 	PacketCount
 };
 
-using TopicPart = uint32_t;
+using TopicPart = FixedHash<4>;
 
 using Topic = std::vector;
 
@@ -92,7 +92,15 @@ public:
 	TopicFilter() {}
 	TopicFilter(TopicMask const& _m): m_topicMasks(1, _m) {}
 	TopicFilter(TopicMasks const& _m): m_topicMasks(_m) {}
-	TopicFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
+	TopicFilter(RLP const& _r)//: m_topicMasks(_r.toVector>())
+	{
+		for (RLP i: _r)
+		{
+			m_topicMasks.push_back(TopicMask());
+			for (RLP j: i)
+				m_topicMasks.back().push_back(j.toPair, FixedHash<4>>());
+		}
+	}
 
 	void streamRLP(RLPStream& _s) const { _s << m_topicMasks; }
 	h256 sha3() const;
@@ -106,17 +114,12 @@ private:
 class BuildTopicMask: BuildTopic
 {
 public:
-	enum EmptyType { Empty };
-
-	BuildTopicMask() { shift(); }
-	BuildTopicMask(EmptyType) {}
+	BuildTopicMask() {}
 	template  BuildTopicMask(T const& _t) { shift(_t); }
 
 	template  BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; }
 	BuildTopicMask& shiftRaw(h256 const& _h) { BuildTopic::shiftRaw(_h); return *this; }
-	BuildTopic& shift() { m_parts.push_back(h256()); return *this; }
 
-	BuildTopicMask& operator()() { shift(); return *this; }
 	template  BuildTopicMask& operator()(T const& _t) { shift(_t); return *this; }
 
 	operator TopicMask() const { return toTopicMask(); }
diff --git a/libwhisper/Message.h b/libwhisper/Message.h
index 3b0d14aae..954aed4a0 100644
--- a/libwhisper/Message.h
+++ b/libwhisper/Message.h
@@ -55,7 +55,7 @@ public:
 	{
 		m_expiry = _m[0].toInt();
 		m_ttl = _m[1].toInt();
-		m_topic = (Topic)_m[2];
+		m_topic = _m[2].toVector>();
 		m_data = _m[3].toBytes();
 		m_nonce = _m[4].toInt();
 	}
diff --git a/solc/main.cpp b/solc/main.cpp
index 04fdc0ee1..a7216e594 100644
--- a/solc/main.cpp
+++ b/solc/main.cpp
@@ -26,12 +26,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 using namespace std;
@@ -85,48 +86,34 @@ int main(int argc, char** argv)
 	else
 		sourceCode = asString(dev::contents(infile));
 
-	ASTPointer ast;
-	shared_ptr scanner = make_shared(CharStream(sourceCode));
-	Parser parser;
-	bytes instructions;
-	Compiler compiler;
+	CompilerStack compiler;
 	try
 	{
-		ast = parser.parse(scanner);
-
-		NameAndTypeResolver resolver;
-		resolver.resolveNamesAndTypes(*ast.get());
-
-		cout << "Syntax tree for the contract:" << endl;
-		dev::solidity::ASTPrinter printer(ast, sourceCode);
-		printer.print(cout);
-
-		compiler.compileContract(*ast);
-		instructions = compiler.getAssembledBytecode(optimize);
+		compiler.compile(sourceCode, optimize);
 	}
 	catch (ParserError const& exception)
 	{
-		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", *scanner);
+		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner());
 		return -1;
 	}
 	catch (DeclarationError const& exception)
 	{
-		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", *scanner);
+		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner());
 		return -1;
 	}
 	catch (TypeError const& exception)
 	{
-		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", *scanner);
+		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner());
 		return -1;
 	}
 	catch (CompilerError const& exception)
 	{
-		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", *scanner);
+		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner());
 		return -1;
 	}
 	catch (InternalCompilerError const& exception)
 	{
-		cerr << "Internal compiler error: " << boost::diagnostic_information(exception) << endl;
+		SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner());
 		return -1;
 	}
 	catch (Exception const& exception)
@@ -140,11 +127,15 @@ int main(int argc, char** argv)
 		return -1;
 	}
 
+	cout << "Syntax tree for the contract:" << endl;
+	ASTPrinter printer(compiler.getAST(), sourceCode);
+	printer.print(cout);
 	cout << "EVM assembly:" << endl;
 	compiler.streamAssembly(cout);
 	cout << "Opcodes:" << endl;
-	cout << eth::disassemble(instructions) << endl;
-	cout << "Binary: " << toHex(instructions) << endl;
+	cout << eth::disassemble(compiler.getBytecode()) << endl;
+	cout << "Binary: " << toHex(compiler.getBytecode()) << endl;
+	cout << "Interface specification: " << compiler.getInterface() << endl;
 
 	return 0;
 }
diff --git a/stdserv.js b/stdserv.js
index 55ae90d86..fe681414e 100644
--- a/stdserv.js
+++ b/stdserv.js
@@ -1,67 +1,41 @@
-eth = web3.eth;
-
-env.note('Creating Config...')
-var configCode = eth.lll("
-{
-  [[69]] (caller)
-  (returnlll {
-    (when (&& (= (calldatasize) 64) (= (caller) @@69))
-      (for {} (< @i (calldatasize)) [i](+ @i 64)
-        [[ (calldataload @i) ]] (calldataload (+ @i 32))
-      )
-    )
-    (return @@ $0)
-  })
-}
-")
-env.note('Config code: ' + configCode)
-var config;
-eth.transact({ 'code': configCode }, function(a) { config = a; });
-
-env.note('Config at address ' + config)
-
-var nameRegCode = eth.lll("
-{
-  [[(address)]] 'NameReg
-  [['NameReg]] (address)
-  [[config]] 'Config
-  [['Config]] config
-  [[69]] (caller)
-  (returnlll {
-    (when (= $0 'register) {
-      (when @@ $32 (stop))
-      (when @@(caller) [[@@(caller)]] 0)
-      [[$32]] (caller)
-      [[(caller)]] $32
-      (stop)
-    })
-    (when (&& (= $0 'unregister) @@(caller)) {
-      [[@@(caller)]] 0
-      [[(caller)]] 0
-      (stop)
-    })
-    (when (&& (= $0 'kill) (= (caller) @@69)) (suicide (caller)))
-    (return @@ $0)
-  })
-}
-");
-env.note('NameReg code: ' + nameRegCode)
-
-var nameReg;
-
-env.note('Create NameReg...')
-eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; });
-
-env.note('Register NameReg...')
-eth.transact({ 'to': config, 'data': ['0', nameReg] });
-
+var compile = function(name) { return web3.eth.lll(env.contents("../../dapp-bin/" + name + "/" + name + ".lll")); };
+var create = function(code) { return web3.eth.transact({ 'code': code }); };
+var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); };
+var initService = function(name, index, dep) { return dep.then(function(){ var ret = compile(name).then(create); register(ret, index); return ret; }); };
+
+var config = compile("config").then(create);
+var register = function(address, index) { return web3.eth.transact({ 'to': config, 'gas': '10000', 'data': [index + '', address] }); };
+var nameReg = initService("namereg", 0, config);
+var regName = function(account, name) { return web3.eth.transact({ 'from': account, 'to': nameReg, 'gas': '10000', 'data': [ web3.fromAscii('register'), web3.fromAscii(name) ] }); };
+var coins = initService("coins", 1, nameReg);
+var coin = initService("coin", 2, coins);
+var approve = function(account, approvedAddress) { web3.eth.transact({ 'from': account, 'to': coin, 'gas': '10000', 'data': [ web3.fromAscii('approve'), approvedAddress ] }); };
+var exchange = initService("exchange", 3, coin);
+var offer = function(account, haveCoin, haveVal, wantCoin, wantVal) { web3.eth.transact({ 'from': account, 'to': exchange, 'gas': '10000', 'data': [web3.fromAscii('new'), haveCoin, haveVal, wantCoin, wantVal] }); };
+
+config.then(function() {
+	web3.eth.accounts.then(function(accounts)
+	{
+		var funded = send(accounts[0], '100000000000000000000', accounts[1]);
+		funded.then(function(){ env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); regName(accounts[1], 'Gav Would'); env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); approve(accounts[1], exchange); });
+		regName(accounts[0], 'Gav');
+		approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); });
+
+		// TODO: once we have a new implementation of DNSReg.
+		//	env.note('Register gav.eth...')
+		//	eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
+	});
+});
+
+// TODO
+/*
 var nameRegJeff;
 
 env.note('Create NameRegJeff...')
 eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; });
 
 env.note('Register NameRegJeff...')
-eth.transact({ 'to': config, 'data': ['4', nameReg] });
+eth.transact({ 'to': config, 'data': ['4', nameRegJeff] });
 
 var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00';
 
@@ -73,240 +47,6 @@ env.note('DnsReg at address ' + dnsReg)
 
 env.note('Register DnsReg...')
 eth.transact({ 'to': config, 'data': ['4', dnsReg] });
-
-var coinRegCode = eth.lll("
-{
-(regname 'CoinReg)
-(returnlll {
-	(def 'name $0)
-	(def 'denom $32)
-	(def 'address (caller))
-	(when (|| (& 0xffffffffffffffffffffffffff name) @@name) (stop))
-	(set 'n (+ @@0 1))
-	[[0]] @n
-	[[@n]] name
-	[[name]] address
-	[[(sha3 name)]] denom
-})
-}
-");
-
-var coinReg;
-env.note('Create CoinReg...')
-eth.transact({ 'code': coinRegCode }, function(a) { coinReg = a; });
-
-env.note('Register CoinReg...')
-eth.transact({ 'to': config, 'data': ['1', coinReg] });
-
-var gavCoinCode = eth.lll("
-{
-[[ (caller) ]] 0x1000000
-[[ 0x69 ]] (caller)
-[[ 0x42 ]] (number)
-
-(regname 'GavCoin)
-(regcoin 'GAV 1000)
-
-(returnlll {
-	(when (&& (= $0 'kill) (= (caller) @@0x69)) (suicide (caller)))
-	(when (= $0 'balance) (return @@$32))
-	(when (= $0 'approved) (return @@ (sha3pair (if (= (calldatasize) 64) (caller) $64) $32)) )
-	
-	(when (= $0 'approve) {
-		[[(sha3pair (caller) $32)]] $32
-		(stop)
-	})
-
-	(when (= $0 'send) {
-		(set 'fromVar (if (= (calldatasize) 96)
-			(caller)
-			{
-				(when (! @@ (sha3pair (origin) (caller))) (return 0))
-				(origin)
-			}
-		))
-		(def 'to $32)
-		(def 'value $64)
-		(def 'from (get 'fromVar))
-		(set 'fromBal @@from)
-		(when (< @fromBal value) (return 0))
-		[[ from ]]: (- @fromBal value)
-		[[ to ]]: (+ @@to value)
-		(return 1)
-	})
-
-	(set 'n @@0x42)
-	(when (&& (|| (= $0 'mine) (! (calldatasize))) (> (number) @n)) {
-		(set 'b (- (number) @n))
-		[[(coinbase)]] (+ @@(coinbase) (* 1000 @b))
-		[[(caller)]] (+ @@(caller) (* 1000 @b))
-		[[0x42]] (number)
-		(return @b)
-	})
-
-	(return @@ $0)
-})
-}
-");
-
-var gavCoin;
-env.note('Create GavCoin...')
-eth.transact({ 'code': gavCoinCode }, function(a) { gavCoin = a; });
-
-env.note('Register GavCoin...')
-eth.transact({ 'to': config, 'data': ['2', gavCoin] });
-
-
-var exchangeCode = eth.lll("
-{
-(regname 'Exchange)
-
-(def 'min (a b) (if (< a b) a b))
-
-(def 'head (_list) @@ _list)
-(def 'next (_item) @@ _item)
-(def 'inc (itemref) [itemref]: (next @itemref))
-(def 'rateof (_item) @@ (+ _item 1))
-(def 'idof (_item) @@ (+ _item 2))
-(def 'wantof (_item) @@ (+ _item 3))
-(def 'newitem (rate who want list) {
-	(set 'pos (sha3trip rate who list))
-	[[ (+ @pos 1) ]] rate
-	[[ (+ @pos 2) ]] who
-	[[ (+ @pos 3) ]] want
-	@pos
-})
-(def 'stitchitem (parent pos) {
-	[[ pos ]] @@ parent
-	[[ parent ]] pos
-})
-(def 'addwant (_item amount) [[ (+ _item 3) ]] (+ @@ (+ _item 3) amount))
-(def 'deductwant (_item amount) [[ (+ _item 3) ]] (- @@ (+ _item 3) amount))
-
-(def 'xfer (contract to amount)
-	(if contract {
-		[0] 'send
-		[32] to
-		[64] amount
-		(msg allgas contract 0 0 96)
-	}
-		(send to amount)
-	)
-)
-
-(def 'fpdiv (a b) (/ (+ (/ b 2) (* a (exp 2 128))) b))
-(def 'fpmul (a b) (/ (* a b) (exp 2 128)) )
-
-(returnlll {
-	(when (= $0 'new) {
-		(set 'offer $32)
-		(set 'xoffer (if @offer $64 (callvalue)))
-		(set 'want $96)
-		(set 'xwant $128)
-		(set 'rate (fpdiv @xoffer @xwant))
-		(set 'irate (fpdiv @xwant @xoffer))
-
-		(unless (&& @rate @irate @xoffer @xwant) (stop))
-
-		(when @offer {
-			(set 'arg1 'send)
-			(set 'arg2 (address))
-			(set 'arg3 @xoffer)
-			(set 'arg4 (caller))
-			(unless (msg allgas @offer 0 arg1 128) (stop))
-		})
-		(set 'list (sha3pair @offer @want))
-		(set 'ilist (sha3pair @want @offer))
-
-		(set 'last @ilist)
-		(set 'item @@ @last)
-		
-		(for {} (&& @item (>= (rateof @item) @irate)) {} {
-			(set 'offerA (min @xoffer (wantof @item)))
-			(set 'wantA (fpmul @offerA (rateof @item)))
-
-			(set 'xoffer (- @xoffer @offerA))
-			(set 'xwant (- @xwant @wantA))
-
-			(deductwant @item @offerA)
-
-			(xfer @offer (idof @item) @offerA)
-			(xfer @want (caller) @wantA)
-
-			(unless @xoffer (stop))
-
-			(set 'item @@ @item)
-			[[ @last ]] @item
-		})
-
-		(set 'last @list)
-		(set 'item @@ @last)
-		
-		(set 'newpos (newitem @rate (caller) @xwant @list))
-
-		(for {} (&& @item (!= @item @newpos) (>= (rateof @item) @rate)) { (set 'last @item) (inc item) } {})
-		(if (= @item @newpos)
-			(addwant @item @wantx)
-			(stitchitem @last @newpos)
-		)
-		(stop)
-	})
-	(when (= $0 'delete) {
-		(set 'offer $32)
-		(set 'want $64)
-		(set 'rate $96)
-		(set 'list (sha3pair @offer @want))
-		(set 'last @list)
-		(set 'item @@ @last)
-		(for {} (&& @item (!= (idof @item) (caller)) (!= (rateof @item) @rate)) { (set 'last @item) (inc item) } {})
-		(when @item {
-			(set 'xoffer (fpmul (wantof @item) (rateof @item)))
-			[[ @last ]] @@ @item
-			(xfer @offer (caller) @xoffer)
-		})
-		(stop)
-	})
-	(when (= $0 'price) {
-		(set 'offer $32)
-		(set 'want $96)
-		(set 'item (head (sha3pair @offer @want)))
-		(return (if @item (rateof @list) 0))
-	})
-})
-}
-");
-
-var exchange;
-env.note('Create Exchange...')
-eth.transact({ 'code': exchangeCode }, function(a) { exchange = a; });
-
-env.note('Register Exchange...')
-eth.transact({ 'to': config, 'data': ['3', exchange] });
-
-
-
-
-env.note('Register my name...')
-eth.transact({ 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii('Gav') ] });
-
-env.note('Dole out ETH to other address...')
-eth.transact({ 'value': '100000000000000000000', 'to': eth.accounts[1] });
-
-env.note('Register my other name...')
-eth.transact({ 'from': eth.keys[1], 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii("Gav Would") ] });
-
-env.note('Approve Exchange...')
-eth.transact({ 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] });
-
-env.note('Approve Exchange on other address...')
-eth.transact({ 'from': eth.keys[1], 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] });
-
-env.note('Make offer 5000GAV/5ETH...')
-eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] });
-
-env.note('Register gav.eth...')
-eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
-
-env.note('All done.')
+*/
 
 // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js')
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
index c1a141abb..1b13f9e82 100644
--- a/test/TestHelper.cpp
+++ b/test/TestHelper.cpp
@@ -27,8 +27,6 @@
 #include 
 #include 
 
-//#define FILL_TESTS
-
 using namespace std;
 using namespace dev::eth;
 
@@ -351,28 +349,33 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
 	string testPath = getTestPath();
 	testPath += _testPathAppendix;
 
-#ifdef FILL_TESTS
-	try
-	{
-		cnote << "Populating tests...";
-		json_spirit::mValue v;
-		boost::filesystem::path p(__FILE__);
-		boost::filesystem::path dir = p.parent_path();
-		string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json"));
-		BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty.");
-		json_spirit::read_string(s, v);
-		doTests(v, true);
-		writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
-	}
-	catch (Exception const& _e)
-	{
-		BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
-	}
-	catch (std::exception const& _e)
+	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
 	{
-		BOOST_ERROR("Failed test with Exception: " << _e.what());
+		string arg = boost::unit_test::framework::master_test_suite().argv[i];
+		if (arg == "--filltests")
+		{
+			try
+			{
+				cnote << "Populating tests...";
+				json_spirit::mValue v;
+				boost::filesystem::path p(__FILE__);
+				boost::filesystem::path dir = p.parent_path();
+				string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json"));
+				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty.");
+				json_spirit::read_string(s, v);
+				doTests(v, true);
+				writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
+			}
+			catch (Exception const& _e)
+			{
+				BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
+			}
+			catch (std::exception const& _e)
+			{
+				BOOST_ERROR("Failed test with Exception: " << _e.what());
+			}
+		}
 	}
-#endif
 
 	try
 	{
diff --git a/test/TestHelperCrypto.h b/test/TestHelperCrypto.h
deleted file mode 100644
index 01e97c21f..000000000
--- a/test/TestHelperCrypto.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- 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 .
- */
-/** @file TestHelperCrypto.h
- * @author Alex Leverington 
- * @date 2014
- */
-
-#pragma once
-
-#include 
-
-using namespace std;
-using namespace CryptoPP;
-
-void SavePrivateKey(const PrivateKey& key, const string& file = "ecies.private.key")
-{
-	FileSink sink(file.c_str());
-	key.Save(sink);
-}
-
-void SavePublicKey(const PublicKey& key, const string& file = "ecies.public.key")
-{
-	FileSink sink(file.c_str());
-	key.Save(sink);
-}
-
-void LoadPrivateKey(PrivateKey& key, const string& file = "ecies.private.key")
-{
-	FileSource source(file.c_str(), true);
-	key.Load(source);
-}
-
-void LoadPublicKey(PublicKey& key, const string& file = "ecies.public.key")
-{
-	FileSource source(file.c_str(), true);
-	key.Load(source);
-}
diff --git a/test/crypto.cpp b/test/crypto.cpp
index 06e55658a..d8bd25035 100644
--- a/test/crypto.cpp
+++ b/test/crypto.cpp
@@ -27,9 +27,9 @@
 #include 
 #include 
 #include 
-#include 
-#include 
-#include "TestHelperCrypto.h"
+#include 
+#include 
+#include 
 
 using namespace std;
 using namespace dev;
@@ -38,9 +38,24 @@ using namespace CryptoPP;
 
 BOOST_AUTO_TEST_SUITE(devcrypto)
 
+static Secp256k1 s_secp256k1;
+static CryptoPP::AutoSeededRandomPool s_rng;
+static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1());
+static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID);
+static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve());
+
+BOOST_AUTO_TEST_CASE(verify_secert)
+{
+	h256 empty;
+	KeyPair kNot(empty);
+	BOOST_REQUIRE(!kNot.address());
+	KeyPair k(sha3(empty));
+	BOOST_REQUIRE(k.address());
+}
+
 BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
 {
-	string message("Now is the time for all good persons to come to the aide of humanity.");
+	string message("Now is the time for all good persons to come to the aid of humanity.");
 	bytes m = asBytes(message);
 	bytesConstRef bcr(&m);
 
@@ -56,103 +71,50 @@ BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
 	BOOST_REQUIRE(plain == asBytes(message));
 }
 
-BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
-{
-	ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-	ECIES::Encryptor e(d.GetKey());
-	
-	Secret s;
-	pp::exportPrivateKey(d.GetKey(), s);
-	
-	Public p;
-	pp::exportPublicKey(e.GetKey(), p);
-	
-	BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref())));
-	
-	Secret previous = s;
-	for (auto i = 0; i < 2; i++)
-	{
-		ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-		ECIES::Encryptor e(d.GetKey());
-		
-		Secret s;
-		pp::exportPrivateKey(d.GetKey(), s);
-		BOOST_REQUIRE(s != previous);
-		
-		Public p;
-		pp::exportPublicKey(e.GetKey(), p);
-
-		h160 secp256k1Addr = dev::toAddress(s);
-		h160 cryptoppAddr = right160(dev::sha3(p.ref()));
-		if (secp256k1Addr != cryptoppAddr)
-		{
-			BOOST_REQUIRE(secp256k1Addr == cryptoppAddr);
-			break;
-		}
-	}
-}
-
 BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
 {
-	// cryptopp implementation of secp256k1lib sign_compact w/recid parameter and recovery of public key from signature
-		
+	secp256k1_start();
+	
 	// base secret
 	Secret secret(sha3("privacy"));
 	
 	// we get ec params from signer
-	const CryptoPP::DL_GroupParameters_EC params = pp::secp256k1Params;
 	ECDSA::Signer signer;
 	
 	// e := sha3(msg)
 	bytes e(fromHex("0x01"));
 	e.resize(32);
-	int tests = 2; // Oct 29: successful @ 1500
+	int tests = 2;
 	while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--)
 	{
 		KeyPair key(secret);
 		Public pkey = key.pub();
-		pp::initializeDLScheme(secret, signer);
+		signer.AccessKey().Initialize(s_params, secretToExponent(secret));
 		
 		h256 he(sha3(e));
 		Integer heInt(he.asBytes().data(), 32);
 		h256 k(crypto::kdf(secret, he));
 		Integer kInt(k.asBytes().data(), 32);
-		kInt %= params.GetSubgroupOrder()-1;
+		kInt %= s_params.GetSubgroupOrder()-1;
 
-		ECP::Point rp = params.ExponentiateBase(kInt);
-		Integer const& q = params.GetGroupOrder();
-		Integer r = params.ConvertElementToInteger(rp);
-		int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
+		ECP::Point rp = s_params.ExponentiateBase(kInt);
+		Integer const& q = s_params.GetGroupOrder();
+		Integer r = s_params.ConvertElementToInteger(rp);
 
 		Integer kInv = kInt.InverseMod(q);
 		Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q;
 		BOOST_REQUIRE(!!r && !!s);
-		
-/*
-		// For future reference:
-		// According to maths, this codepath can't be reached, however, it's in secp256k1.
-		// Commenting this out diverges from codebase implementation.
-		// To be removed after upstream PR and proof are evaulated.
- 
-		if (s > params.GetSubgroupOrder())
-		{
-			// note: this rarely happens
-			s = params.GetGroupOrder() - s;
-			if (recid)
-				recid ^= 1;
-		}
- */
 
 		Signature sig;
+		sig[64] = rp.y.IsOdd() ? 1 : 0;
 		r.Encode(sig.data(), 32);
 		s.Encode(sig.data() + 32, 32);
-		sig[64] = recid;
 
 		Public p = dev::recover(sig, he);
 		BOOST_REQUIRE(p == pkey);
 		
 		// verify w/cryptopp
-		BOOST_REQUIRE(crypto::verify(pkey, sig, bytesConstRef(&e)));
+		BOOST_REQUIRE(s_secp256k1.verify(pkey, sig, bytesConstRef(&e)));
 		
 		// verify with secp256k1lib
 		byte encpub[65] = {0x04};
@@ -166,16 +128,18 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
 
 BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 {
+	secp256k1_start();
+	
 	// cryptopp integer encoding
 	Integer nHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2H");
 	Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32);
 	BOOST_REQUIRE(nHex == nB);
 	
-	bytes sbytes(fromHex("0x01"));
-	Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
+	bytes sbytes(fromHex("0xFFFF"));
+	Secret secret(sha3(sbytes));
 	KeyPair key(secret);
 	
-	bytes m(fromHex("0x01"));
+	bytes m({0xFF});
 	int tests = 2;
 	while (m[0]++, tests--)
 	{
@@ -183,45 +147,45 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 		Integer hInt(hm.asBytes().data(), 32);
 		h256 k(hm ^ key.sec());
 		Integer kInt(k.asBytes().data(), 32);
-		
+
 		// raw sign w/cryptopp (doesn't pass through cryptopp hash filter)
 		ECDSA::Signer signer;
-		pp::initializeDLScheme(key.sec(), signer);
+		signer.AccessKey().Initialize(s_params, secretToExponent(key.sec()));
 		Integer r, s;
 		signer.RawSign(kInt, hInt, r, s);
 
 		// verify cryptopp raw-signature w/cryptopp
 		ECDSA::Verifier verifier;
-		pp::initializeDLScheme(key.pub(), verifier);
+		verifier.AccessKey().Initialize(s_params, publicToPoint(key.pub()));
 		Signature sigppraw;
 		r.Encode(sigppraw.data(), 32);
 		s.Encode(sigppraw.data() + 32, 32);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppraw.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm));
 		
 		// sign with cryptopp, verify, recover w/sec256lib
 		Signature seclibsig(dev::sign(key.sec(), hm));
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), seclibsig.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm));
 		BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub());
 
 		// sign with cryptopp (w/hash filter?), verify with cryptopp
 		bytes sigppb(signer.MaxSignatureLength());
-		size_t ssz = signer.SignMessage(pp::PRNG, m.data(), m.size(), sigppb.data());
+		size_t ssz = signer.SignMessage(s_rng, m.data(), m.size(), sigppb.data());
 		Signature sigpp;
 		memcpy(sigpp.data(), sigppb.data(), 64);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz));
-		BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm));
 
 		// sign with cryptopp and stringsource hash filter
 		string sigstr;
-		StringSource ssrc(asString(m), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr)));
+		StringSource ssrc(asString(m), true, new SignerFilter(s_rng, signer, new StringSink(sigstr)));
 		FixedHash retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer);
 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64));
-		BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
+//		BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
 		BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm));
 		
 		/// verification w/sec256lib
@@ -247,92 +211,102 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
 	}
 }
 
-BOOST_AUTO_TEST_CASE(cryptopp_public_export_import)
-{
-	ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve);
-	ECIES::Encryptor e(d.GetKey());
-
-	Secret s;
-	pp::exportPrivateKey(d.GetKey(), s);
-	Public p;
-	pp::exportPublicKey(e.GetKey(), p);
-	Address addr = right160(dev::sha3(p.ref()));
-	BOOST_REQUIRE(toAddress(s) == addr);
-	
-	KeyPair l(s);
-	BOOST_REQUIRE(l.address() == addr);
-}
-
 BOOST_AUTO_TEST_CASE(ecies_eckeypair)
 {
 	KeyPair k = KeyPair::create();
 
-	string message("Now is the time for all good persons to come to the aide of humanity.");
+	string message("Now is the time for all good persons to come to the aid of humanity.");
 	string original = message;
 	
 	bytes b = asBytes(message);
-	encrypt(k.pub(), b);
+	s_secp256k1.encrypt(k.pub(), b);
 	BOOST_REQUIRE(b != asBytes(original));
 
-	decrypt(k.sec(), b);
+	s_secp256k1.decrypt(k.sec(), b);
 	BOOST_REQUIRE(b == asBytes(original));
 }
 
-BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
+BOOST_AUTO_TEST_CASE(ecdh)
 {
-	// New connections require new ECDH keypairs
-	// Every new connection requires a new EC keypair
-	// Every new trust requires a new EC keypair
-	// All connections should share seed for PRF (or PRNG) for nonces
+	cnote << "Testing ecdh...";
+
+	ECDH::Domain dhLocal(s_curveOID);
+	SecByteBlock privLocal(dhLocal.PrivateKeyLength());
+	SecByteBlock pubLocal(dhLocal.PublicKeyLength());
+	dhLocal.GenerateKeyPair(s_rng, privLocal, pubLocal);
+	
+	ECDH::Domain dhRemote(s_curveOID);
+	SecByteBlock privRemote(dhRemote.PrivateKeyLength());
+	SecByteBlock pubRemote(dhRemote.PublicKeyLength());
+	dhRemote.GenerateKeyPair(s_rng, privRemote, pubRemote);
+	
+	assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
+	
+	// local: send public to remote; remote: send public to local
 	
+	// Local
+	SecByteBlock sharedLocal(dhLocal.AgreedValueLength());
+	assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote));
 	
+	// Remote
+	SecByteBlock sharedRemote(dhRemote.AgreedValueLength());
+	assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal));
+	
+	// Test
+	Integer ssLocal, ssRemote;
+	ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes());
+	ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes());
+	
+	assert(ssLocal != 0);
+	assert(ssLocal == ssRemote);
+	
+	
+	// Now use our keys
+	KeyPair a = KeyPair::create();
+	byte puba[65] = {0x04};
+	memcpy(&puba[1], a.pub().data(), 64);
+	
+	KeyPair b = KeyPair::create();
+	byte pubb[65] = {0x04};
+	memcpy(&pubb[1], b.pub().data(), 64);
+	
+	ECDH::Domain dhA(s_curveOID);
+	Secret shared;
+	BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb));
+	BOOST_REQUIRE(shared);
 }
 
-BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
+BOOST_AUTO_TEST_CASE(ecdhe)
 {
-	cnote << "Testing cryptopp_ecies_message...";
-
-	string const message("Now is the time for all good persons to come to the aide of humanity.");
-
-	ECIES::Decryptor localDecryptor(pp::PRNG, pp::secp256k1Curve);
-	SavePrivateKey(localDecryptor.GetPrivateKey());
+	cnote << "Testing ecdhe...";
 	
-	ECIES::Encryptor localEncryptor(localDecryptor);
-	SavePublicKey(localEncryptor.GetPublicKey());
-
-	ECIES::Decryptor futureDecryptor;
-	LoadPrivateKey(futureDecryptor.AccessPrivateKey());
-	futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG, 3);
+	ECDHE a, b;
+	BOOST_CHECK_NE(a.pubkey(), b.pubkey());
 	
-	ECIES::Encryptor futureEncryptor;
-	LoadPublicKey(futureEncryptor.AccessPublicKey());
-	futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG, 3);
-
-	// encrypt/decrypt with local
-	string cipherLocal;
-	StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG, localEncryptor, new StringSink(cipherLocal) ) );
-	string plainLocal;
-	StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocal) ) );
-
-	// encrypt/decrypt with future
-	string cipherFuture;
-	StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG, futureEncryptor, new StringSink(cipherFuture) ) );
-	string plainFuture;
-	StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFuture) ) );
+	ECDHE local;
+	ECDHE remote;
 	
-	// decrypt local w/future
-	string plainFutureFromLocal;
-	StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFutureFromLocal) ) );
+	// local tx pubkey -> remote
+	Secret sremote;
+	remote.agree(local.pubkey(), sremote);
 	
-	// decrypt future w/local
-	string plainLocalFromFuture;
-	StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocalFromFuture) ) );
+	// remote tx pbukey -> local
+	Secret slocal;
+	local.agree(remote.pubkey(), slocal);
+
+	BOOST_REQUIRE(sremote);
+	BOOST_REQUIRE(slocal);
+	BOOST_REQUIRE_EQUAL(sremote, slocal);
+}
+
+BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
+{
+	// New connections require new ECDH keypairs
+	// Every new connection requires a new EC keypair
+	// Every new trust requires a new EC keypair
+	// All connections should share seed for PRF (or PRNG) for nonces
 	
 	
-	BOOST_REQUIRE(plainLocal == message);
-	BOOST_REQUIRE(plainFuture == plainLocal);
-	BOOST_REQUIRE(plainFutureFromLocal == plainLocal);
-	BOOST_REQUIRE(plainLocalFromFuture == plainLocal);
 }
 
 BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
@@ -346,21 +320,28 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
 	rng.GenerateBlock(key, key.size());
 	
 	// cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr
-	byte ctr[AES::BLOCKSIZE];
-	rng.GenerateBlock(ctr, sizeof(ctr));
+	FixedHash ctr;
+	rng.GenerateBlock(ctr.data(), sizeof(ctr));
+
+	// used for decrypt
+	FixedHash ctrcopy(ctr);
 	
-	string text = "Now is the time for all good persons to come to the aide of humanity.";
-	// c++11 ftw
+	string text = "Now is the time for all good persons to come to the aid of humanity.";
 	unsigned char const* in = (unsigned char*)&text[0];
 	unsigned char* out = (unsigned char*)&text[0];
 	string original = text;
+	string doublespeak = text + text;
 	
 	string cipherCopy;
 	try
 	{
 		CTR_Mode::Encryption e;
-		e.SetKeyWithIV(key, key.size(), ctr);
+		e.SetKeyWithIV(key, key.size(), ctr.data());
+		
+		// 68 % 255 should be difference of counter
 		e.ProcessData(out, in, text.size());
+		ctr = h128(u128(ctr) + text.size() % 16);
+		
 		BOOST_REQUIRE(text != original);
 		cipherCopy = text;
 	}
@@ -372,7 +353,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
 	try
 	{
 		CTR_Mode< AES >::Decryption d;
-		d.SetKeyWithIV(key, key.size(), ctr);
+		d.SetKeyWithIV(key, key.size(), ctrcopy.data());
 		d.ProcessData(out, in, text.size());
 		BOOST_REQUIRE(text == original);
 	}
@@ -390,7 +371,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
 		out = (unsigned char*)&cipherCopy[0];
 		
 		CTR_Mode::Encryption e;
-		e.SetKeyWithIV(key, key.size(), ctr);
+		e.SetKeyWithIV(key, key.size(), ctrcopy.data());
 		e.ProcessData(out, in, text.size());
 		
 		// yep, ctr mode.
diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp
index ba2db67e6..054ad3297 100644
--- a/test/solidityCompiler.cpp
+++ b/test/solidityCompiler.cpp
@@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
 							 "}\n";
 	bytes code = compileContract(sourceCode);
 
-	unsigned boilerplateSize = 51;
+	unsigned boilerplateSize = 42;
 	bytes expectation({byte(Instruction::JUMPDEST),
 					   byte(Instruction::PUSH1), 0x0, // initialize local variable x
 					   byte(Instruction::PUSH1), 0x2,
@@ -100,8 +100,8 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers)
 							 "}\n";
 	bytes code = compileContract(sourceCode);
 
-	unsigned shift = 75;
-	unsigned boilerplateSize = 88;
+	unsigned shift = 70;
+	unsigned boilerplateSize = 83;
 	bytes expectation({byte(Instruction::JUMPDEST),
 					   byte(Instruction::PUSH1), 0x0, // initialize return variable d
 					   byte(Instruction::DUP3),
@@ -153,8 +153,8 @@ BOOST_AUTO_TEST_CASE(ifStatement)
 							 "}\n";
 	bytes code = compileContract(sourceCode);
 
-	unsigned shift = 38;
-	unsigned boilerplateSize = 51;
+	unsigned shift = 29;
+	unsigned boilerplateSize = 42;
 	bytes expectation({byte(Instruction::JUMPDEST),
 					   byte(Instruction::PUSH1), 0x0,
 					   byte(Instruction::DUP1),
@@ -195,8 +195,8 @@ BOOST_AUTO_TEST_CASE(loops)
 							 "}\n";
 	bytes code = compileContract(sourceCode);
 
-	unsigned shift = 38;
-	unsigned boilerplateSize = 51;
+	unsigned shift = 29;
+	unsigned boilerplateSize = 42;
 	bytes expectation({byte(Instruction::JUMPDEST),
 					   byte(Instruction::JUMPDEST),
 					   byte(Instruction::PUSH1), 0x1,
diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp
index 796adcb15..d905646cb 100644
--- a/test/solidityEndToEndTest.cpp
+++ b/test/solidityEndToEndTest.cpp
@@ -22,6 +22,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,36 +42,72 @@ class ExecutionFramework
 public:
 	ExecutionFramework() { g_logVerbosity = 0; }
 
-	bytes const& compileAndRun(std::string const& _sourceCode)
+	bytes const& compileAndRun(string const& _sourceCode)
 	{
-		bytes code = dev::solidity::CompilerStack::compile(_sourceCode);
+		bytes code = dev::solidity::CompilerStack::staticCompile(_sourceCode);
 		sendMessage(code, true);
 		BOOST_REQUIRE(!m_output.empty());
 		return m_output;
 	}
 
-	bytes const& callFunction(byte _index, bytes const& _data)
+	bytes const& callContractFunction(byte _index, bytes const& _data = bytes())
 	{
 		sendMessage(bytes(1, _index) + _data, false);
 		return m_output;
 	}
 
-	bytes const& callFunction(byte _index, u256 const& _argument1)
+	template 
+	bytes const& callContractFunction(byte _index, Args const&... _arguments)
 	{
-		return callFunction(_index, toBigEndian(_argument1));
+		return callContractFunction(_index, argsToBigEndian(_arguments...));
 	}
 
-	bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun, u256 const& _argument1)
+	template 
+	void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunction, Args const&... _arguments)
 	{
-		return toBigEndian(_cppfun(_argument1)) == callFunction(_index, toBigEndian(_argument1));
+		bytes solidityResult = callContractFunction(_index, _arguments...);
+		bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...);
+		BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match."
+							"\nSolidity: " + toHex(solidityResult) + "\nC++:      " + toHex(cppResult));
 	}
 
-	bool testSolidityAgainstCpp(byte _index, std::function const& _cppfun)
+	template 
+	void testSolidityAgainstCppOnRange(byte _index, CppFunction const& _cppFunction,
+									   u256 const& _rangeStart, u256 const& _rangeEnd)
 	{
-		return toBigEndian(_cppfun()) == callFunction(_index, bytes());
+		for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument)
+		{
+			bytes solidityResult = callContractFunction(_index, argument);
+			bytes cppResult = callCppAndEncodeResult(_cppFunction, argument);
+			BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match."
+								"\nSolidity: " + toHex(solidityResult) + "\nC++:      " + toHex(cppResult) +
+								"\nArgument: " + toHex(toBigEndian(argument)));
+		}
 	}
 
 private:
+	template 
+	bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const
+	{
+		return toBigEndian(_firstArg) + argsToBigEndian(_followingArgs...);
+	}
+
+	bytes argsToBigEndian() const { return bytes(); }
+
+	template 
+	auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
+	-> typename enable_if::value, bytes>::type
+	{
+		_cppFunction(_arguments...);
+		return bytes();
+	}
+	template 
+	auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
+	-> typename enable_if::value, bytes>::type
+	{
+		return toBigEndian(_cppFunction(_arguments...));
+	}
+
 	void sendMessage(bytes const& _data, bool _isCreation)
 	{
 		eth::Executive executive(m_state);
@@ -91,7 +128,10 @@ private:
 			BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
 		}
 		else
+		{
+			BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress));
 			BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address()));
+		}
 		BOOST_REQUIRE(executive.go());
 		executive.finalize();
 		m_output = executive.out().toVector();
@@ -112,8 +152,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
 							 "  function f(uint a) returns(uint d) { return a * 7; }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	u256 a = 0x200030004;
-	BOOST_CHECK(callFunction(0, a) == toBigEndian(a * 7));
+	testSolidityAgainstCppOnRange(0, [](u256 const& a) -> u256 { return a * 7; }, 0, 100);
 }
 
 BOOST_AUTO_TEST_CASE(empty_contract)
@@ -121,7 +160,7 @@ BOOST_AUTO_TEST_CASE(empty_contract)
 	char const* sourceCode = "contract test {\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, bytes()).empty());
+	BOOST_CHECK(callContractFunction(0, bytes()).empty());
 }
 
 BOOST_AUTO_TEST_CASE(recursive_calls)
@@ -133,7 +172,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	std::function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256
+	function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256
 	{
 		if (n <= 1)
 			return 1;
@@ -141,11 +180,23 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
 			return n * recursive_calls_cpp(n - 1);
 	};
 
-	BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(0)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(1)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(2)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(3)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, recursive_calls_cpp, u256(4)));
+	testSolidityAgainstCppOnRange(0, recursive_calls_cpp, 0, 5);
+}
+
+BOOST_AUTO_TEST_CASE(multiple_functions)
+{
+	char const* sourceCode = "contract test {\n"
+							 "  function a() returns(uint n) { return 0; }\n"
+							 "  function b() returns(uint n) { return 1; }\n"
+							 "  function c() returns(uint n) { return 2; }\n"
+							 "  function f() returns(uint n) { return 3; }\n"
+							 "}\n";
+	compileAndRun(sourceCode);
+	BOOST_CHECK(callContractFunction(0, bytes()) == toBigEndian(u256(0)));
+	BOOST_CHECK(callContractFunction(1, bytes()) == toBigEndian(u256(1)));
+	BOOST_CHECK(callContractFunction(2, bytes()) == toBigEndian(u256(2)));
+	BOOST_CHECK(callContractFunction(3, bytes()) == toBigEndian(u256(3)));
+	BOOST_CHECK(callContractFunction(4, bytes()) == bytes());
 }
 
 BOOST_AUTO_TEST_CASE(while_loop)
@@ -169,11 +220,7 @@ BOOST_AUTO_TEST_CASE(while_loop)
 		return nfac;
 	};
 
-	BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(0)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(1)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(2)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(3)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, while_loop_cpp, u256(4)));
+	testSolidityAgainstCppOnRange(0, while_loop_cpp, 0, 5);
 }
 
 BOOST_AUTO_TEST_CASE(break_outside_loop)
@@ -184,9 +231,8 @@ BOOST_AUTO_TEST_CASE(break_outside_loop)
 							 "    break; continue; return 2;\n"
 							 "  }\n"
 							 "}\n";
-	ExecutionFramework framework;
-	framework.compileAndRun(sourceCode);
-	BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2)));
+	compileAndRun(sourceCode);
+	testSolidityAgainstCpp(0, [](u256 const&) -> u256 { return 2; }, u256(0));
 }
 
 BOOST_AUTO_TEST_CASE(nested_loops)
@@ -209,8 +255,7 @@ BOOST_AUTO_TEST_CASE(nested_loops)
 							 "    return x;\n"
 							 "  }\n"
 							 "}\n";
-	ExecutionFramework framework;
-	framework.compileAndRun(sourceCode);
+	compileAndRun(sourceCode);
 
 	auto nested_loops_cpp = [](u256  n) -> u256
 	{
@@ -236,18 +281,7 @@ BOOST_AUTO_TEST_CASE(nested_loops)
 		return n;
 	};
 
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(0)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(1)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(2)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(3)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(4)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(5)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(6)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(7)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(8)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(9)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(10)));
-	BOOST_CHECK(framework.testSolidityAgainstCpp(0, nested_loops_cpp, u256(11)));
+	testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12);
 }
 
 BOOST_AUTO_TEST_CASE(calling_other_functions)
@@ -279,7 +313,8 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
 		return 3 * n + 1;
 	};
 
-	auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp] (u256 n) -> u256 {
+	auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp](u256 n) -> u256
+	{
 		u256 y;
 		while ((y = n) > 1)
 		{
@@ -291,11 +326,11 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
 		return y;
 	};
 
-	BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(0)));
-	BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(1)));
-	BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(2)));
-	BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(8)));
-	BOOST_CHECK(testSolidityAgainstCpp(2, collatz_cpp, u256(127)));
+	testSolidityAgainstCpp(2, collatz_cpp, u256(0));
+	testSolidityAgainstCpp(2, collatz_cpp, u256(1));
+	testSolidityAgainstCpp(2, collatz_cpp, u256(2));
+	testSolidityAgainstCpp(2, collatz_cpp, u256(8));
+	testSolidityAgainstCpp(2, collatz_cpp, u256(127));
 }
 
 BOOST_AUTO_TEST_CASE(many_local_variables)
@@ -308,8 +343,15 @@ BOOST_AUTO_TEST_CASE(many_local_variables)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, toBigEndian(u256(0x1000)) + toBigEndian(u256(0x10000)) + toBigEndian(u256(0x100000)))
-				== toBigEndian(u256(0x121121)));
+	auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256
+	{
+		u256 a = 0x1;
+		u256 b = 0x10;
+		u256 c = 0x100;
+		u256 y = a + b + c + x1 + x2 + x3;
+		return y + b + x2;
+	};
+	testSolidityAgainstCpp(0, f, u256(0x1000), u256(0x10000), u256(0x100000));
 }
 
 BOOST_AUTO_TEST_CASE(packing_unpacking_types)
@@ -322,7 +364,7 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0"))
+	BOOST_CHECK(callContractFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0"))
 				== fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f"));
 }
 
@@ -334,7 +376,7 @@ BOOST_AUTO_TEST_CASE(multiple_return_values)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
+	BOOST_CHECK(callContractFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd)))
 				== toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0)));
 }
 
@@ -354,8 +396,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
 		return n;
 	};
 
-	BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(0)));
-	BOOST_CHECK(testSolidityAgainstCpp(0, short_circuiting_cpp, u256(1)));
+	testSolidityAgainstCppOnRange(0, short_circuiting_cpp, 0, 2);
 }
 
 BOOST_AUTO_TEST_CASE(high_bits_cleaning)
@@ -375,7 +416,7 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning)
 			return 0;
 		return x;
 	};
-	BOOST_CHECK(testSolidityAgainstCpp(0, high_bits_cleaning_cpp));
+	testSolidityAgainstCpp(0, high_bits_cleaning_cpp);
 }
 
 BOOST_AUTO_TEST_CASE(sign_extension)
@@ -395,7 +436,7 @@ BOOST_AUTO_TEST_CASE(sign_extension)
 			return 0;
 		return u256(x) * -1;
 	};
-	BOOST_CHECK(testSolidityAgainstCpp(0, sign_extension_cpp));
+	testSolidityAgainstCpp(0, sign_extension_cpp);
 }
 
 BOOST_AUTO_TEST_CASE(small_unsigned_types)
@@ -412,7 +453,7 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types)
 		uint32_t x = uint32_t(0xffffff) * 0xffffff;
 		return x / 0x100;
 	};
-	BOOST_CHECK(testSolidityAgainstCpp(0, small_unsigned_types_cpp));
+	testSolidityAgainstCpp(0, small_unsigned_types_cpp);
 }
 
 BOOST_AUTO_TEST_CASE(small_signed_types)
@@ -427,7 +468,7 @@ BOOST_AUTO_TEST_CASE(small_signed_types)
 	{
 		return -int32_t(10) * -int64_t(20);
 	};
-	BOOST_CHECK(testSolidityAgainstCpp(0, small_signed_types_cpp));
+	testSolidityAgainstCpp(0, small_signed_types_cpp);
 }
 
 BOOST_AUTO_TEST_CASE(state_smoke_test)
@@ -445,14 +486,14 @@ BOOST_AUTO_TEST_CASE(state_smoke_test)
 							 "  }\n"
 							 "}\n";
 	compileAndRun(sourceCode);
-	BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0)));
-	BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0)));
-	BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes());
-	BOOST_CHECK(callFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes());
-	BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234)));
-	BOOST_CHECK(callFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765)));
-	BOOST_CHECK(callFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes());
-	BOOST_CHECK(callFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3)));
+	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0)));
+	BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0)));
+	BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes());
+	BOOST_CHECK(callContractFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes());
+	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234)));
+	BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765)));
+	BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes());
+	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3)));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/solidityJSONInterfaceTest.cpp b/test/solidityJSONInterfaceTest.cpp
new file mode 100644
index 000000000..1a443087f
--- /dev/null
+++ b/test/solidityJSONInterfaceTest.cpp
@@ -0,0 +1,214 @@
+/*
+	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 .
+ */
+/**
+ * @author Marek Kotewicz 
+ * @date 2014
+ * Unit tests for the solidity compiler JSON Interface output.
+ */
+
+#include 
+#include 
+#include 
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+class InterfaceChecker
+{
+public:
+	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
+	{
+		m_compilerStack.parse(_code);
+		std::string generatedInterfaceString = m_compilerStack.getInterface();
+		Json::Value generatedInterface;
+		m_reader.parse(generatedInterfaceString, generatedInterface);
+		Json::Value expectedInterface;
+		m_reader.parse(_expectedInterfaceString, expectedInterface);
+		return expectedInterface == generatedInterface;
+	}
+	
+private:
+	CompilerStack m_compilerStack;
+	Json::Reader m_reader;
+};
+
+BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker)
+
+BOOST_AUTO_TEST_CASE(basic_test)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"}\n";
+
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(empty_contract)
+{
+	char const* sourceCode = "contract test {\n"
+	"}\n";
+
+	char const* interface = "[]";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_methods)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"  function g(uint b) returns(uint e) { return b * 8; }\n"
+	"}\n";
+	
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	},
+	{
+		"name": "g",
+		"inputs": [
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "e",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_params)
+{
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n"
+	"}\n";
+
+	char const* interface = R"([
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		},
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_CASE(multiple_methods_order)
+{
+	// methods are expected to be in alpabetical order
+	char const* sourceCode = "contract test {\n"
+	"  function f(uint a) returns(uint d) { return a * 7; }\n"
+	"  function c(uint b) returns(uint e) { return b * 8; }\n"
+	"}\n";
+		
+	char const* interface = R"([
+	{
+		"name": "c",
+		"inputs": [
+		{
+			"name": "b",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "e",
+			"type": "uint256"
+		}
+		]
+	},
+	{
+		"name": "f",
+		"inputs": [
+		{
+			"name": "a",
+			"type": "uint256"
+		}
+		],
+		"outputs": [
+		{
+			"name": "d",
+			"type": "uint256"
+		}
+		]
+	}
+	])";
+	
+	BOOST_CHECK(checkInterface(sourceCode, interface));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+}
diff --git a/test/stPreCompiledContractsFiller.json b/test/stPreCompiledContractsFiller.json
index 8975f1aea..bb2b35756 100644
--- a/test/stPreCompiledContractsFiller.json
+++ b/test/stPreCompiledContractsFiller.json
@@ -12,7 +12,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -46,7 +46,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -80,7 +80,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -114,7 +114,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }",
+                 "code": "{ [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -148,7 +148,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -182,7 +182,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -216,7 +216,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
+                 "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -284,7 +284,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -318,7 +318,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -352,7 +352,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -386,7 +386,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -420,7 +420,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -454,7 +454,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -522,7 +522,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ [[ 2 ]] (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -556,7 +556,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -590,7 +590,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -624,7 +624,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -658,7 +658,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
@@ -692,7 +692,7 @@
              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
                  "balance" : "20000000",
                  "nonce" : 0,
-                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
+                 "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}",
                  "storage": {}
              },
             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
diff --git a/test/state.cpp b/test/state.cpp
index 91d9f3e51..b5b238299 100644
--- a/test/state.cpp
+++ b/test/state.cpp
@@ -122,6 +122,40 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
 	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
 }
 
+BOOST_AUTO_TEST_CASE(stCreateTest)
+{
+	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
+	{
+		string arg = boost::unit_test::framework::master_test_suite().argv[i];
+		if (arg == "--createtest")
+		{
+			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
+			{
+				cnote << "usage: ./testeth --createtest  \n";
+				return;
+			}
+			try
+			{
+				cnote << "Populating tests...";
+				json_spirit::mValue v;
+				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
+				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
+				json_spirit::read_string(s, v);
+				dev::test::doStateTests(v, true);
+				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
+			}
+			catch (Exception const& _e)
+			{
+				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e));
+			}
+			catch (std::exception const& _e)
+			{
+				BOOST_ERROR("Failed state test with Exception: " << _e.what());
+			}
+		}
+	}
+}
+
 BOOST_AUTO_TEST_CASE(userDefinedFileState)
 {
 	dev::test::userDefinedTest("--statetest", dev::test::doStateTests);
diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj
index 30deea983..0578a8f16 100644
--- a/windows/LibEthereum.vcxproj
+++ b/windows/LibEthereum.vcxproj
@@ -125,6 +125,7 @@
     
     
     
+    
     
     
       true
@@ -145,7 +146,6 @@
       true
     
     
-    
     
     
     
@@ -341,6 +341,8 @@
     
     
     
+    
+    
     
     
       true
@@ -367,7 +369,6 @@
       true
     
     
-	
     
     
     
@@ -567,4 +568,4 @@
   
   
   
-
+
\ No newline at end of file
diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters
index 514320472..114364008 100644
--- a/windows/LibEthereum.vcxproj.filters
+++ b/windows/LibEthereum.vcxproj.filters
@@ -40,9 +40,6 @@
     
       libevmcore
     
-    
-      liblll
-    
     
       liblll
     
@@ -202,6 +199,9 @@
     
       libethereum
     
+    
+      libevmcore
+    
   
   
     
@@ -248,9 +248,6 @@
     
     
       liblll
-    
-	
-	  libevmcore
     
     
       liblll
@@ -435,6 +432,12 @@
     
       libethereum
     
+    
+      libevmcore
+    
+    
+      libevmcore
+    
   
   
     
@@ -471,4 +474,4 @@
       {d838fece-fc20-42f6-bff5-97c236159b80}
     
   
-
+
\ No newline at end of file