diff --git a/abi/main.cpp b/abi/main.cpp
index e895152cc..cdae81f1e 100644
--- a/abi/main.cpp
+++ b/abi/main.cpp
@@ -43,8 +43,8 @@ void help()
 		<< "    -h,--help  Print this help message and exit." << endl
 		<< "    -V,--version  Show the version and exit." << endl
 		<< "Input options:" << endl
-		<< "    -p,--prefix  Require all input formats to be prefixed e.g. 0x for hex, . for decimal, @ for binary." << endl
-		<< "    -P,--no-prefix  Require no input format to be prefixed." << endl
+		<< "    -f,--format-prefix  Require all input formats to be prefixed e.g. 0x for hex, . for decimal, @ for binary." << endl
+		<< "    -F,--no-format-prefix  Require no input format to be prefixed." << endl
 		<< "    -t,--typing  Require all arguments to be typed e.g. b32: (bytes32), u64: (uint64), b[]: (byte[]), i: (int256)." << endl
 		<< "    -T,--no-typing  Require no arguments to be typed." << endl
 		<< "Output options:" << endl
@@ -53,8 +53,6 @@ void help()
 		<< "    -x,--hex  Display all data as hex." << endl
 		<< "    -b,--binary  Display all data as binary." << endl
 		<< "    -p,--prefix  Prefix by a base identifier." << endl
-		<< "    -z,--no-zeroes  Remove any leading zeroes from the data." << endl
-		<< "    -n,--no-nulls  Remove any trailing nulls from the data." << endl
 		;
 	exit(0);
 }
@@ -90,7 +88,9 @@ enum class Format
 {
 	Binary,
 	Hex,
-	Decimal
+	Decimal,
+	Open,
+	Close
 };
 
 struct InvalidUserString: public Exception {};
@@ -115,6 +115,12 @@ static const map<Base, string> s_bases =
 	{ Base::Fixed, "fixed" }
 };
 
+struct EncodingPrefs
+{
+	Encoding e = Encoding::Auto;
+	bool prefix = true;
+};
+
 struct ABIType
 {
 	Base base = Base::Unknown;
@@ -204,39 +210,72 @@ struct ABIType
 
 	bool isBytes() const { return base == Base::Bytes && !size; }
 
-	string render(bytes const& _data) const
+	string render(bytes const& _data, EncodingPrefs _e) const
 	{
-		if (base == Base::Uint)
-			return toString(fromBigEndian<u256>(_data));
-		else if (base == Base::Int)
-			return toString((s256)fromBigEndian<u256>(_data));
+		if (base == Base::Uint || base == Base::Int)
+		{
+			if (_e.e == Encoding::Hex)
+				return (_e.prefix ? "0x" : "") + toHex(toCompactBigEndian(fromBigEndian<bigint>(bytesConstRef(&_data).cropped(32 - size / 8))));
+			else
+			{
+				bigint i = fromBigEndian<bigint>(bytesConstRef(&_data).cropped(32 - size / 8));
+				if (base == Base::Int && i > (bigint(1) << (size - 1)))
+					i -= (bigint(1) << size);
+				return toString(i);
+			}
+		}
 		else if (base == Base::Address)
-			return toString(Address(h256(_data)));
+		{
+			Address a = Address(h256(_data), Address::AlignRight);
+			return _e.e == Encoding::Binary ? asString(a.asBytes()) : ((_e.prefix ? "0x" : "") + toString(a));
+		}
+		else if (isBytes())
+		{
+			return _e.e == Encoding::Binary ? asString(_data) : ((_e.prefix ? "0x" : "") + toHex(_data));
+		}
+		else if (base == Base::Bytes)
+		{
+			bytesConstRef b(&_data);
+			b = b.cropped(0, size);
+			return _e.e == Encoding::Binary ? asString(b) : ((_e.prefix ? "0x" : "") + toHex(b));
+		}
+		else
+			throw InvalidFormat();
+	}
+
+	bytes unrender(bytes const& _data, Format _f) const
+	{
+		if (isBytes())
+		{
+			auto ret = _data;
+			while (ret.size() % 32 != 0)
+				ret.push_back(0);
+			return ret;
+		}
 		else
-			return toHex(_data);
+			return aligned(_data, _f, 32);
 	}
 
 	void noteHexInput(unsigned _nibbles) { if (base == Base::Unknown) { if (_nibbles == 40) base = Base::Address; else { base = Base::Bytes; size = _nibbles / 2; } } }
 	void noteBinaryInput() { if (base == Base::Unknown) { base = Base::Bytes; size = 32; } }
 	void noteDecimalInput() { if (base == Base::Unknown) { base = Base::Uint; size = 32; } }
-};
 
-bytes aligned(bytes const& _b, ABIType _t, Format _f, unsigned _length)
-{
-	(void)_t;
-	bytes ret = _b;
-	while (ret.size() < _length)
-		if (_f == Format::Binary)
-			ret.push_back(0);
-		else
-			ret.insert(ret.begin(), 0);
-	while (ret.size() > _length)
-		if (_f == Format::Binary)
-			ret.pop_back();
-		else
-			ret.erase(ret.begin());
-	return ret;
-}
+	bytes aligned(bytes const& _b, Format _f, unsigned _length) const
+	{
+		bytes ret = _b;
+		while (ret.size() < _length)
+			if (_f == Format::Binary)
+				ret.push_back(0);
+			else
+				ret.insert(ret.begin(), 0);
+		while (ret.size() > _length)
+			if (_f == Format::Binary)
+				ret.pop_back();
+			else
+				ret.erase(ret.begin());
+		return ret;
+	}
+};
 
 tuple<bytes, ABIType, Format> fromUser(std::string const& _arg, Tristate _prefix, Tristate _typing)
 {
@@ -269,25 +308,36 @@ tuple<bytes, ABIType, Format> fromUser(std::string const& _arg, Tristate _prefix
 			type.noteBinaryInput();
 			return make_tuple(asBytes(val.substr(1)), type, Format::Binary);
 		}
+		if (val == "[")
+			return make_tuple(bytes(), type, Format::Open);
+		if (val == "]")
+			return make_tuple(bytes(), type, Format::Close);
 	}
 	if (_prefix != Tristate::True)
 	{
-		if (_arg.find_first_not_of("0123456789") == string::npos)
+		if (val.find_first_not_of("0123456789") == string::npos)
 		{
 			type.noteDecimalInput();
 			return make_tuple(toCompactBigEndian(bigint(val)), type, Format::Decimal);
 		}
-		if (_arg.find_first_not_of("0123456789abcdefABCDEF") == string::npos)
+		if (val.find_first_not_of("0123456789abcdefABCDEF") == string::npos)
 		{
 			type.noteHexInput(val.size());
 			return make_tuple(fromHex(val), type, Format::Hex);
 		}
+		if (val == "[")
+			return make_tuple(bytes(), type, Format::Open);
+		if (val == "]")
+			return make_tuple(bytes(), type, Format::Close);
 		type.noteBinaryInput();
-		return make_tuple(asBytes(_arg), type, Format::Binary);
+		return make_tuple(asBytes(val), type, Format::Binary);
 	}
 	throw InvalidUserString();
 }
 
+struct ExpectedOpen: public Exception {};
+struct ExpectedClose: public Exception {};
+
 struct ABIMethod
 {
 	string name;
@@ -355,77 +405,107 @@ struct ABIMethod
 
 	bytes encode(vector<pair<bytes, Format>> const& _params) const
 	{
-		// ALL WRONG!!!!
-		// INARITIES SHOULD BE HEIRARCHICAL!
-
 		bytes ret = name.empty() ? bytes() : id().asBytes();
+		bytes suffix;
+
+		// int int[] int
+		// example: 42 [ 1 2 3 ] 69
+		// int[2][][3]
+		// example: [ [ [ 1 2 3 ] [ 4 5 6 ] ] [ ] ]
+
 		unsigned pi = 0;
-		vector<unsigned> inArity;
-		for (ABIType const& i: ins)
-		{
-			unsigned arity = 1;
-			for (auto j: i.dims)
-				if (j == -1)
-				{
-					ret += aligned(_params[pi].first, ABIType(), Format::Decimal, 32);
-					arity *= fromBigEndian<unsigned>(_params[pi].first);
-					pi++;
-				}
-				else
-					arity *= j;
-			if (i.isBytes())
-				for (unsigned i = 0; i < arity; ++i)
 
-			inArity.push_back(arity);
-		}
-		unsigned ii = 0;
-		for (ABIType const& i: ins)
+		for (ABIType const& a: ins)
 		{
-			for (unsigned j = 0; j < inArity[ii]; ++j)
-			{
-				if (i.base == Base::Bytes && !i.size)
+			auto put = [&]() {
+				if (a.isBytes())
+					ret += h256(u256(_params[pi].first.size())).asBytes();
+				suffix += a.unrender(_params[pi].first, _params[pi].second);
+				pi++;
+			};
+			function<void(vector<int>, unsigned)> putDim = [&](vector<int> addr, unsigned q) {
+				if (addr.size() == a.dims.size())
+					put();
+				else
 				{
-					ret += _params[pi].first;
-					while (ret.size() % 32 != 0)
-						ret.push_back(0);
+					if (_params[pi].second != Format::Open)
+						throw ExpectedOpen();
+					int l = a.dims[addr.size()];
+					if (l == -1)
+					{
+						// read ahead in params and discover the arity.
+						unsigned depth = 0;
+						l = 0;
+						for (unsigned pi2 = pi + 1; depth || _params[pi2].second != Format::Close;)
+						{
+							if (_params[pi2].second == Format::Open)
+								++depth;
+							if (_params[pi2].second == Format::Close)
+								--depth;
+							if (!depth)
+								++l;
+							if (++pi2 == _params.size())
+								throw ExpectedClose();
+						}
+						ret += h256(u256(l)).asBytes();
+					}
+					q *= l;
+					for (addr.push_back(0); addr.back() < l; ++addr.back())
+						putDim(addr, q);
+					if (_params[pi].second != Format::Close)
+						throw ExpectedClose();
 				}
-				else
-					ret += aligned(_params[pi].first, i, _params[pi].second, 32);
-				++pi;
-			}
-			++ii;
+			};
+			putDim(vector<int>(), 1);
 		}
-		return ret;
+		return ret + suffix;
 	}
-	string decode(bytes const& _data, int _index = -1)
+	string decode(bytes const& _data, int _index, EncodingPrefs _ep)
 	{
 		stringstream out;
 		if (_index == -1)
 			out << "[";
 		unsigned di = 0;
-		vector<ABIType> souts;
 		vector<unsigned> catDims;
-		for (ABIType a: outs)
+		for (ABIType const& a: outs)
 		{
-			unsigned q = 1;
-			for (auto& i: a.dims)
-			{
-				for (unsigned j = 0; j < q; ++j)
-					if (i == -1)
+			auto put = [&]() {
+				if (a.isBytes())
+				{
+					catDims.push_back(fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32)));
+					di += 32;
+				}
+			};
+			function<void(vector<int>, unsigned)> putDim = [&](vector<int> addr, unsigned q) {
+				if (addr.size() == a.dims.size())
+					put();
+				else
+				{
+					out << "[";
+					int l = a.dims[addr.size()];
+					if (l == -1)
 					{
-						catDims.push_back(fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32)));
+						l = fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32));
+						catDims.push_back(l);
 						di += 32;
 					}
-				q *= i;
-			}
-			if (a.isBytes())
-			souts.push_back(a);
+					q *= l;
+					for (addr.push_back(0); addr.back() < l; ++addr.back())
+						putDim(addr, q);
+					out << "]";
+				}
+			};
+			putDim(vector<int>(), 1);
 		}
-		for (ABIType const& a: souts)
+		unsigned d = 0;
+		for (ABIType const& a: outs)
 		{
 			auto put = [&]() {
-				out << a.render(bytesConstRef(&_data).cropped(di, 32).toBytes()) << ", ";
-				di += 32;
+				unsigned l = 32;
+				if (a.isBytes())
+					l = (catDims[d++] + 31 / 32) * 32;
+				out << a.render(bytesConstRef(&_data).cropped(di, l).toBytes(), _ep) << ", ";
+				di += l;
 			};
 			function<void(vector<int>)> putDim = [&](vector<int> addr) {
 				if (addr.size() == a.dims.size())
@@ -433,9 +513,11 @@ struct ABIMethod
 				else
 				{
 					out << "[";
-					auto d = addr;
 					addr.push_back(0);
-					for (addr.back() = 0; addr.back() < a.dims[addr.size() - 1]; ++addr.back())
+					int l = a.dims[addr.size() - 1];
+					if (l == -1)
+						l = catDims[d++];
+					for (addr.back() = 0; addr.back() < l; ++addr.back())
 					{
 						if (addr.back())
 							out << ", ";
@@ -543,10 +625,9 @@ int main(int argc, char** argv)
 	Mode mode = Mode::Encode;
 	string abiFile;
 	string method;
-	Tristate prefix = Tristate::Mu;
+	Tristate formatPrefix = Tristate::Mu;
 	Tristate typePrefix = Tristate::Mu;
-	bool clearZeroes = false;
-	bool clearNulls = false;
+	EncodingPrefs prefs;
 	bool verbose = false;
 	int outputIndex = -1;
 	vector<pair<bytes, Format>> params;
@@ -566,25 +647,23 @@ int main(int argc, char** argv)
 		else if ((arg == "-i" || arg == "--index") && argc > i)
 			outputIndex = atoi(argv[++i]);
 		else if (arg == "-p" || arg == "--prefix")
-			prefix = Tristate::True;
-		else if (arg == "-P" || arg == "--no-prefix")
-			prefix = Tristate::False;
+			prefs.prefix = true;
+		else if (arg == "-f" || arg == "--format-prefix")
+			formatPrefix = Tristate::True;
+		else if (arg == "-F" || arg == "--no-format-prefix")
+			formatPrefix = Tristate::False;
 		else if (arg == "-t" || arg == "--typing")
 			typePrefix = Tristate::True;
 		else if (arg == "-T" || arg == "--no-typing")
 			typePrefix = Tristate::False;
-		else if (arg == "-z" || arg == "--no-zeroes")
-			clearZeroes = true;
-		else if (arg == "-n" || arg == "--no-nulls")
-			clearNulls = true;
 		else if (arg == "-v" || arg == "--verbose")
 			verbose = true;
 		else if (arg == "-x" || arg == "--hex")
-			encoding = Encoding::Hex;
+			prefs.e = Encoding::Hex;
 		else if (arg == "-d" || arg == "--decimal" || arg == "--dec")
-			encoding = Encoding::Decimal;
+			prefs.e = Encoding::Decimal;
 		else if (arg == "-b" || arg == "--binary" || arg == "--bin")
-			encoding = Encoding::Binary;
+			prefs.e = Encoding::Binary;
 		else if (arg == "-v" || arg == "--verbose")
 			version();
 		else if (arg == "-V" || arg == "--version")
@@ -593,7 +672,7 @@ int main(int argc, char** argv)
 			method = arg;
 		else
 		{
-			auto u = fromUser(arg, prefix, typePrefix);
+			auto u = fromUser(arg, formatPrefix, typePrefix);
 			args.push_back(get<1>(u));
 			params.push_back(make_pair(get<0>(u), get<2>(u)));
 		}
@@ -648,14 +727,8 @@ int main(int argc, char** argv)
 			string encoded;
 			for (int i = cin.get(); i != -1; i = cin.get())
 				encoded.push_back((char)i);
-			cout << m.decode(fromHex(encoded));
+			cout << m.decode(fromHex(encoded), outputIndex, prefs);
 		}
-
-		// TODO: read abi to determine output format.
-		(void)encoding;
-		(void)clearZeroes;
-		(void)clearNulls;
-		(void)outputIndex;
 	}
 
 	return 0;
diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt
index 49c847a16..c81c86222 100644
--- a/alethzero/CMakeLists.txt
+++ b/alethzero/CMakeLists.txt
@@ -19,6 +19,7 @@ find_package (Qt5WebEngine QUIET)
 find_package (Qt5WebEngineWidgets QUIET)
 
 qt5_wrap_ui(ui_Main.h Main.ui)
+qt5_wrap_ui(ui_Connect.h Connect.ui)
 qt5_wrap_ui(ui_Debugger.h Debugger.ui)
 qt5_wrap_ui(ui_Transact.h Transact.ui)
 
@@ -32,8 +33,8 @@ endif ()
 	
 # eth_add_executable is defined in cmake/EthExecutableHelper.cmake
 eth_add_executable(${EXECUTABLE} 
-	ICON alethzero 
-	UI_RESOURCES alethzero.icns Main.ui Debugger.ui Transact.ui
+	ICON alethzero
+	UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui
 	WIN_RESOURCES alethzero.rc
 )
 
diff --git a/alethzero/Connect.cpp b/alethzero/Connect.cpp
new file mode 100644
index 000000000..32fa74f38
--- /dev/null
+++ b/alethzero/Connect.cpp
@@ -0,0 +1,63 @@
+/*
+	This file is part of cpp-ethereum.
+
+	cpp-ethereum is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	cpp-ethereum is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file Connect.cpp
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2015
+ */
+
+#include "Connect.h"
+
+#include <libp2p/Host.h>
+#include "ui_Connect.h"
+
+Connect::Connect(QWidget *parent) :
+	QDialog(parent),
+	ui(new Ui::Connect)
+{
+	ui->setupUi(this);
+}
+
+Connect::~Connect()
+{
+	delete ui;
+}
+
+void Connect::setEnvironment(QStringList const& _nodes)
+{
+	ui->host->addItems(_nodes);
+}
+
+void Connect::reset()
+{
+	ui->nodeId->clear();
+	ui->required->setChecked(false);
+}
+
+QString Connect::host()
+{
+	return ui->host->currentText();
+}
+
+QString Connect::nodeId()
+{
+	return ui->nodeId->text();
+}
+
+bool Connect::required()
+{
+	return ui->required->isChecked();
+}
diff --git a/alethzero/Connect.h b/alethzero/Connect.h
new file mode 100644
index 000000000..8209a78af
--- /dev/null
+++ b/alethzero/Connect.h
@@ -0,0 +1,55 @@
+/*
+	This file is part of cpp-ethereum.
+
+	cpp-ethereum is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	cpp-ethereum is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file Connect.h
+ * @author Alex Leverington <nessence@gmail.com>
+ * @date 2015
+ */
+
+#pragma once
+
+#include <QDialog>
+#include <QList>
+
+namespace Ui { class Connect; }
+namespace dev { namespace p2p { class Host; } }
+
+class Connect : public QDialog
+{
+	Q_OBJECT
+
+public:
+	explicit Connect(QWidget* _parent = 0);
+	~Connect();
+
+	/// Populate host chooser with default host entries.
+	void setEnvironment(QStringList const& _nodes);
+
+	/// Clear dialogue inputs.
+	void reset();
+
+	/// @returns the host string, as chosen or entered by the user. Assumed to be "hostOrIP:port" (:port is optional).
+	QString host();
+	
+	/// @returns the identity of the node, as entered by the user. Assumed to be a 64-character hex string.
+	QString nodeId();
+	
+	/// @returns true if Required is checked by the user, indicating that the host is a required Peer.
+	bool required();
+
+private:
+	Ui::Connect* ui;
+};
diff --git a/alethzero/Connect.ui b/alethzero/Connect.ui
new file mode 100644
index 000000000..9a0522e5f
--- /dev/null
+++ b/alethzero/Connect.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Connect</class>
+ <widget class="QDialog" name="Connect">
+  <property name="windowModality">
+   <enum>Qt::WindowModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>343</width>
+    <height>178</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>343</width>
+    <height>178</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Connect to Peer</string>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QFormLayout" name="formLayout_2">
+   <item row="1" column="0">
+    <layout class="QFormLayout" name="formLayout">
+     <item row="1" column="0" colspan="2">
+      <widget class="QComboBox" name="host">
+       <property name="minimumSize">
+        <size>
+         <width>311</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="editable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0" colspan="2">
+      <widget class="QLineEdit" name="nodeId">
+       <property name="placeholderText">
+        <string>Node Id</string>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="0" colspan="2">
+      <widget class="QCheckBox" name="required">
+       <property name="text">
+        <string>Required (Always Connect to this Peer)</string>
+       </property>
+       <property name="tristate">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item row="4" column="0" colspan="2">
+      <widget class="QDialogButtonBox" name="buttonBox">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="standardButtons">
+        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="formLabel">
+     <property name="text">
+      <string>Enter a peer to which a connection may be made:</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>Connect</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>Connect</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/alethzero/Debugger.cpp b/alethzero/Debugger.cpp
index 93d6b1f6a..371630456 100644
--- a/alethzero/Debugger.cpp
+++ b/alethzero/Debugger.cpp
@@ -67,7 +67,8 @@ void Debugger::populate(dev::eth::Executive& _executive, dev::eth::Transaction c
 bool DebugSession::populate(dev::eth::Executive& _executive, dev::eth::Transaction const& _transaction)
 {
 	try {
-		if (_executive.setup(_transaction))
+		_executive.initialize(_transaction);
+		if (_executive.execute())
 			return false;
 	}
 	catch (...)
diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index 34f240fbf..b59c9ce2d 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -118,7 +118,7 @@
      <x>0</x>
      <y>0</y>
      <width>1617</width>
-     <height>24</height>
+     <height>22</height>
     </rect>
    </property>
    <widget class="QMenu" name="menu_File">
@@ -134,8 +134,7 @@
     <addaction name="go"/>
     <addaction name="separator"/>
     <addaction name="upnp"/>
-    <addaction name="usePast"/>
-    <addaction name="localNetworking"/>
+    <addaction name="dropPeers"/>
     <addaction name="net"/>
     <addaction name="connect"/>
    </widget>
@@ -284,7 +283,27 @@
        </widget>
        <widget class="QWidget" name="layoutWidget">
         <layout class="QGridLayout" name="gridLayout_2">
-         <item row="1" column="2">
+         <item row="3" column="0">
+          <widget class="QLabel" name="label">
+           <property name="text">
+            <string>&amp;Listen on</string>
+           </property>
+           <property name="buddy">
+            <cstring>port</cstring>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1" colspan="2">
+          <widget class="QSpinBox" name="idealPeers">
+           <property name="minimum">
+            <number>1</number>
+           </property>
+           <property name="value">
+            <number>5</number>
+           </property>
+          </widget>
+         </item>
+         <item row="3" column="2">
           <widget class="QSpinBox" name="port">
            <property name="minimum">
             <number>1024</number>
@@ -297,8 +316,8 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="1">
-          <widget class="QLineEdit" name="forceAddress">
+         <item row="3" column="1">
+          <widget class="QLineEdit" name="listenIP">
            <property name="inputMask">
             <string/>
            </property>
@@ -310,16 +329,6 @@
            </property>
           </widget>
          </item>
-         <item row="1" column="0">
-          <widget class="QLabel" name="label">
-           <property name="text">
-            <string>&amp;Listen on</string>
-           </property>
-           <property name="buddy">
-            <cstring>port</cstring>
-           </property>
-          </widget>
-         </item>
          <item row="0" column="0">
           <widget class="QLabel" name="label_3">
            <property name="text">
@@ -330,20 +339,17 @@
            </property>
           </widget>
          </item>
-         <item row="0" column="1" colspan="2">
-          <widget class="QSpinBox" name="idealPeers">
-           <property name="minimum">
-            <number>1</number>
-           </property>
-           <property name="value">
-            <number>5</number>
+         <item row="5" column="1">
+          <widget class="QLineEdit" name="forcePublicIP">
+           <property name="placeholderText">
+            <string>Automatic</string>
            </property>
           </widget>
          </item>
-         <item row="2" column="1" colspan="2">
-          <widget class="QLineEdit" name="clientName">
-           <property name="placeholderText">
-            <string>Anonymous</string>
+         <item row="5" column="0">
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Public IP</string>
            </property>
           </widget>
          </item>
@@ -357,6 +363,13 @@
            </property>
           </widget>
          </item>
+         <item row="2" column="1">
+          <widget class="QLineEdit" name="clientName">
+           <property name="placeholderText">
+            <string>Anonymous</string>
+           </property>
+          </widget>
+         </item>
         </layout>
        </widget>
       </widget>
@@ -1443,12 +1456,12 @@ font-size: 14pt</string>
     <string>Show &amp;Anonymous Accounts</string>
    </property>
   </action>
-  <action name="usePast">
+  <action name="dropPeers">
    <property name="checkable">
     <bool>true</bool>
    </property>
    <property name="text">
-    <string>Use &amp;Past Peers</string>
+    <string>&amp;Drop Past Peers</string>
    </property>
   </action>
   <action name="loadJS">
@@ -1694,9 +1707,8 @@ font-size: 14pt</string>
   <tabstop>tabWidget</tabstop>
   <tabstop>urlEdit</tabstop>
   <tabstop>idealPeers</tabstop>
-  <tabstop>forceAddress</tabstop>
+  <tabstop>listenIP</tabstop>
   <tabstop>port</tabstop>
-  <tabstop>clientName</tabstop>
   <tabstop>transactionQueue</tabstop>
   <tabstop>pendingInfo</tabstop>
   <tabstop>blockChainFilter</tabstop>
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 36b6176f4..0de7e2cb8 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -28,6 +28,7 @@
 //pragma GCC diagnostic ignored "-Werror=pedantic"
 #include <QtNetwork/QNetworkReply>
 #include <QtWidgets/QFileDialog>
+#include <QtWidgets/QDialog>
 #include <QtWidgets/QMessageBox>
 #include <QtWidgets/QInputDialog>
 #include <QtWebEngine/QtWebEngine>
@@ -141,7 +142,7 @@ Main::Main(QWidget *parent) :
 #endif
 
 #if ETH_DEBUG
-	m_servers.append("localhost:30300");
+	m_servers.append("127.0.0.1:30300");
 #endif
 	m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
 
@@ -251,7 +252,30 @@ void Main::addNewId(QString _ids)
 
 NetworkPreferences Main::netPrefs() const
 {
-	return NetworkPreferences(ui->port->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), ui->localNetworking->isChecked());
+	auto listenIP = ui->listenIP->text().toStdString();
+	try
+	{
+		listenIP = bi::address::from_string(listenIP).to_string();
+	}
+	catch (...)
+	{
+		listenIP.clear();
+	}
+	
+	auto publicIP = ui->forcePublicIP->text().toStdString();
+	try
+	{
+		publicIP = bi::address::from_string(publicIP).to_string();
+	}
+	catch (...)
+	{
+		publicIP.clear();
+	}
+	
+	if (isPublicAddress(publicIP))
+		return NetworkPreferences(publicIP, listenIP, ui->port->value(), ui->upnp->isChecked());
+	else
+		return NetworkPreferences(listenIP, ui->port->value(), ui->upnp->isChecked());
 }
 
 void Main::onKeysChanged()
@@ -675,9 +699,7 @@ void Main::writeSettings()
 	}
 
 	s.setValue("upnp", ui->upnp->isChecked());
-	s.setValue("forceAddress", ui->forceAddress->text());
-	s.setValue("usePast", ui->usePast->isChecked());
-	s.setValue("localNetworking", ui->localNetworking->isChecked());
+	s.setValue("forceAddress", ui->forcePublicIP->text());
 	s.setValue("forceMining", ui->forceMining->isChecked());
 	s.setValue("paranoia", ui->paranoia->isChecked());
 	s.setValue("natSpec", ui->natSpec->isChecked());
@@ -685,6 +707,7 @@ void Main::writeSettings()
 	s.setValue("showAllAccounts", ui->showAllAccounts->isChecked());
 	s.setValue("clientName", ui->clientName->text());
 	s.setValue("idealPeers", ui->idealPeers->value());
+	s.setValue("listenIP", ui->listenIP->text());
 	s.setValue("port", ui->port->value());
 	s.setValue("url", ui->urlEdit->text());
 	s.setValue("privateChain", m_privateChain);
@@ -744,9 +767,8 @@ void Main::readSettings(bool _skipGeometry)
 	}
 
 	ui->upnp->setChecked(s.value("upnp", true).toBool());
-	ui->forceAddress->setText(s.value("forceAddress", "").toString());
-	ui->usePast->setChecked(s.value("usePast", true).toBool());
-	ui->localNetworking->setChecked(s.value("localNetworking", true).toBool());
+	ui->forcePublicIP->setText(s.value("forceAddress", "").toString());
+	ui->dropPeers->setChecked(false);
 	ui->forceMining->setChecked(s.value("forceMining", false).toBool());
 	on_forceMining_triggered();
 	ui->paranoia->setChecked(s.value("paranoia", false).toBool());
@@ -757,6 +779,7 @@ void Main::readSettings(bool _skipGeometry)
 	if (ui->clientName->text().isEmpty())
 		ui->clientName->setText(QInputDialog::getText(nullptr, "Enter identity", "Enter a name that will identify you on the peer network"));
 	ui->idealPeers->setValue(s.value("idealPeers", ui->idealPeers->value()).toInt());
+	ui->listenIP->setText(s.value("listenIP", "").toString());
 	ui->port->setValue(s.value("port", ui->port->value()).toInt());
 	ui->nameReg->setText(s.value("nameReg", "").toString());
 	m_privateChain = s.value("privateChain", "").toString();
@@ -1099,7 +1122,7 @@ void Main::refreshBlockChain()
 				blocks.insert(bc.numberHash(b));
 		}
 		else if (f.toLongLong() <= bc.number())
-			blocks.insert(bc.numberHash(u256(f.toLongLong())));
+			blocks.insert(bc.numberHash((unsigned)f.toLongLong()));
 		else if (f.size() == 40)
 		{
 			Address h(f.toStdString());
@@ -1362,7 +1385,7 @@ void Main::on_transactionQueue_currentItemChanged()
 		if (!!receipt.bloom())
 			s << "<div>Log Bloom: " << receipt.bloom() << "</div>";
 		else
-			s << "<div>Log Bloom: <i>Uneventful</i></div>";
+			s << "<div>Log Bloom: <b><i>Uneventful</i></b></div>";
 		auto r = receipt.rlp();
 		s << "<div>Receipt: " << toString(RLP(r)) << "</div>";
 		s << "<div>Receipt-Hex: " Span(Mono) << toHex(receipt.rlp()) << "</span></div>";
@@ -1461,7 +1484,7 @@ void Main::on_blocks_currentItemChanged()
 			if (!!info.logBloom)
 				s << "<div>Log Bloom: " << info.logBloom << "</div>";
 			else
-				s << "<div>Log Bloom: <i>Uneventful</i></div>";
+				s << "<div>Log Bloom: <b><i>Uneventful</i></b></div>";
 			s << "<div>Transactions: <b>" << block[1].itemCount() << "</b> @<b>" << info.transactionsRoot << "</b>" << "</div>";
 			s << "<div>Uncles: <b>" << block[2].itemCount() << "</b> @<b>" << info.sha3Uncles << "</b>" << "</div>";
 			for (auto u: block[2])
@@ -1743,11 +1766,8 @@ void Main::on_net_triggered()
 	if (ui->net->isChecked())
 	{
 		web3()->setIdealPeerCount(ui->idealPeers->value());
-		web3()->setNetworkPreferences(netPrefs());
+		web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked());
 		ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256());
-		// TODO: p2p
-//		if (m_networkConfig.size()/* && ui->usePast->isChecked()*/)
-//			web3()->restoreNetwork(bytesConstRef((byte*)m_networkConfig.data(), m_networkConfig.size()));
 		web3()->startNetwork();
 		ui->downloadView->setDownloadMan(ethereum()->downloadMan());
 	}
@@ -1765,13 +1785,25 @@ void Main::on_connect_triggered()
 		ui->net->setChecked(true);
 		on_net_triggered();
 	}
-	bool ok = false;
-	QString s = QInputDialog::getItem(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", m_servers, m_servers.count() ? rand() % m_servers.count() : 0, true, &ok);
-	if (ok && s.contains(":"))
+	
+	m_connect.setEnvironment(m_servers);
+	if (m_connect.exec() == QDialog::Accepted)
 	{
-		string host = s.section(":", 0, 0).toStdString();
-		unsigned short port = s.section(":", 1).toInt();
-		web3()->connect(host, port);
+		bool required = m_connect.required();
+		string host(m_connect.host().toStdString());
+		NodeId nodeID;
+		try
+		{
+			nodeID = NodeId(fromHex(m_connect.nodeId().toStdString()));
+		}
+		catch (BadHexCharacter&) {}
+		
+		m_connect.reset();
+		
+		if (required)
+			web3()->requirePeer(nodeID, host);
+		else
+			web3()->addNode(nodeID, host);
 	}
 }
 
@@ -1882,7 +1914,7 @@ void Main::on_go_triggered()
 		ui->net->setChecked(true);
 		on_net_triggered();
 	}
-	web3()->connect(Host::pocHost());
+	web3()->addNode(p2p::NodeId(), Host::pocHost());
 }
 
 QString Main::prettyU256(dev::u256 _n) const
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index ba89b455a..fccbc855d 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -40,6 +40,7 @@
 #include "Context.h"
 #include "Transact.h"
 #include "NatspecHandler.h"
+#include "Connect.h"
 
 namespace Ui {
 class Main;
@@ -256,4 +257,6 @@ private:
 	std::unique_ptr<DappHost> m_dappHost;
 	DappLoader* m_dappLoader;
 	QWebEnginePage* m_webPage;
+	
+	Connect m_connect;
 };
diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp
index 534f18a69..6f52548c7 100644
--- a/alethzero/Transact.cpp
+++ b/alethzero/Transact.cpp
@@ -316,7 +316,7 @@ void Transact::rejigData()
 		return;
 	}
 	else
-		gasNeeded = min<qint64>((qint64)ethereum()->gasLimitRemaining(), (qint64)((b - value()) / gasPrice()));
+		gasNeeded = (qint64)min<bigint>(ethereum()->gasLimitRemaining(), ((b - value()) / gasPrice()));
 
 	// Dry-run execution to determine gas requirement and any execution errors
 	Address to;
@@ -326,7 +326,7 @@ void Transact::rejigData()
 	else
 	{
 		to = m_context->fromString(ui->destination->currentText());
-		er = ethereum()->call(s, value(), to, m_data, ethereum()->gasLimitRemaining(), gasPrice());
+		er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
 	}
 	gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
 	htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(gasNeeded).arg(baseGas).arg(gasNeeded - baseGas).arg((qint64)er.gasRefunded) + htmlInfo;
diff --git a/eth/main.cpp b/eth/main.cpp
index e0cf76193..2a065cc8c 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -121,8 +121,9 @@ void help()
 		<< "	--json-rpc-port	 Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
 #endif
 		<< "    -K,--kill-blockchain  First kill the blockchain." << endl
-		<< "    -l,--listen <port>  Listen on the given port for incoming connected (default: 30303)." << endl
-		<< "    -L,--local-networking Use peers whose addresses are local." << endl
+		<< "       --listen-ip <port>  Listen on the given port for incoming connections (default: 30303)." << endl
+		<< "    -l,--listen <ip>  Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
+		<< "    -u,--public-ip <ip>  Force public ip to given (default: auto)." << endl
 		<< "    -m,--mining <on/off/number>  Enable mining, optionally for a specified number of blocks (Default: off)" << endl
 		<< "    -n,--upnp <on/off>  Use upnp for NAT (default: on)." << endl
 		<< "    -o,--mode <full/peer>  Start a full node or a peer node (Default: full)." << endl
@@ -131,7 +132,6 @@ void help()
 		<< "    -r,--remote <host>  Connect to remote host (default: none)." << endl
 		<< "    -s,--secret <secretkeyhex>  Set the secret key for use with send command (default: auto)." << endl
 		<< "    -t,--miners <number>  Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl
-		<< "    -u,--public-ip <ip>  Force public ip to given (default; auto)." << endl
 		<< "    -v,--verbosity <0 - 9>  Set the log verbosity from 0 to 9 (Default: 8)." << endl
 		<< "    -x,--peers <number>  Attempt to connect to given number of peers (Default: 5)." << endl
 		<< "    -V,--version  Show the version and exit." << endl
@@ -199,7 +199,9 @@ enum class NodeMode
 
 int main(int argc, char** argv)
 {
+	string listenIP;
 	unsigned short listenPort = 30303;
+	string publicIP;
 	string remoteHost;
 	unsigned short remotePort = 30303;
 	string dbPath;
@@ -211,10 +213,8 @@ int main(int argc, char** argv)
 #if ETH_JSONRPC
 	int jsonrpc = -1;
 #endif
-	string publicIP;
 	bool bootstrap = false;
 	bool upnp = true;
-	bool useLocal = false;
 	bool forceMining = false;
 	bool killChain = false;
 	bool jit = false;
@@ -250,7 +250,9 @@ int main(int argc, char** argv)
 	for (int i = 1; i < argc; ++i)
 	{
 		string arg = argv[i];
-		if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
+		if (arg == "--listen-ip" && i + 1 < argc)
+			listenIP = argv[++i];
+		else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
 			listenPort = (short)atoi(argv[++i]);
 		else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
 			publicIP = argv[++i];
@@ -271,8 +273,6 @@ int main(int argc, char** argv)
 				return -1;
 			}
 		}
-		else if (arg == "-L" || arg == "--local-networking")
-			useLocal = true;
 		else if (arg == "-K" || arg == "--kill-blockchain")
 			killChain = true;
 		else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
@@ -421,7 +421,7 @@ int main(int argc, char** argv)
 
 	StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
 	VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
-	NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal);
+	auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
 	auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp");
 	std::string clientImplString = "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
 	dev::WebThreeDirect web3(
@@ -449,9 +449,9 @@ int main(int argc, char** argv)
 	web3.startNetwork();
 
 	if (bootstrap)
-		web3.connect(Host::pocHost());
+		web3.addNode(p2p::NodeId(), Host::pocHost());
 	if (remoteHost.size())
-		web3.connect(remoteHost, remotePort);
+		web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort));
 
 #if ETH_JSONRPC
 	shared_ptr<WebThreeStubServer> jsonrpcServer;
@@ -511,7 +511,7 @@ int main(int argc, char** argv)
 				string addr;
 				unsigned port;
 				iss >> addr >> port;
-				web3.connect(addr, (short)port);
+				web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
 			}
 			else if (cmd == "netstop")
 			{
@@ -835,11 +835,8 @@ int main(int argc, char** argv)
 					Executive e(state, c->blockChain(), 0);
 					Transaction t = state.pending()[index];
 					state = state.fromPending(index);
-					bytes r = t.rlp();
 					try
 					{
-						e.setup(&r);
-
 						OnOpFunc oof;
 						if (format == "pretty")
 							oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, dev::eth::VM* vvm, dev::eth::ExtVMFace const* vextVM)
@@ -872,7 +869,9 @@ int main(int argc, char** argv)
 										f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
 								f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl;
 							};
-						e.go(oof);
+						e.initialize(t);
+						if (!e.execute())
+							e.go(oof);
 						e.finalize();
 					}
 					catch(Exception const& _e)
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 1c7a4cd61..6468e250f 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -42,14 +42,15 @@ enum class WhenError
 };
 
 /// Convert a series of bytes to the corresponding string of hex duplets.
-/// @param _w specifies the width of each of the elements. Defaults to two - enough to represent a byte.
+/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte.
 /// @example toHex("A\x69") == "4169"
 template <class _T>
 std::string toHex(_T const& _data, int _w = 2)
 {
 	std::ostringstream ret;
+	unsigned ii = 0;
 	for (auto i: _data)
-		ret << std::hex << std::setfill('0') << std::setw(_w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
+		ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
 	return ret.str();
 }
 
@@ -74,6 +75,13 @@ inline std::string asString(bytes const& _b)
 	return std::string((char const*)_b.data(), (char const*)(_b.data() + _b.size()));
 }
 
+/// Converts byte array ref to a string containing the same (binary) data. Unless
+/// the byte array happens to contain ASCII data, this won't be printable.
+inline std::string asString(bytesConstRef _b)
+{
+	return std::string((char const*)_b.data(), (char const*)(_b.data() + _b.size()));
+}
+
 /// Converts a string to a byte array containing the string's (byte) data.
 inline bytes asBytes(std::string const& _b)
 {
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index f5469ada8..456365299 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -141,6 +141,7 @@ public:
 		return ret;
 	}
 
+	/// @returns a random valued object.
 	static FixedHash random() { return random(s_fixedHashEngine); }
 
 	/// A generic std::hash compatible function object.
diff --git a/libethcore/Ethasher.cpp b/libethcore/Ethasher.cpp
index 1e6f0acef..79a2fdea3 100644
--- a/libethcore/Ethasher.cpp
+++ b/libethcore/Ethasher.cpp
@@ -119,9 +119,21 @@ bool Ethasher::verify(BlockInfo const& _header)
 		boundary.data());
 
 #if ETH_DEBUG
-	// should be equivalent to:
 	auto result = eval(_header);
-	assert((result.mixHash == _header.mixHash && result.value <= boundary) == ret);
+	if ((result.value <= boundary && result.mixHash == _header.mixHash) != ret)
+	{
+		cwarn << "Assertion failure coming: evaluated result gives different outcome to ethash_quick_check_difficulty";
+		cwarn << "headerHash:" << _header.headerHash(WithoutNonce);
+		cwarn << "nonce:" << _header.nonce;
+		cwarn << "mixHash:" << _header.mixHash;
+		cwarn << "difficulty:" << _header.difficulty;
+		cwarn << "boundary:" << boundary;
+		cwarn << "result.value:" << result.value;
+		cwarn << "result.mixHash:" << result.mixHash;
+	}
+	assert((result.value <= boundary) == ret);
+	if (result.value <= boundary)
+		assert(result.mixHash == _header.mixHash);
 #endif
 
 	return ret;
diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h
index df6a08817..db2718fc4 100644
--- a/libethcore/Exceptions.h
+++ b/libethcore/Exceptions.h
@@ -38,6 +38,7 @@ using errinfo_difficulty = boost::error_info<struct tag_difficulty, u256>;
 using BadFieldError = boost::tuple<errinfo_field, errinfo_data>;
 
 struct DatabaseAlreadyOpen: virtual dev::Exception {};
+struct NotEnoughAvailableSpace: virtual dev::Exception {};
 struct NotEnoughCash: virtual dev::Exception {};
 struct GasPriceTooLow: virtual dev::Exception {};
 struct BlockGasLimitReached: virtual dev::Exception {};
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index f80680f38..508531f9d 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -63,7 +63,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
 	return _out;
 }
 
-ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)
+ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
 {
 #if ALL_COMPILERS_ARE_CPP11_COMPLIANT
 	static thread_local h256 h = _h ^ sha3(h256(u256(_sub)));
@@ -131,10 +131,19 @@ void BlockChain::open(std::string _path, bool _killExisting)
 	o.create_if_missing = true;
 	ldb::DB::Open(o, _path + "/blocks", &m_blocksDB);
 	ldb::DB::Open(o, _path + "/details", &m_extrasDB);
-	if (!m_blocksDB)
-		BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
-	if (!m_extrasDB)
-		BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
+	if (!m_blocksDB || !m_extrasDB)
+	{
+		if (boost::filesystem::space(_path + "/blocks").available < 1024)
+		{
+			cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing.";
+			BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace());
+		}
+		else
+		{
+			cwarn << "Database already open. You appear to have another instance of ethereum running. Bailing.";
+			BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
+		}
+	}
 
 	if (!details(m_genesisHash))
 	{
@@ -184,6 +193,19 @@ inline string toString(h256s const& _bs)
 	return out.str();
 }
 
+LastHashes BlockChain::lastHashes(unsigned _n) const
+{
+	Guard l(x_lastLastHashes);
+	if (m_lastLastHashesNumber != _n || m_lastLastHashes.empty())
+	{
+		m_lastLastHashes.resize(256);
+		for (unsigned i = 0; i < 256; ++i)
+			m_lastLastHashes[i] = _n >= i ? numberHash(_n - i) : h256();
+		m_lastLastHashesNumber = _n;
+	}
+	return m_lastLastHashes;
+}
+
 h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
 {
 	_bq.tick(*this);
@@ -412,6 +434,9 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
 			WriteGuard l(x_lastBlockHash);
 			m_lastBlockHash = newHash;
 		}
+
+		noteCanonChanged();
+
 		m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
 		clog(BlockChainNote) << "   Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret);
 		StructuredLogger::chainNewHead(
@@ -428,7 +453,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
 	return ret;
 }
 
-h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, bool _post) const
+h256s BlockChain::treeRoute(h256 const& _from, h256 const& _to, h256* o_common, bool _pre, bool _post) const
 {
 	//	cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
 	if (!_from || !_to)
@@ -438,38 +463,40 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
 	unsigned fn = details(_from).number;
 	unsigned tn = details(_to).number;
 	//	cdebug << "treeRoute" << fn << "..." << tn;
+	h256 from = _from;
 	while (fn > tn)
 	{
 		if (_pre)
-			ret.push_back(_from);
-		_from = details(_from).parent;
+			ret.push_back(from);
+		from = details(from).parent;
 		fn--;
 		//		cdebug << "from:" << fn << _from.abridged();
 	}
+	h256 to = _to;
 	while (fn < tn)
 	{
 		if (_post)
-			back.push_back(_to);
-		_to = details(_to).parent;
+			back.push_back(to);
+		to = details(to).parent;
 		tn--;
 		//		cdebug << "to:" << tn << _to.abridged();
 	}
-	while (_from != _to)
+	while (from != to)
 	{
-		assert(_from);
-		assert(_to);
-		_from = details(_from).parent;
-		_to = details(_to).parent;
+		assert(from);
+		assert(to);
+		from = details(from).parent;
+		to = details(to).parent;
 		if (_pre)
-			ret.push_back(_from);
+			ret.push_back(from);
 		if (_post)
-			back.push_back(_to);
+			back.push_back(to);
 		fn--;
 		tn--;
 		//		cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
 	}
 	if (o_common)
-		*o_common = _from;
+		*o_common = from;
 	ret.reserve(ret.size() + back.size());
 	for (auto it = back.cbegin(); it != back.cend(); ++it)
 		ret.push_back(*it);
@@ -677,7 +704,7 @@ vector<unsigned> BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie
 	return ret;
 }
 
-h256Set BlockChain::allUnclesFrom(h256 _parent) const
+h256Set BlockChain::allUnclesFrom(h256 const& _parent) const
 {
 	// Get all uncles cited given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
 	h256Set ret;
@@ -692,7 +719,7 @@ h256Set BlockChain::allUnclesFrom(h256 _parent) const
 	return ret;
 }
 
-bool BlockChain::isKnown(h256 _hash) const
+bool BlockChain::isKnown(h256 const& _hash) const
 {
 	if (_hash == m_genesisHash)
 		return true;
@@ -706,7 +733,7 @@ bool BlockChain::isKnown(h256 _hash) const
 	return !!d.size();
 }
 
-bytes BlockChain::block(h256 _hash) const
+bytes BlockChain::block(h256 const& _hash) const
 {
 	if (_hash == m_genesisHash)
 		return m_genesisBlock;
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index 235a39267..03c0fdcfd 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -30,9 +30,10 @@
 #include <chrono>
 #include <libdevcore/Log.h>
 #include <libdevcore/Exceptions.h>
+#include <libdevcore/Guards.h>
 #include <libethcore/Common.h>
 #include <libethcore/BlockInfo.h>
-#include <libdevcore/Guards.h>
+#include <libevm/ExtVMFace.h>
 #include "BlockDetails.h"
 #include "Account.h"
 #include "Transaction.h"
@@ -61,7 +62,7 @@ struct BlockChainNote: public LogChannel { static const char* name() { return "=
 // TODO: Move all this Genesis stuff into Genesis.h/.cpp
 std::map<Address, Account> const& genesisState();
 
-ldb::Slice toSlice(h256 _h, unsigned _sub = 0);
+ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
 
 using BlocksHash = std::map<h256, bytes>;
 using TransactionHashes = h256s;
@@ -105,37 +106,42 @@ public:
 	h256s import(bytes const& _block, OverlayDB const& _stateDB);
 
 	/// Returns true if the given block is known (though not necessarily a part of the canon chain).
-	bool isKnown(h256 _hash) const;
+	bool isKnown(h256 const& _hash) const;
 
 	/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
-	BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); }
+	BlockInfo info(h256 const& _hash) const { return BlockInfo(block(_hash)); }
 	BlockInfo info() const { return BlockInfo(block()); }
 
 	/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
-	bytes block(h256 _hash) const;
+	bytes block(h256 const& _hash) const;
 	bytes block() const { return block(currentHash()); }
 
 	/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
-	BlockDetails details(h256 _hash) const { return queryExtras<BlockDetails, ExtraDetails>(_hash, m_details, x_details, NullBlockDetails); }
+	BlockDetails details(h256 const& _hash) const { return queryExtras<BlockDetails, ExtraDetails>(_hash, m_details, x_details, NullBlockDetails); }
 	BlockDetails details() const { return details(currentHash()); }
 
 	/// Get the transactions' log blooms of a block (or the most recent mined if none given). Thread-safe.
-	BlockLogBlooms logBlooms(h256 _hash) const { return queryExtras<BlockLogBlooms, ExtraLogBlooms>(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
+	BlockLogBlooms logBlooms(h256 const& _hash) const { return queryExtras<BlockLogBlooms, ExtraLogBlooms>(_hash, m_logBlooms, x_logBlooms, NullBlockLogBlooms); }
 	BlockLogBlooms logBlooms() const { return logBlooms(currentHash()); }
 
 	/// Get the transactions' receipts of a block (or the most recent mined if none given). Thread-safe.
-	BlockReceipts receipts(h256 _hash) const { return queryExtras<BlockReceipts, ExtraReceipts>(_hash, m_receipts, x_receipts, NullBlockReceipts); }
+	BlockReceipts receipts(h256 const& _hash) const { return queryExtras<BlockReceipts, ExtraReceipts>(_hash, m_receipts, x_receipts, NullBlockReceipts); }
 	BlockReceipts receipts() const { return receipts(currentHash()); }
 
 	/// Get a list of transaction hashes for a given block. Thread-safe.
-	TransactionHashes transactionHashes(h256 _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[1]) ret.push_back(sha3(t.data())); return ret; }
+	TransactionHashes transactionHashes(h256 const& _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[1]) ret.push_back(sha3(t.data())); return ret; }
 	TransactionHashes transactionHashes() const { return transactionHashes(currentHash()); }
 
 	/// Get a list of uncle hashes for a given block. Thread-safe.
-	UncleHashes uncleHashes(h256 _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[2]) ret.push_back(sha3(t.data())); return ret; }
+	UncleHashes uncleHashes(h256 const& _hash) const { auto b = block(_hash); RLP rlp(b); h256s ret; for (auto t: rlp[2]) ret.push_back(sha3(t.data())); return ret; }
 	UncleHashes uncleHashes() const { return uncleHashes(currentHash()); }
 	
-	h256 numberHash(u256 _index) const { if (!_index) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(_index), m_blockHashes, x_blockHashes, NullBlockHash).value; }
+	/// Get the hash for a given block's number.
+	h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(u256(_i)), m_blockHashes, x_blockHashes, NullBlockHash).value; }
+
+	/// Get the last N hashes for a given block. (N is determined by the LastHashes type.)
+	LastHashes lastHashes() const { return lastHashes(number()); }
+	LastHashes lastHashes(unsigned _i) const;
 
 	/** Get the block blooms for a number of blocks. Thread-safe.
 	 * @returns the object pertaining to the blocks:
@@ -158,15 +164,15 @@ public:
 	std::vector<unsigned> withBlockBloom(LogBloom const& _b, unsigned _earliest, unsigned _latest, unsigned _topLevel, unsigned _index) const;
 
 	/// Get a transaction from its hash. Thread-safe.
-	bytes transaction(h256 _transactionHash) const { TransactionAddress ta = queryExtras<TransactionAddress, ExtraTransactionAddress>(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytes(); return transaction(ta.blockHash, ta.index); }
-	std::pair<h256, unsigned> transactionLocation(h256 _transactionHash) const { TransactionAddress ta = queryExtras<TransactionAddress, ExtraTransactionAddress>(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return std::pair<h256, unsigned>(h256(), 0); return std::make_pair(ta.blockHash, ta.index); }
+	bytes transaction(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras<TransactionAddress, ExtraTransactionAddress>(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return bytes(); return transaction(ta.blockHash, ta.index); }
+	std::pair<h256, unsigned> transactionLocation(h256 const& _transactionHash) const { TransactionAddress ta = queryExtras<TransactionAddress, ExtraTransactionAddress>(_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress); if (!ta) return std::pair<h256, unsigned>(h256(), 0); return std::make_pair(ta.blockHash, ta.index); }
 
 	/// Get a block's transaction (RLP format) for the given block hash (or the most recent mined if none given) & index. Thread-safe.
-	bytes transaction(h256 _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
+	bytes transaction(h256 const& _blockHash, unsigned _i) const { bytes b = block(_blockHash); return RLP(b)[1][_i].data().toBytes(); }
 	bytes transaction(unsigned _i) const { return transaction(currentHash(), _i); }
 
 	/// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
-	unsigned number(h256 _hash) const { return details(_hash).number; }
+	unsigned number(h256 const& _hash) const { return details(_hash).number; }
 	unsigned number() const { return number(currentHash()); }
 
 	/// Get a given block (RLP format). Thread-safe.
@@ -178,7 +184,7 @@ public:
 	/// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5).
 	/// @returns set including the header-hash of every parent (including @a _parent) up to and including generation +5
 	/// togther with all their quoted uncles.
-	h256Set allUnclesFrom(h256 _parent) const;
+	h256Set allUnclesFrom(h256 const& _parent) const;
 
 	/** @returns the hash of all blocks between @a _from and @a _to, all blocks are ordered first by a number of
 	 * blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent.
@@ -194,7 +200,7 @@ public:
 	 * treeRoute(1b, 2a) == { 1b, 1a, 2a }; // *o_common == g
 	 * @endcode
 	 */
-	h256s treeRoute(h256 _from, h256 _to, h256* o_common = nullptr, bool _pre = true, bool _post = true) const;
+	h256s treeRoute(h256 const& _from, h256 const& _to, h256* o_common = nullptr, bool _pre = true, bool _post = true) const;
 
 	struct Statistics
 	{
@@ -219,7 +225,7 @@ private:
 	void open(std::string _path, bool _killExisting = false);
 	void close();
 
-	template<class T, unsigned N> T queryExtras(h256 _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n) const
+	template<class T, unsigned N> T queryExtras(h256 const& _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n) const
 	{
 		{
 			ReadGuard l(_x);
@@ -268,6 +274,11 @@ private:
 	void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
 	std::chrono::system_clock::time_point m_lastCollection;
 
+	void noteCanonChanged() const { Guard l(x_lastLastHashes); m_lastLastHashes.clear(); }
+	mutable Mutex x_lastLastHashes;
+	mutable LastHashes m_lastLastHashes;
+	mutable unsigned m_lastLastHashesNumber = (unsigned)-1;
+
 	void updateStats() const;
 	mutable Statistics m_lastStats;
 
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 5fb30b8f0..1091bba58 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -110,7 +110,7 @@ public:
 private:
 	u256 m_weiPerRef;
 	u256 m_refsPerBlock;
-	u256 m_gasPerBlock = 1000000;
+	u256 m_gasPerBlock = 3141592;
 	std::array<u256, 9> m_octiles;
 };
 
diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp
index df30595b6..b45b9cf27 100644
--- a/libethereum/ClientBase.cpp
+++ b/libethereum/ClientBase.cpp
@@ -73,7 +73,7 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt
 		State temp = asOf(_blockNumber);
 		u256 n = temp.transactionsFrom(toAddress(_secret));
 		Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
-		ret = temp.execute(bc(), t.rlp(), Permanence::Reverted);
+		ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
 	}
 	catch (...)
 	{
@@ -92,7 +92,7 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
 		//	cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
 		
 		Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
-		ret = temp.execute(bc(), t.rlp(), Permanence::Reverted);
+		ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
 	}
 	catch (...)
 	{
diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp
index 7dfc51b47..5bc42540f 100644
--- a/libethereum/EthereumHost.cpp
+++ b/libethereum/EthereumHost.cpp
@@ -178,7 +178,7 @@ void EthereumHost::maintainTransactions()
 			for (auto const& i: m_tq.transactions())
 				if (ep->m_requireTransactions || (!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first)))
 				{
-					b += i.second;
+					b += i.second.rlp();
 					++n;
 					m_transactionsSent.insert(i.first);
 				}
diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp
index c574fa650..dfd526bef 100644
--- a/libethereum/Executive.cpp
+++ b/libethereum/Executive.cpp
@@ -35,7 +35,7 @@ using namespace dev::eth;
 
 Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
 	m_s(_s),
-	m_lastHashes(_s.getLastHashes(_bc, (unsigned)_s.info().number - 1)),
+	m_lastHashes(_bc.lastHashes((unsigned)_s.info().number - 1)),
 	m_depth(_level)
 {}
 
@@ -55,12 +55,33 @@ void Executive::accrueSubState(SubState& _parentContext)
 		_parentContext += m_ext->sub;
 }
 
-bool Executive::setup(bytesConstRef _rlp)
+void Executive::initialize(Transaction const& _transaction)
 {
-	// Entry point for a user-executed transaction.
+	m_t = _transaction;
+
+	// Avoid transactions that would take us beyond the block gas limit.
+	u256 startGasUsed = m_s.gasUsed();
+	if (startGasUsed + (bigint)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();
+		m_excepted = TransactionException::BlockGasLimitReached;
+		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
+	}
+
+	// Check gas cost is enough.
+	m_gasRequired = Interface::txGas(m_t.data());
+	if (m_t.gas() < m_gasRequired)
+	{
+		clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << m_gasRequired << " Got" << m_t.gas();
+		m_excepted = TransactionException::OutOfGas;
+		BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)m_gasRequired, (bigint)m_t.gas()));
+	}
+
+	// Avoid invalid transactions.
+	u256 nonceReq;
 	try
 	{
-		m_t = Transaction(_rlp, CheckSignature::Sender);
+		nonceReq = m_s.transactionsFrom(m_t.sender());
 	}
 	catch (...)
 	{
@@ -68,15 +89,6 @@ bool Executive::setup(bytesConstRef _rlp)
 		m_excepted = TransactionException::InvalidSignature;
 		throw;
 	}
-	return setup();
-}
-
-bool Executive::setup()
-{
-	// Entry point for a user-executed transaction.
-
-	// Avoid invalid transactions.
-	auto nonceReq = m_s.transactionsFrom(m_t.sender());
 	if (m_t.nonce() != nonceReq)
 	{
 		clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce();
@@ -84,46 +96,32 @@ bool Executive::setup()
 		BOOST_THROW_EXCEPTION(InvalidNonce() << RequirementError((bigint)nonceReq, (bigint)m_t.nonce()));
 	}
 
-	// Check gas cost is enough.
-	auto gasRequired = Interface::txGas(m_t.data());
-
-	if (m_t.gas() < gasRequired)
-	{
-		clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasRequired << " Got" << m_t.gas();
-		m_excepted = TransactionException::OutOfGas;
-		BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasRequired, (bigint)m_t.gas()));
-	}
-
-	bigint gasCost = (bigint)m_t.gas() * m_t.gasPrice();
-	bigint totalCost = m_t.value() + gasCost;
-
 	// Avoid unaffordable transactions.
-	if (m_s.balance(m_t.sender()) < totalCost)
+	m_gasCost = (bigint)m_t.gas() * m_t.gasPrice();
+	m_totalCost = m_t.value() + m_gasCost;
+	if (m_s.balance(m_t.sender()) < m_totalCost)
 	{
-		clog(StateDetail) << "Not enough cash: Require >" << totalCost << " Got" << m_s.balance(m_t.sender());
+		clog(StateDetail) << "Not enough cash: Require >" << m_totalCost << " Got" << m_s.balance(m_t.sender());
 		m_excepted = TransactionException::NotEnoughCash;
-		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError(totalCost, (bigint)m_s.balance(m_t.sender())));
+		BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError(m_totalCost, (bigint)m_s.balance(m_t.sender())));
 	}
+}
 
-	u256 startGasUsed = m_s.gasUsed();
-	if (startGasUsed + (bigint)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();
-		m_excepted = TransactionException::BlockGasLimitReached;
-		BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas()));
-	}
+bool Executive::execute()
+{
+	// Entry point for a user-executed transaction.
 
 	// Increment associated nonce for sender.
 	m_s.noteSending(m_t.sender());
 
 	// Pay...
-	clog(StateDetail) << "Paying" << formatBalance(u256(gasCost)) << "from sender for gas (" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")";
-	m_s.subBalance(m_t.sender(), gasCost);
+	clog(StateDetail) << "Paying" << formatBalance(u256(m_gasCost)) << "from sender for gas (" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")";
+	m_s.subBalance(m_t.sender(), m_gasCost);
 
 	if (m_t.isCreation())
-		return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasRequired, &m_t.data(), m_t.sender());
+		return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_gasRequired, &m_t.data(), m_t.sender());
 	else
-		return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasRequired, m_t.sender());
+		return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_gasRequired, m_t.sender());
 }
 
 bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress)
diff --git a/libethereum/Executive.h b/libethereum/Executive.h
index eb0c27ad2..3445ad407 100644
--- a/libethereum/Executive.h
+++ b/libethereum/Executive.h
@@ -41,10 +41,21 @@ struct VMTraceChannel: public LogChannel { static const char* name() { return "E
  * @brief Message-call/contract-creation executor; useful for executing transactions.
  *
  * Two ways of using this class - either as a transaction executive or a CALL/CREATE executive.
- * In the first use, after construction, begin with setup() and end with finalize(). Call go()
- * after setup() only if it returns false.
+ *
+ * In the first use, after construction, begin with initialize(), then execute() and end with finalize(). Call go()
+ * after execute() only if it returns false.
+ *
  * In the second use, after construction, begin with call() or create() and end with
  * accrueSubState(). Call go() after call()/create() only if it returns false.
+ *
+ * Example:
+ * @code
+ * Executive e(state, blockchain, 0);
+ * e.initialize(transaction);
+ * if (!e.execute())
+ *    e.go();
+ * e.finalize();
+ * @endcode
  */
 class Executive
 {
@@ -59,17 +70,17 @@ public:
 	Executive(Executive const&) = delete;
 	void operator=(Executive) = delete;
 
-	/// Set up the executive for evaluating a transaction. You must call finalize() following this.
-	/// @returns true iff go() must be called (and thus a VM execution in required).
-	bool setup(bytesConstRef _transaction);
-	/// Set up the executive for evaluating a transaction. You must call finalize() following this.
-	/// @returns true iff go() must be called (and thus a VM execution in required).
-	bool setup(Transaction const& _transaction) { m_t = _transaction; return setup(); }
-	/// Finalise a transaction previously set up with setup().
-	/// @warning Only valid after setup(), and possibly go().
+	/// Initializes the executive for evaluating a transaction. You must call finalize() at some point following this.
+	void initialize(bytesConstRef _transaction) { initialize(Transaction(_transaction, CheckSignature::None)); }
+	void initialize(Transaction const& _transaction);
+	/// Finalise a transaction previously set up with initialize().
+	/// @warning Only valid after initialize() and execute(), and possibly go().
 	void finalize();
-	/// @returns the transaction from setup().
-	/// @warning Only valid after setup().
+	/// Begins execution of a transaction. You must call finalize() following this.
+	/// @returns true if the transaction is done, false if go() must be called.
+	bool execute();
+	/// @returns the transaction from initialize().
+	/// @warning Only valid after initialize().
 	Transaction const& t() const { return m_t; }
 	/// @returns the log entries created by this operation.
 	/// @warning Only valid after finalise().
@@ -107,8 +118,6 @@ public:
 	ExecutionResult executionResult() const;
 
 private:
-	bool setup();
-
 	State& m_s;							///< The state to which this operation/transaction is applied.
 	LastHashes m_lastHashes;
 	std::shared_ptr<ExtVM> m_ext;		///< The VM externality object for the VM execution or null if no VM is required.
@@ -125,6 +134,10 @@ private:
 
 	Transaction m_t;					///< The original transaction. Set by setup().
 	LogEntries m_logs;					///< The log entries created by this transaction. Set by finalize().
+
+	bigint m_gasRequired;
+	bigint m_gasCost;
+	bigint m_totalCost;
 };
 
 }
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index 47fdb7250..529ddc093 100644
--- a/libethereum/Interface.h
+++ b/libethereum/Interface.h
@@ -71,11 +71,13 @@ public:
 	virtual void flushTransactions() = 0;
 
 	/// Makes the given call. Nothing is recorded into the state.
-	virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
+	virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
+	ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); }
 
 	/// Does the given creation. Nothing is recorded into the state.
 	/// @returns the pair of the Address of the created contract together with its code.
-	virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = 0) = 0;
+	virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0;
+	ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); }
 
 	// [STATE-QUERY API]
 
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 486abde12..378c60fa3 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -60,7 +60,18 @@ OverlayDB State::openDB(std::string _path, bool _killExisting)
 	ldb::DB* db = nullptr;
 	ldb::DB::Open(o, _path + "/state", &db);
 	if (!db)
-		BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
+	{
+		if (boost::filesystem::space(_path + "/state").available < 1024)
+		{
+			cwarn << "Not enough available space found on hard drive. Please free some up and then re-run. Bailing.";
+			BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace());
+		}
+		else
+		{
+			cwarn << "Database already open. You appear to have another instance of ethereum running. Bailing.";
+			BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
+		}
+	}
 
 	cnote << "Opened state DB.";
 	return OverlayDB(db);
@@ -388,8 +399,7 @@ bool State::cull(TransactionQueue& _tq) const
 		{
 			try
 			{
-				Transaction t(i.second, CheckSignature::Sender);
-				if (t.nonce() <= transactionsFrom(t.sender()))
+				if (i.second.nonce() <= transactionsFrom(i.second.sender()))
 				{
 					_tq.drop(i.first);
 					ret = true;
@@ -411,7 +421,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
 	TransactionReceipts ret;
 	auto ts = _tq.transactions();
 
-	auto lh = getLastHashes(_bc, _bc.number());
+	LastHashes lh;
 
 	for (int goodTxs = 1; goodTxs;)
 	{
@@ -421,12 +431,11 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
 			{
 				try
 				{
-					Transaction t(i.second, CheckSignature::Sender);
-					if (t.gasPrice() >= _gp.ask(*this))
+					if (i.second.gasPrice() >= _gp.ask(*this))
 					{
-						// don't have it yet! Execute it now.
-						uncommitToMine();
 	//					boost::timer t;
+						if (lh.empty())
+							lh = _bc.lastHashes();
 						execute(lh, i.second);
 						ret.push_back(m_receipts.back());
 						_tq.noteGood(i);
@@ -434,6 +443,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
 	//					cnote << "TX took:" << t.elapsed() * 1000;
 					}
 				}
+#if ETH_DEBUG
 				catch (InvalidNonce const& in)
 				{
 					bigint const* req = boost::get_error_info<errinfo_required>(in);
@@ -449,13 +459,19 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
 					else
 						_tq.setFuture(i);
 				}
+				catch (BlockGasLimitReached const& e)
+				{
+					_tq.setFuture(i);
+				}
+#endif
 				catch (Exception const& _e)
 				{
 					// Something else went wrong - drop it.
 					_tq.drop(i.first);
 					if (o_transactionQueueChanged)
 						*o_transactionQueueChanged = true;
-					cwarn << "Sync went wrong\n" << diagnostic_information(_e);
+					cnote << "Dropping invalid transaction:";
+					cnote << diagnostic_information(_e);
 				}
 				catch (std::exception const&)
 				{
@@ -463,6 +479,7 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
 					_tq.drop(i.first);
 					if (o_transactionQueueChanged)
 						*o_transactionQueueChanged = true;
+					cnote << "Transaction caused low-level exception :(";
 				}
 			}
 	}
@@ -498,7 +515,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
 	GenericTrieDB<MemoryDB> receiptsTrie(&rm);
 	receiptsTrie.init();
 
-	LastHashes lh = getLastHashes(_bc, (unsigned)m_previousBlock.number);
+	LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number);
 	RLP rlp(_block);
 
 	// All ok with the block generally. Play back the transactions now...
@@ -509,7 +526,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
 		k << i;
 
 		transactionsTrie.insert(&k.out(), tr.data());
-		execute(lh, tr.data());
+		execute(lh, Transaction(tr.data(), CheckSignature::Sender));
 
 		RLPStream receiptrlp;
 		m_receipts.back().streamRLP(receiptrlp);
@@ -1040,56 +1057,34 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
 	return true;
 }
 
-LastHashes State::getLastHashes(BlockChain const& _bc, unsigned _n) const
-{
-	LastHashes ret;
-	ret.resize(256);
-	if (eth::c_protocolVersion > 49)
-	{
-		ret[0] = _bc.numberHash(_n);
-		for (unsigned i = 1; i < 256; ++i)
-			ret[i] = ret[i - 1] ? _bc.details(ret[i - 1]).parent : h256();
-	}
-	return ret;
-}
-
-ExecutionResult State::execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p)
-{
-	return execute(getLastHashes(_bc, _bc.number()), &_rlp, _p);
-}
-
-ExecutionResult State::execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p)
+ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Permanence _p)
 {
-	return execute(getLastHashes(_bc, _bc.number()), _rlp, _p);
-}
-
-// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + OverlayDB; allow overlay copying for rewind operations.
-ExecutionResult State::execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p)
-{
-#ifndef ETH_RELEASE
-	commit();	// get an updated hash
-#endif
-
+#if ETH_PARANOIA
 	paranoia("start of execution.", true);
-
 	State old(*this);
-#if ETH_PARANOIA
 	auto h = rootHash();
 #endif
 
+	// Create and initialize the executive. This will throw fairly cheaply and quickly if the
+	// transaction is bad in any way.
 	Executive e(*this, _lh, 0);
-	e.setup(_rlp);
+	e.initialize(_t);
 
-	u256 startGasUsed = gasUsed();
+	// Uncommitting is a non-trivial operation - only do it once we've verified as much of the
+	// transaction as possible.
+	uncommitToMine();
 
+	// OK - transaction looks valid - execute.
+	u256 startGasUsed = gasUsed();
 #if ETH_PARANOIA
 	ctrace << "Executing" << e.t() << "on" << h;
 	ctrace << toHex(e.t().rlp());
 #endif
+	if (!e.execute())
 #if ETH_VMTRACE
-	e.go(e.simpleTrace());
+		e.go(e.simpleTrace());
 #else
-	e.go();
+		e.go();
 #endif
 	e.finalize();
 
diff --git a/libethereum/State.h b/libethereum/State.h
index ee88f443e..5ed76cc27 100644
--- a/libethereum/State.h
+++ b/libethereum/State.h
@@ -188,15 +188,9 @@ public:
 	/// Like sync but only operate on _tq, killing the invalid/old ones.
 	bool cull(TransactionQueue& _tq) const;
 
-	/// Returns the last few block hashes of the current chain.
-	LastHashes getLastHashes(BlockChain const& _bc, unsigned _n) const;
-
 	/// Execute a given transaction.
 	/// This will append @a _t to the transaction list and change the state accordingly.
-	ExecutionResult execute(BlockChain const& _bc, bytes const& _rlp, Permanence _p = Permanence::Committed);
-	ExecutionResult execute(BlockChain const& _bc, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
-	ExecutionResult execute(LastHashes const& _lh, bytes const& _rlp, Permanence _p = Permanence::Committed) { return execute(_lh, &_rlp, _p); }
-	ExecutionResult execute(LastHashes const& _lh, bytesConstRef _rlp, Permanence _p = Permanence::Committed);
+	ExecutionResult execute(LastHashes const& _lh, Transaction const& _t, Permanence _p = Permanence::Committed);
 
 	/// Get the remaining gas limit in this block.
 	u256 gasLimitRemaining() const { return m_currentBlock.gasLimit - gasUsed(); }
diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp
index 5701fc4a5..803d320ee 100644
--- a/libethereum/TransactionQueue.cpp
+++ b/libethereum/TransactionQueue.cpp
@@ -46,7 +46,7 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP)
 
 		UpgradeGuard ul(l);
 		// If valid, append to blocks.
-		m_current[h] = _transactionRLP.toBytes();
+		m_current[h] = t;
 		m_known.insert(h);
 	}
 	catch (Exception const& _e)
@@ -63,20 +63,20 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP)
 	return true;
 }
 
-void TransactionQueue::setFuture(std::pair<h256, bytes> const& _t)
+void TransactionQueue::setFuture(std::pair<h256, Transaction> const& _t)
 {
 	WriteGuard l(m_lock);
 	if (m_current.count(_t.first))
 	{
 		m_current.erase(_t.first);
-		m_unknown.insert(make_pair(Transaction(_t.second, CheckSignature::Sender).sender(), _t));
+		m_unknown.insert(make_pair(_t.second.sender(), _t));
 	}
 }
 
-void TransactionQueue::noteGood(std::pair<h256, bytes> const& _t)
+void TransactionQueue::noteGood(std::pair<h256, Transaction> const& _t)
 {
 	WriteGuard l(m_lock);
-	auto r = m_unknown.equal_range(Transaction(_t.second, CheckSignature::Sender).sender());
+	auto r = m_unknown.equal_range(_t.second.sender());
 	for (auto it = r.first; it != r.second; ++it)
 		m_current.insert(it->second);
 	m_unknown.erase(r.first, r.second);
diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h
index b58944e4f..b104b98ca 100644
--- a/libethereum/TransactionQueue.h
+++ b/libethereum/TransactionQueue.h
@@ -25,6 +25,7 @@
 #include <libdevcore/Common.h>
 #include "libethcore/Common.h"
 #include <libdevcore/Guards.h>
+#include "Transaction.h"
 
 namespace dev
 {
@@ -46,19 +47,19 @@ public:
 
 	void drop(h256 _txHash);
 
-	std::map<h256, bytes> transactions() const { ReadGuard l(m_lock); return m_current; }
+	std::map<h256, Transaction> transactions() const { ReadGuard l(m_lock); return m_current; }
 	std::pair<unsigned, unsigned> items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_unknown.size()); }
 
-	void setFuture(std::pair<h256, bytes> const& _t);
-	void noteGood(std::pair<h256, bytes> const& _t);
+	void setFuture(std::pair<h256, Transaction> const& _t);
+	void noteGood(std::pair<h256, Transaction> const& _t);
 
 	void clear() { WriteGuard l(m_lock); m_known.clear(); m_current.clear(); m_unknown.clear(); }
 
 private:
 	mutable boost::shared_mutex m_lock;							///< General lock.
 	std::set<h256> m_known;										///< Hashes of transactions in both sets.
-	std::map<h256, bytes> m_current;							///< Map of SHA3(tx) to tx.
-	std::multimap<Address, std::pair<h256, bytes>> m_unknown;	///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX.
+	std::map<h256, Transaction> m_current;						///< Map of SHA3(tx) to tx.
+	std::multimap<Address, std::pair<h256, Transaction>> m_unknown;	///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX.
 };
 
 }
diff --git a/libp2p/Common.cpp b/libp2p/Common.cpp
index b995723c3..95c96e346 100644
--- a/libp2p/Common.cpp
+++ b/libp2p/Common.cpp
@@ -25,10 +25,11 @@ using namespace dev;
 using namespace dev::p2p;
 
 const unsigned dev::p2p::c_protocolVersion = 3;
+const unsigned dev::p2p::c_defaultIPPort = 30303;
 
 bool p2p::isPublicAddress(std::string const& _addressToCheck)
 {
-	return isPublicAddress(bi::address::from_string(_addressToCheck));
+	return _addressToCheck.empty() ? false : isPublicAddress(bi::address::from_string(_addressToCheck));
 }
 
 bool p2p::isPublicAddress(bi::address const& _addressToCheck)
@@ -67,7 +68,7 @@ bool p2p::isPrivateAddress(bi::address const& _addressToCheck)
 
 bool p2p::isPrivateAddress(std::string const& _addressToCheck)
 {
-	return isPrivateAddress(bi::address::from_string(_addressToCheck));
+	return _addressToCheck.empty() ? false : isPrivateAddress(bi::address::from_string(_addressToCheck));
 }
 
 // Helper function to determine if an address is localhost
@@ -86,7 +87,7 @@ bool p2p::isLocalHostAddress(bi::address const& _addressToCheck)
 
 bool p2p::isLocalHostAddress(std::string const& _addressToCheck)
 {
-	return isLocalHostAddress(bi::address::from_string(_addressToCheck));
+	return _addressToCheck.empty() ? false : isLocalHostAddress(bi::address::from_string(_addressToCheck));
 }
 
 std::string p2p::reasonOf(DisconnectReason _r)
diff --git a/libp2p/Common.h b/libp2p/Common.h
index 3303c9c07..c9aee9a0e 100644
--- a/libp2p/Common.h
+++ b/libp2p/Common.h
@@ -50,7 +50,8 @@ namespace p2p
 
 /// Peer network protocol version.
 extern const unsigned c_protocolVersion;
-	
+extern const unsigned c_defaultIPPort;
+
 using NodeId = h512;
 
 bool isPrivateAddress(bi::address const& _addressToCheck);
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index 41c2fbb77..ab39c5c25 100644
--- a/libp2p/Host.cpp
+++ b/libp2p/Host.cpp
@@ -66,10 +66,6 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, byte
 	m_alias(networkAlias(_restoreNetwork)),
 	m_lastPing(chrono::steady_clock::time_point::min())
 {
-	for (auto address: m_ifAddresses)
-		if (address.is_v4())
-			clog(NetNote) << "IP Address: " << address << " = " << (isPrivateAddress(address) ? "[LOCAL]" : "[PEER]");
-
 	clog(NetNote) << "Id:" << id();
 }
 
@@ -287,67 +283,50 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
 	}
 }
 
-void Host::determinePublic(string const& _publicAddress, bool _upnp)
+void Host::determinePublic()
 {
-	m_peerAddresses.clear();
-
-	// no point continuing if there are no interface addresses or valid listen port
-	if (!m_ifAddresses.size() || m_listenPort < 1)
-		return;
-
-	// populate interfaces we'll listen on (eth listens on all interfaces); ignores local
-	for (auto addr: m_ifAddresses)
-		if ((m_netPrefs.localNetworking || !isPrivateAddress(addr)) && !isLocalHostAddress(addr))
-			m_peerAddresses.insert(addr);
-
-	// if user supplied address is a public address then we use it
-	// if user supplied address is private, and localnetworking is enabled, we use it
-	bi::address reqPublicAddr(bi::address(_publicAddress.empty() ? bi::address() : bi::address::from_string(_publicAddress)));
-	bi::tcp::endpoint reqPublic(reqPublicAddr, m_listenPort);
-	bool isprivate = isPrivateAddress(reqPublicAddr);
-	bool ispublic = !isprivate && !isLocalHostAddress(reqPublicAddr);
-	if (!reqPublicAddr.is_unspecified() && (ispublic || (isprivate && m_netPrefs.localNetworking)))
+	// set m_tcpPublic := listenIP (if public) > public > upnp > unspecified address.
+	
+	auto ifAddresses = Network::getInterfaceAddresses();
+	auto laddr = m_netPrefs.listenIPAddress.empty() ? bi::address() : bi::address::from_string(m_netPrefs.listenIPAddress);
+	auto lset = !laddr.is_unspecified();
+	auto paddr = m_netPrefs.publicIPAddress.empty() ? bi::address() : bi::address::from_string(m_netPrefs.publicIPAddress);
+	auto pset = !paddr.is_unspecified();
+	
+	bool listenIsPublic = lset && isPublicAddress(laddr);
+	bool publicIsHost = !lset && pset && ifAddresses.count(paddr);
+	
+	bi::tcp::endpoint ep(bi::address(), m_netPrefs.listenPort);
+	if (m_netPrefs.traverseNAT && listenIsPublic)
 	{
-		if (!m_peerAddresses.count(reqPublicAddr))
-			m_peerAddresses.insert(reqPublicAddr);
-		m_tcpPublic = reqPublic;
-		return;
+		clog(NetNote) << "Listen address set to Public address:" << laddr << ". UPnP disabled.";
+		ep.address(laddr);
 	}
-
-	// if address wasn't provided, then use first public ipv4 address found
-	for (auto addr: m_peerAddresses)
-		if (addr.is_v4() && !isPrivateAddress(addr))
-		{
-			m_tcpPublic = bi::tcp::endpoint(*m_peerAddresses.begin(), m_listenPort);
-			return;
-		}
-
-	// or find address via upnp
-	if (_upnp)
+	else if (m_netPrefs.traverseNAT && publicIsHost)
+	{
+		clog(NetNote) << "Public address set to Host configured address:" << paddr << ". UPnP disabled.";
+		ep.address(paddr);
+	}
+	else if (m_netPrefs.traverseNAT)
 	{
-		bi::address upnpifaddr;
-		bi::tcp::endpoint upnpep = Network::traverseNAT(m_ifAddresses, m_listenPort, upnpifaddr);
-		if (!upnpep.address().is_unspecified() && !upnpifaddr.is_unspecified())
+		bi::address natIFAddr;
+		ep = Network::traverseNAT(lset && ifAddresses.count(laddr) ? std::set<bi::address>({laddr}) : ifAddresses, m_netPrefs.listenPort, natIFAddr);
+		
+		if (lset && natIFAddr != laddr)
+			// if listen address is set, Host will use it, even if upnp returns different
+			clog(NetWarn) << "Listen address" << laddr << "differs from local address" << natIFAddr << "returned by UPnP!";
+		
+		if (pset && ep.address() != paddr)
 		{
-			if (!m_peerAddresses.count(upnpep.address()))
-				m_peerAddresses.insert(upnpep.address());
-			m_tcpPublic = upnpep;
-			return;
+			// if public address is set, Host will advertise it, even if upnp returns different
+			clog(NetWarn) << "Specified public address" << paddr << "differs from external address" << ep.address() << "returned by UPnP!";
+			ep.address(paddr);
 		}
 	}
+	else if (pset)
+		ep.address(paddr);
 
-	// or if no address provided, use private ipv4 address if local networking is enabled
-	if (reqPublicAddr.is_unspecified())
-		if (m_netPrefs.localNetworking)
-			for (auto addr: m_peerAddresses)
-				if (addr.is_v4() && isPrivateAddress(addr))
-				{
-					m_tcpPublic = bi::tcp::endpoint(addr, m_listenPort);
-					return;
-				}
-
-	// otherwise address is unspecified
-	m_tcpPublic = bi::tcp::endpoint(bi::address(), m_listenPort);
+	m_tcpPublic = ep;
 }
 
 void Host::runAcceptor()
@@ -401,7 +380,7 @@ string Host::pocHost()
 	return "poc-" + strs[1] + ".ethdev.com";
 }
 
-void Host::addNode(NodeId const& _node, std::string const& _addr, unsigned short _tcpPeerPort, unsigned short _udpNodePort)
+void Host::addNode(NodeId const& _node, bi::address const& _addr, unsigned short _udpNodePort, unsigned short _tcpPeerPort)
 {
 	// TODO: p2p clean this up (bring tested acceptor code over from network branch)
 	while (isWorking() && !m_run)
@@ -417,24 +396,59 @@ void Host::addNode(NodeId const& _node, std::string const& _addr, unsigned short
 		cwarn << "Private port being recorded - setting to 0";
 		_tcpPeerPort = 0;
 	}
+	
+	if (m_nodeTable)
+		m_nodeTable->addNode(Node(_node, NodeIPEndpoint(bi::udp::endpoint(_addr, _udpNodePort), bi::tcp::endpoint(_addr, _tcpPeerPort))));
+}
 
-	boost::system::error_code ec;
-	bi::address addr = bi::address::from_string(_addr, ec);
-	if (ec)
+void Host::requirePeer(NodeId const& _n, bi::address const& _udpAddr, unsigned short _udpPort, bi::address const& _tcpAddr, unsigned short _tcpPort)
+{
+	auto naddr = _udpAddr;
+	auto paddr = _tcpAddr.is_unspecified() ? naddr : _tcpAddr;
+	auto udp = bi::udp::endpoint(naddr, _udpPort);
+	auto tcp = bi::tcp::endpoint(paddr, _tcpPort ? _tcpPort : _udpPort);
+	Node node(_n, NodeIPEndpoint(udp, tcp));
+	if (_n)
 	{
-		bi::tcp::resolver *r = new bi::tcp::resolver(m_ioService);
-		r->async_resolve({_addr, toString(_tcpPeerPort)}, [=](boost::system::error_code const& _ec, bi::tcp::resolver::iterator _epIt)
+		// add or replace peer
+		shared_ptr<Peer> p;
 		{
-			if (!_ec)
+			RecursiveGuard l(x_sessions);
+			if (m_peers.count(_n))
+				p = m_peers[_n];
+			else
 			{
-				bi::tcp::endpoint tcp = *_epIt;
-				if (m_nodeTable) m_nodeTable->addNode(Node(_node, NodeIPEndpoint(bi::udp::endpoint(tcp.address(), _udpNodePort), tcp)));
+				p.reset(new Peer());
+				p->id = _n;
+				p->required = true;
+				m_peers[_n] = p;
 			}
-			delete r;
+			p->endpoint.udp = node.endpoint.udp;
+			p->endpoint.tcp = node.endpoint.tcp;
+		}
+		connect(p);
+	}
+	else if (m_nodeTable)
+	{
+		shared_ptr<boost::asio::deadline_timer> t(new boost::asio::deadline_timer(m_ioService));
+		m_timers.push_back(t);
+		
+		m_nodeTable->addNode(node);
+		t->expires_from_now(boost::posix_time::milliseconds(600));
+		t->async_wait([this, _n](boost::system::error_code const& _ec)
+		{
+			if (!_ec && m_nodeTable)
+				if (auto n = m_nodeTable->node(_n))
+					requirePeer(n.id, n.endpoint.udp.address(), n.endpoint.udp.port(), n.endpoint.tcp.address(), n.endpoint.tcp.port());
 		});
 	}
-	else
-		if (m_nodeTable) m_nodeTable->addNode(Node(_node, NodeIPEndpoint(bi::udp::endpoint(addr, _udpNodePort), bi::tcp::endpoint(addr, _tcpPeerPort))));
+}
+
+void Host::relinquishPeer(NodeId const& _node)
+{
+	Guard l(x_requiredPeers);
+	if (m_requiredPeers.count(_node))
+		m_requiredPeers.erase(_node);
 }
 
 void Host::connect(std::shared_ptr<Peer> const& _p)
@@ -485,6 +499,9 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
 				Guard l(x_connecting);
 				m_connecting.push_back(handshake);
 			}
+			
+			// preempt setting failedAttempts; this value is cleared upon success
+			_p->m_failedAttempts++;
 			handshake->start();
 		}
 		
@@ -541,6 +558,13 @@ void Host::run(boost::system::error_code const&)
 		Guard l(x_connecting);
 		m_connecting.remove_if([](std::weak_ptr<RLPXHandshake> h){ return h.lock(); });
 	}
+	{
+		Guard l(x_timers);
+		m_timers.remove_if([](std::shared_ptr<boost::asio::deadline_timer> t)
+		{
+			return t->expires_from_now().total_milliseconds() > 0;
+		});
+	}
 	
 	for (auto p: m_sessions)
 		if (auto pp = p.second.lock())
@@ -597,21 +621,21 @@ void Host::startedWorking()
 		h.second->onStarting();
 	
 	// try to open acceptor (todo: ipv6)
-	m_listenPort = Network::tcp4Listen(m_tcp4Acceptor, m_netPrefs.listenPort);
+	m_listenPort = Network::tcp4Listen(m_tcp4Acceptor, m_netPrefs);
 
 	// determine public IP, but only if we're able to listen for connections
 	// todo: GUI when listen is unavailable in UI
 	if (m_listenPort)
 	{
-		determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
+		determinePublic();
 
 		if (m_listenPort > 0)
 			runAcceptor();
 	}
 	else
-		clog(NetNote) << "p2p.start.notice id:" << id().abridged() << "Listen port is invalid or unavailable. Node Table using default port (30303).";
+		clog(NetNote) << "p2p.start.notice id:" << id().abridged() << "TCP Listen port is invalid or unavailable.";
 
-	m_nodeTable.reset(new NodeTable(m_ioService, m_alias, bi::address::from_string(listenAddress()), listenPort() > 0 ? listenPort() : 30303));
+	m_nodeTable.reset(new NodeTable(m_ioService, m_alias, bi::address::from_string(listenAddress()), listenPort()));
 	m_nodeTable->setEventHandler(new HostNodeTableHandler(*this));
 	restoreNetwork(&m_restoreNetwork);
 
@@ -720,6 +744,9 @@ void Host::restoreNetwork(bytesConstRef _b)
 	if (!isStarted())
 		BOOST_THROW_EXCEPTION(NetworkStartRequired());
 
+	if (m_dropPeers)
+		return;
+	
 	RecursiveGuard l(x_sessions);
 	RLP r(_b);
 	if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt<unsigned>() == dev::p2p::c_protocolVersion)
diff --git a/libp2p/Host.h b/libp2p/Host.h
index 0feda364f..c161f8437 100644
--- a/libp2p/Host.h
+++ b/libp2p/Host.h
@@ -70,9 +70,7 @@ private:
  * @brief The Host class
  * Capabilities should be registered prior to startNetwork, since m_capabilities is not thread-safe.
  *
- * @todo cleanup startPeerSession
  * @todo determinePublic: ipv6, udp
- * @todo handle conflict if addNode/requireNode called and Node already exists w/conflicting tcp or udp port
  * @todo per-session keepalive/ping instead of broadcast; set ping-timeout via median-latency
  */
 class Host: public Worker
@@ -105,8 +103,14 @@ public:
 	template <class T> std::shared_ptr<T> cap() const { try { return std::static_pointer_cast<T>(m_capabilities.at(std::make_pair(T::staticName(), T::staticVersion()))); } catch (...) { return nullptr; } }
 
 	/// Add node as a peer candidate. Node is added if discovery ping is successful and table has capacity.
-	void addNode(NodeId const& _node, std::string const& _addr, unsigned short _tcpPort, unsigned short _udpPort);
+	void addNode(NodeId const& _node, bi::address const& _addr, unsigned short _udpPort, unsigned short _tcpPort);
+	
+	/// Create Peer and attempt keeping peer connected.
+	void requirePeer(NodeId const& _node, bi::address const& _udpAddr, unsigned short _udpPort, bi::address const& _tcpAddr = bi::address(), unsigned short _tcpPort = 0);
 
+	/// Note peer as no longer being required.
+	void relinquishPeer(NodeId const& _node);
+	
 	/// Set ideal number of peers.
 	void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
 
@@ -117,10 +121,10 @@ public:
 	size_t peerCount() const;
 
 	/// Get the address we're listening on currently.
-	std::string listenAddress() const { return m_tcpPublic.address().to_string(); }
+	std::string listenAddress() const { return m_netPrefs.listenIPAddress.empty() ? "0.0.0.0" : m_netPrefs.listenIPAddress; }
 
 	/// Get the port we're listening on currently.
-	unsigned short listenPort() const { return m_tcpPublic.port(); }
+	unsigned short listenPort() const { return m_netPrefs.listenPort; }
 
 	/// Serialise the set of known peers.
 	bytes saveNetwork() const;
@@ -128,7 +132,7 @@ public:
 	// TODO: P2P this should be combined with peers into a HostStat object of some kind; coalesce data, as it's only used for status information.
 	Peers getPeers() const { RecursiveGuard l(x_sessions); Peers ret; for (auto const& i: m_peers) ret.push_back(*i.second); return ret; }
 
-	void setNetworkPreferences(NetworkPreferences const& _p) { auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
+	void setNetworkPreferences(NetworkPreferences const& _p, bool _dropPeers = false) { m_dropPeers = _dropPeers; auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
 
 	/// Start network. @threadsafe
 	void start();
@@ -154,8 +158,8 @@ protected:
 private:
 	bool havePeerSession(NodeId _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? !!m_sessions[_id].lock() : false; }
 	
-	/// Populate m_peerAddresses with available public addresses.
-	void determinePublic(std::string const& _publicAddress, bool _upnp);
+	/// Determines and sets m_tcpPublic to publicly advertised address.
+	void determinePublic();
 
 	void connect(std::shared_ptr<Peer> const& _p);
 
@@ -192,7 +196,7 @@ private:
 	NetworkPreferences m_netPrefs;										///< Network settings.
 
 	/// Interface addresses (private, public)
-	std::vector<bi::address> m_ifAddresses;								///< Interface addresses.
+	std::set<bi::address> m_ifAddresses;								///< Interface addresses.
 
 	int m_listenPort = -1;												///< What port are we listening on. -1 means binding failed or acceptor hasn't been initialized.
 
@@ -211,6 +215,10 @@ private:
 
 	/// Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer;
 	std::map<NodeId, std::shared_ptr<Peer>> m_peers;
+	
+	/// Peers we try to connect regardless of p2p network.
+	std::set<NodeId> m_requiredPeers;
+	Mutex x_requiredPeers;
 
 	/// The nodes to which we are currently connected. Used by host to service peer requests and keepAlivePeers and for shutdown. (see run())
 	/// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method.
@@ -222,12 +230,15 @@ private:
 
 	unsigned m_idealPeerCount = 5;										///< Ideal number of peers to be connected to.
 
-	std::set<bi::address> m_peerAddresses;									///< Public addresses that peers (can) know us by.
-
 	std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities;	///< Each of the capabilities we support.
+	
+	/// Deadline timers used for isolated network events. GC'd by run.
+	std::list<std::shared_ptr<boost::asio::deadline_timer>> m_timers;
+	Mutex x_timers;
 
 	std::chrono::steady_clock::time_point m_lastPing;						///< Time we sent the last ping to all peers.
 	bool m_accepting = false;
+	bool m_dropPeers = false;
 };
 
 }
diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp
index bdd1f0108..74bc8bd45 100644
--- a/libp2p/Network.cpp
+++ b/libp2p/Network.cpp
@@ -27,6 +27,7 @@
 #endif
 
 #include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/split.hpp>
 
 #include <libdevcore/Common.h>
 #include <libdevcore/Assertions.h>
@@ -40,9 +41,9 @@ using namespace std;
 using namespace dev;
 using namespace dev::p2p;
 
-std::vector<bi::address> Network::getInterfaceAddresses()
+std::set<bi::address> Network::getInterfaceAddresses()
 {
-	std::vector<bi::address> addresses;
+	std::set<bi::address> addresses;
 
 #ifdef _WIN32
 	WSAData wsaData;
@@ -72,7 +73,7 @@ std::vector<bi::address> Network::getInterfaceAddresses()
 		char *addrStr = inet_ntoa(addr);
 		bi::address address(bi::address::from_string(addrStr));
 		if (!isLocalHostAddress(address))
-			addresses.push_back(address.to_v4());
+			addresses.insert(address.to_v4());
 	}
 
 	WSACleanup();
@@ -91,7 +92,7 @@ std::vector<bi::address> Network::getInterfaceAddresses()
 			in_addr addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
 			boost::asio::ip::address_v4 address(boost::asio::detail::socket_ops::network_to_host_long(addr.s_addr));
 			if (!isLocalHostAddress(address))
-				addresses.push_back(address);
+				addresses.insert(address);
 		}
 		else if (ifa->ifa_addr->sa_family == AF_INET6)
 		{
@@ -101,7 +102,7 @@ std::vector<bi::address> Network::getInterfaceAddresses()
 			memcpy(&bytes[0], addr.s6_addr, 16);
 			boost::asio::ip::address_v6 address(bytes, sockaddr->sin6_scope_id);
 			if (!isLocalHostAddress(address))
-				addresses.push_back(address);
+				addresses.insert(address);
 		}
 	}
 
@@ -113,13 +114,39 @@ std::vector<bi::address> Network::getInterfaceAddresses()
 	return std::move(addresses);
 }
 
-int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, unsigned short _listenPort)
+int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const& _netPrefs)
 {
 	int retport = -1;
-	for (unsigned i = 0; i < 2; ++i)
+	if (_netPrefs.listenIPAddress.empty())
+		for (unsigned i = 0; i < 2; ++i)
+		{
+			// try to connect w/listenPort, else attempt net-allocated port
+			bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : _netPrefs.listenPort);
+			try
+			{
+				_acceptor.open(endpoint.protocol());
+				_acceptor.set_option(ba::socket_base::reuse_address(true));
+				_acceptor.bind(endpoint);
+				_acceptor.listen();
+				retport = _acceptor.local_endpoint().port();
+				break;
+			}
+			catch (...)
+			{
+				if (i)
+				{
+					// both attempts failed
+					cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information();
+				}
+				
+				// first attempt failed
+				_acceptor.close();
+				continue;
+			}
+		}
+	else
 	{
-		// try to connect w/listenPort, else attempt net-allocated port
-		bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : _listenPort);
+		bi::tcp::endpoint endpoint(bi::address::from_string(_netPrefs.listenIPAddress), _netPrefs.listenPort);
 		try
 		{
 			_acceptor.open(endpoint.protocol());
@@ -127,25 +154,18 @@ int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, unsigned short _listenPort
 			_acceptor.bind(endpoint);
 			_acceptor.listen();
 			retport = _acceptor.local_endpoint().port();
-			break;
 		}
 		catch (...)
 		{
-			if (i)
-			{
-				// both attempts failed
-				cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information();
-			}
-
-			// first attempt failed
-			_acceptor.close();
-			continue;
+			clog(NetWarn) << "Couldn't start accepting connections on host. Failed to accept socket.\n" << boost::current_exception_diagnostic_information();
 		}
+		assert(retport == _netPrefs.listenPort);
+		return retport;
 	}
 	return retport;
 }
 
-bi::tcp::endpoint Network::traverseNAT(std::vector<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr)
+bi::tcp::endpoint Network::traverseNAT(std::set<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpInterfaceAddr)
 {
 	asserts(_listenPort != 0);
 
@@ -157,26 +177,26 @@ bi::tcp::endpoint Network::traverseNAT(std::vector<bi::address> const& _ifAddres
 	// let m_upnp continue as null - we handle it properly.
 	catch (...) {}
 
-	bi::tcp::endpoint upnpep;
+	bi::tcp::endpoint upnpEP;
 	if (upnp && upnp->isValid())
 	{
-		bi::address paddr;
+		bi::address pAddr;
 		int extPort = 0;
 		for (auto const& addr: _ifAddresses)
 			if (addr.is_v4() && isPrivateAddress(addr) && (extPort = upnp->addRedirect(addr.to_string().c_str(), _listenPort)))
 			{
-				paddr = addr;
+				pAddr = addr;
 				break;
 			}
 
-		auto eip = upnp->externalIP();
-		bi::address eipaddr(bi::address::from_string(eip));
-		if (extPort && eip != string("0.0.0.0") && !isPrivateAddress(eipaddr))
+		auto eIP = upnp->externalIP();
+		bi::address eIPAddr(bi::address::from_string(eIP));
+		if (extPort && eIP != string("0.0.0.0") && !isPrivateAddress(eIPAddr))
 		{
 			clog(NetNote) << "Punched through NAT and mapped local port" << _listenPort << "onto external port" << extPort << ".";
-			clog(NetNote) << "External addr:" << eip;
-			o_upnpifaddr = paddr;
-			upnpep = bi::tcp::endpoint(eipaddr, (unsigned short)extPort);
+			clog(NetNote) << "External addr:" << eIP;
+			o_upnpInterfaceAddr = pAddr;
+			upnpEP = bi::tcp::endpoint(eIPAddr, (unsigned short)extPort);
 		}
 		else
 			clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place).";
@@ -185,5 +205,33 @@ bi::tcp::endpoint Network::traverseNAT(std::vector<bi::address> const& _ifAddres
 			delete upnp;
 	}
 
-	return upnpep;
+	return upnpEP;
 }
+
+bi::tcp::endpoint Network::resolveHost(string const& _addr)
+{
+	static boost::asio::io_service s_resolverIoService;
+	
+	vector<string> split;
+	boost::split(split, _addr, boost::is_any_of(":"));
+	unsigned port = split.size() > 1 ? stoi(split[1]) : dev::p2p::c_defaultIPPort;
+
+	bi::tcp::endpoint ep(bi::address(), port);
+	boost::system::error_code ec;
+	bi::address address = bi::address::from_string(split[0], ec);
+	if (!ec)
+		ep.address(address);
+	else
+	{
+		boost::system::error_code ec;
+		// resolve returns an iterator (host can resolve to multiple addresses)
+		bi::tcp::resolver r(s_resolverIoService);
+		auto it = r.resolve({split[0], toString(port)}, ec);
+		if (ec)
+			clog(NetWarn) << "Error resolving host address " << _addr << ":" << ec.message();
+		else
+			ep = *it;
+	}
+	return ep;
+}
+
diff --git a/libp2p/Network.h b/libp2p/Network.h
index aeeabf329..d02ce3cbe 100644
--- a/libp2p/Network.h
+++ b/libp2p/Network.h
@@ -39,12 +39,19 @@ namespace p2p
 
 struct NetworkPreferences
 {
-	NetworkPreferences(unsigned short p = 30303, std::string i = std::string(), bool u = true, bool l = false): listenPort(p), publicIP(i), upnp(u), localNetworking(l) {}
+	// Default Network Preferences
+	NetworkPreferences(unsigned short lp = 30303): listenPort(lp) {}
+	
+	// Network Preferences with specific Listen IP
+	NetworkPreferences(std::string const& l, unsigned short lp = 30303, bool u = true): publicIPAddress(), listenIPAddress(l), listenPort(lp), traverseNAT(u) {}
+	
+	// Network Preferences with intended Public IP
+	NetworkPreferences(std::string const& publicIP, std::string const& l = std::string(), unsigned short lp = 30303, bool u = true): publicIPAddress(publicIP), listenIPAddress(l), listenPort(lp), traverseNAT(u) { if (!publicIPAddress.empty() && !isPublicAddress(publicIPAddress)) BOOST_THROW_EXCEPTION(InvalidPublicIPAddress()); }
 
+	std::string publicIPAddress;
+	std::string listenIPAddress;
 	unsigned short listenPort = 30303;
-	std::string publicIP;
-	bool upnp = true;
-	bool localNetworking = false;
+	bool traverseNAT = true;
 };
 
 /**
@@ -55,14 +62,17 @@ class Network
 {
 public:
 	/// @returns public and private interface addresses
-	static std::vector<bi::address> getInterfaceAddresses();
+	static std::set<bi::address> getInterfaceAddresses();
 	
 	/// Try to bind and listen on _listenPort, else attempt net-allocated port.
-	static int tcp4Listen(bi::tcp::acceptor& _acceptor, unsigned short _listenPort);
+	static int tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const& _netPrefs);
 
 	/// Return public endpoint of upnp interface. If successful o_upnpifaddr will be a private interface address and endpoint will contain public address and port.
-	static bi::tcp::endpoint traverseNAT(std::vector<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr);
+	static bi::tcp::endpoint traverseNAT(std::set<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpInterfaceAddr);
+	
+	/// Resolve "host:port" string as TCP endpoint. Returns unspecified endpoint on failure.
+	static bi::tcp::endpoint resolveHost(std::string const& _host);
 };
-
+	
 }
 }
diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp
index c230c5441..407b99942 100644
--- a/libp2p/NodeTable.cpp
+++ b/libp2p/NodeTable.cpp
@@ -101,6 +101,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node)
 	shared_ptr<NodeEntry> ret(new NodeEntry(m_node, _node.id, NodeIPEndpoint(_node.endpoint.udp, _node.endpoint.tcp)));
 	m_nodes[_node.id] = ret;
 	ret->cullEndpoint();
+	clog(NodeTableConnect) << "addNode pending for" << m_node.endpoint.udp << m_node.endpoint.tcp;
 	PingNode p(_node.endpoint.udp, m_node.endpoint.udp.address().to_string(), m_node.endpoint.udp.port());
 	p.sign(m_secret);
 	m_socketPointer->send(p);
@@ -450,6 +451,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
 						return; // unsolicited pong; don't note node as active
 				}
 				
+				clog(NodeTableConnect) << "PONG from " << nodeid.abridged() << _from;
 				break;
 			}
 				
@@ -550,31 +552,16 @@ void NodeTable::doRefreshBuckets(boost::system::error_code const& _ec)
 
 	clog(NodeTableEvent) << "refreshing buckets";
 	bool connected = m_socketPointer->isOpen();
-	bool refreshed = false;
 	if (connected)
 	{
-		Guard l(x_state);
-		for (auto& d: m_state)
-			if (chrono::steady_clock::now() - d.modified > c_bucketRefresh)
-			{
-				d.touch();
-				while (!d.nodes.empty())
-				{
-					auto n = d.nodes.front();
-					if (auto p = n.lock())
-					{
-						refreshed = true;
-						ping(p.get());
-						break;
-					}
-					d.nodes.pop_front();
-				}
-			}
+		NodeId randNodeId;
+		crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(0, h256::size));
+		crypto::Nonce::get().ref().copyTo(randNodeId.ref().cropped(h256::size, h256::size));
+		discover(randNodeId);
 	}
 
-	unsigned nextRefresh = connected ? (refreshed ? 200 : c_bucketRefresh.count()*1000) : 10000;
 	auto runcb = [this](boost::system::error_code const& error) { doRefreshBuckets(error); };
-	m_bucketRefreshTimer.expires_from_now(boost::posix_time::milliseconds(nextRefresh));
+	m_bucketRefreshTimer.expires_from_now(boost::posix_time::milliseconds(c_bucketRefresh.count()));
 	m_bucketRefreshTimer.async_wait(runcb);
 }
 
diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h
index 6a167930d..9ff28b7f1 100644
--- a/libp2p/NodeTable.h
+++ b/libp2p/NodeTable.h
@@ -195,7 +195,7 @@ private:
 	/* todo: replace boost::posix_time; change constants to upper camelcase */
 	boost::posix_time::milliseconds const c_evictionCheckInterval = boost::posix_time::milliseconds(75);	///< Interval at which eviction timeouts are checked.
 	std::chrono::milliseconds const c_reqTimeout = std::chrono::milliseconds(300);						///< How long to wait for requests (evict, find iterations).
-	std::chrono::seconds const c_bucketRefresh = std::chrono::seconds(3600);							///< Refresh interval prevents bucket from becoming stale. [Kademlia]
+	std::chrono::milliseconds const c_bucketRefresh = std::chrono::milliseconds(112500);							///< Refresh interval prevents bucket from becoming stale. [Kademlia]
 
 	struct NodeBucket
 	{
diff --git a/libp2p/Peer.h b/libp2p/Peer.h
index 8774b6578..bfa2eaeb6 100644
--- a/libp2p/Peer.h
+++ b/libp2p/Peer.h
@@ -47,7 +47,6 @@ namespace p2p
  * those peers. Modifying these properties via a storage backend alleviates
  * Host of the responsibility. (&& remove save/restoreNetwork)
  * @todo reimplement recording of historical session information on per-transport basis
- * @todo rebuild nodetable when localNetworking is enabled/disabled
  * @todo move attributes into protected
  */
 class Peer: public Node
diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp
index d7bfca34e..dac588149 100644
--- a/libp2p/Session.cpp
+++ b/libp2p/Session.cpp
@@ -216,12 +216,8 @@ bool Session::interpret(PacketType _t, RLP const& _r)
 			NodeId id = _r[i][2].toHash<NodeId>();
 			
 			clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")";
-//			clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")" << isPrivateAddress(peerAddress) << this->id().abridged() << isPrivateAddress(endpoint().address()) << m_server->m_peers.count(id) << (m_server->m_peers.count(id) ? isPrivateAddress(m_server->m_peers.at(id)->address.address()) : -1);
 
-			// todo: draft spec: ignore if dist(us,item) - dist(us,them) > 1
-			
-			// TODO: isPrivate
-			if (!m_server->m_netPrefs.localNetworking && isPrivateAddress(peerAddress))
+			if (!isPublicAddress(peerAddress))
 				goto CONTINUE;	// Private address. Ignore.
 
 			if (!id)
@@ -241,7 +237,7 @@ bool Session::interpret(PacketType _t, RLP const& _r)
 
 			// OK passed all our checks. Assume it's good.
 			addRating(1000);
-			m_server->addNode(id, ep.address().to_string(), ep.port(), ep.port());
+			m_server->addNode(id, ep.address(), ep.port(), ep.port());
 			clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id .abridged()<< ")";
 			CONTINUE:;
 			LAMEPEER:;
diff --git a/libp2p/UDP.h b/libp2p/UDP.h
index 68160d053..374f986b0 100644
--- a/libp2p/UDP.h
+++ b/libp2p/UDP.h
@@ -203,7 +203,10 @@ void UDPSocket<Handler, MaxDatagramSize>::doRead()
 	auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this());
 	m_socket.async_receive_from(boost::asio::buffer(m_recvData), m_recvEndpoint, [this, self](boost::system::error_code _ec, size_t _len)
 	{
-		if (_ec)
+		// ASIO Safety: It is possible that ASIO will call lambda w/o an error
+		// and after the socket has been disconnected. Checking m_closed
+		// guarantees that m_host will not be called after disconnect().
+		if (_ec || m_closed)
 			return disconnectWithError(_ec);
 
 		assert(_len);
@@ -222,7 +225,7 @@ void UDPSocket<Handler, MaxDatagramSize>::doWrite()
 	auto self(UDPSocket<Handler, MaxDatagramSize>::shared_from_this());
 	m_socket.async_send_to(boost::asio::buffer(datagram.data), datagram.endpoint(), [this, self](boost::system::error_code _ec, std::size_t)
 	{
-		if (_ec)
+		if (_ec || m_closed)
 			return disconnectWithError(_ec);
 		else
 		{
diff --git a/libtestutils/CMakeLists.txt b/libtestutils/CMakeLists.txt
index 202b9823c..4ae52e0c9 100644
--- a/libtestutils/CMakeLists.txt
+++ b/libtestutils/CMakeLists.txt
@@ -18,6 +18,11 @@ set(EXECUTABLE testutils)
 
 file(GLOB HEADERS "*.h")
 
+if (NOT JSONRPC)
+	list(REMOVE_ITEM SRC_LIST "./FixedWebThreeServer.cpp")
+	list(REMOVE_ITEM HEADERS "./FixedWebThreeServer.h")
+endif()
+
 if (ETH_STATIC)
 	add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
 else()
diff --git a/libtestutils/Common.cpp b/libtestutils/Common.cpp
index f15a2da12..86f96f667 100644
--- a/libtestutils/Common.cpp
+++ b/libtestutils/Common.cpp
@@ -74,7 +74,7 @@ std::string dev::test::toTestFilePath(std::string const& _filename)
 std::string dev::test::getRandomPath()
 {
 	std::stringstream stream;
-	stream << getDataDir() << "/EthereumTests/" << randomNumber();
+	stream << getDataDir("EthereumTests") << "/" << randomNumber();
 	return stream.str();
 }
 
diff --git a/libtestutils/TransientDirectory.cpp b/libtestutils/TransientDirectory.cpp
index 48beca7e3..694784e25 100644
--- a/libtestutils/TransientDirectory.cpp
+++ b/libtestutils/TransientDirectory.cpp
@@ -22,12 +22,16 @@
 #include <boost/filesystem.hpp>
 #include <libdevcore/Exceptions.h>
 #include "TransientDirectory.h"
-
 using namespace std;
 using namespace dev;
 using namespace dev::test;
 
-TransientDirectory::TransientDirectory(std::string const& _path) : m_path(_path)
+TransientDirectory::TransientDirectory():
+	TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string())
+{}
+
+TransientDirectory::TransientDirectory(std::string const& _path):
+	m_path(_path)
 {
 	// we never ever want to delete a directory (including all its contents) that we did not create ourselves.
 	if (boost::filesystem::exists(m_path))
diff --git a/libtestutils/TransientDirectory.h b/libtestutils/TransientDirectory.h
index 328b4c92b..21a338e59 100644
--- a/libtestutils/TransientDirectory.h
+++ b/libtestutils/TransientDirectory.h
@@ -37,7 +37,8 @@ namespace test
 class TransientDirectory
 {
 public:
-	TransientDirectory(std::string const& _path = getRandomPath());
+	TransientDirectory();
+	TransientDirectory(std::string const& _path);
 	~TransientDirectory();
 
 	std::string const& path() const { return m_path; }
diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp
index 6c6414741..b2c6765b5 100644
--- a/libwebthree/WebThree.cpp
+++ b/libwebthree/WebThree.cpp
@@ -27,7 +27,6 @@
 #include <boost/filesystem.hpp>
 
 #include <libdevcore/Log.h>
-#include <libp2p/Host.h>
 #include <libethereum/Defaults.h>
 #include <libethereum/EthereumHost.h>
 #include <libwhisper/WhisperHost.h>
@@ -73,12 +72,12 @@ WebThreeDirect::~WebThreeDirect()
 	m_ethereum.reset();
 }
 
-void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n)
+void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers)
 {
 	auto had = haveNetwork();
 	if (had)
 		stopNetwork();
-	m_net.setNetworkPreferences(_n);
+	m_net.setNetworkPreferences(_n, _dropPeers);
 	if (had)
 		startNetwork();
 }
@@ -103,7 +102,14 @@ bytes WebThreeDirect::saveNetwork()
 	return m_net.saveNetwork();
 }
 
-void WebThreeDirect::connect(std::string const& _seedHost, unsigned short _port)
+void WebThreeDirect::addNode(NodeId const& _node, bi::tcp::endpoint const& _host)
 {
-	m_net.addNode(NodeId(), _seedHost, _port, _port);
+	m_net.addNode(_node, _host.address(), _host.port(), _host.port());
 }
+
+void WebThreeDirect::requirePeer(NodeId const& _node, bi::tcp::endpoint const& _host)
+{
+	m_net.requirePeer(_node, _host.address(), _host.port());
+}
+
+
diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h
index 242639af4..a0e5cc666 100644
--- a/libwebthree/WebThree.h
+++ b/libwebthree/WebThree.h
@@ -63,9 +63,12 @@ public:
 	/// Same as peers().size(), but more efficient.
 	virtual size_t peerCount() const = 0;
 
-	/// Connect to a particular peer.
-	virtual void connect(std::string const& _seedHost, unsigned short _port) = 0;
-
+	/// Add node to connect to.
+	virtual void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) = 0;
+	
+	/// Require connection to peer.
+	virtual void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) = 0;
+	
 	/// Save peers
 	virtual dev::bytes saveNetwork() = 0;
 
@@ -74,7 +77,7 @@ public:
 
 	virtual bool haveNetwork() const = 0;
 
-	virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n) = 0;
+	virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0;
 
 	virtual p2p::NodeId id() const = 0;
 
@@ -137,22 +140,34 @@ public:
 
 	/// Same as peers().size(), but more efficient.
 	size_t peerCount() const override;
-
-	/// Connect to a particular peer.
-	void connect(std::string const& _seedHost, unsigned short _port = 30303) override;
+	
+	/// Add node to connect to.
+	virtual void addNode(p2p::NodeId const& _node, bi::tcp::endpoint const& _hostEndpoint) override;
+	
+	/// Add node to connect to.
+	void addNode(p2p::NodeId const& _node, std::string const& _hostString) { addNode(_node, p2p::Network::resolveHost(_hostString)); }
+	
+	/// Add node to connect to.
+	void addNode(bi::tcp::endpoint const& _endpoint) { addNode(p2p::NodeId(), _endpoint); }
+
+	/// Add node to connect to.
+	void addNode(std::string const& _hostString) { addNode(p2p::NodeId(), _hostString); }
+	
+	/// Require connection to peer.
+	void requirePeer(p2p::NodeId const& _node, bi::tcp::endpoint const& _endpoint) override;
+
+	/// Require connection to peer.
+	void requirePeer(p2p::NodeId const& _node, std::string const& _hostString) { requirePeer(_node, p2p::Network::resolveHost(_hostString)); }
 
 	/// Save peers
 	dev::bytes saveNetwork() override;
 
-//	/// Restore peers
-//	void restoreNetwork(bytesConstRef _saved) override;
-
 	/// Sets the ideal number of peers.
 	void setIdealPeerCount(size_t _n) override;
 
 	bool haveNetwork() const override { return m_net.isStarted(); }
 
-	void setNetworkPreferences(p2p::NetworkPreferences const& _n) override;
+	void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers = false) override;
 
 	p2p::NodeId id() const override { return m_net.id(); }
 
diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp
index 19d946d01..7729c0ffe 100644
--- a/mix/MixClient.cpp
+++ b/mix/MixClient.cpp
@@ -112,7 +112,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
 
 	State execState = _state;
 	Executive execution(execState, lastHashes, 0);
-	execution.setup(&rlp);
+	execution.initialize(&rlp);
+	execution.execute();
 	std::vector<MachineState> machineStates;
 	std::vector<unsigned> levels;
 	std::vector<MachineCode> codes;
@@ -184,7 +185,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
 	// execute on a state
 	if (!_call)
 	{
-		_state.execute(lastHashes, rlp);
+		_state.execute(lastHashes, _t);
 		if (_t.isCreation() && _state.code(d.contractAddress).empty())
 			BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment"));
 		// collect watches
diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml
index 87ad95bcd..2733238b8 100644
--- a/mix/qml/CodeEditorView.qml
+++ b/mix/qml/CodeEditorView.qml
@@ -143,7 +143,7 @@ Item {
 		}
 
 		onProjectSaved: {
-			if (projectModel.appIsClosing)
+			if (projectModel.appIsClosing || projectModel.projectIsClosing)
 				return;
 			for (var i = 0; i < editorListModel.count; i++)
 			{
diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml
index 6c859a9f9..d7a07eab2 100644
--- a/mix/qml/ProjectModel.qml
+++ b/mix/qml/ProjectModel.qml
@@ -35,6 +35,7 @@ Item {
 	readonly property string projectFileName: ".mix"
 
 	property bool appIsClosing: false
+	property bool projectIsClosing: false
 	property string projectPath: ""
 	property string projectTitle: ""
 	property string currentDocumentId: ""
@@ -122,13 +123,17 @@ Item {
 		icon: StandardIcon.Question
 		property var callBack;
 		onYes: {
+			projectIsClosing = true;
 			projectModel.saveAll();
+			unsavedFiles = [];
 			ProjectModelCode.doCloseProject();
 			if (callBack)
 				callBack();
 		}
 		onRejected: {}
 		onNo: {
+			projectIsClosing = true;
+			unsavedFiles = [];
 			ProjectModelCode.doCloseProject();
 			if (callBack)
 				callBack();
diff --git a/mix/qml/TransactionLog.qml b/mix/qml/TransactionLog.qml
index e1c1f6b0b..43736a89a 100644
--- a/mix/qml/TransactionLog.qml
+++ b/mix/qml/TransactionLog.qml
@@ -44,7 +44,7 @@ Item {
 				target: projectModel
 				onProjectSaved:
 				{
-					if (projectModel.appIsClosing)
+					if (projectModel.appIsClosing || projectModel.projectIsClosing)
 						return;
 					if (compilationStatus.compilationComplete && codeModel.hasContract && !clientModel.running)
 						projectModel.stateListModel.debugDefaultState();
diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml
index c33984d36..a5f68ad66 100644
--- a/mix/qml/WebCodeEditor.qml
+++ b/mix/qml/WebCodeEditor.qml
@@ -19,9 +19,9 @@ Item {
 
 	function setText(text, mode) {
 		currentText = text;
-		if(mode !== undefined)
+		if (mode !== undefined)
 			currentMode = mode;
-		if (initialized) {
+		if (initialized && editorBrowser) {
 			editorBrowser.runJavaScript("setTextBase64(\"" + Qt.btoa(text) + "\")");
 			editorBrowser.runJavaScript("setMode(\"" + currentMode + "\")");
 		}
@@ -29,7 +29,8 @@ Item {
 	}
 
 	function setFocus() {
-		editorBrowser.forceActiveFocus();
+		if (editorBrowser)
+			editorBrowser.forceActiveFocus();
 	}
 
 	function getText() {
@@ -37,19 +38,19 @@ Item {
 	}
 
 	function syncClipboard() {
-		if (Qt.platform.os == "osx") {
+		if (Qt.platform.os == "osx" && editorBrowser) {
 			var text = clipboard.text;
 			editorBrowser.runJavaScript("setClipboardBase64(\"" + Qt.btoa(text) + "\")");
 		}
 	}
 
 	function highlightExecution(location) {
-		if (initialized)
+		if (initialized && editorBrowser)
 			editorBrowser.runJavaScript("highlightExecution(" + location.start + "," + location.end + ")");
 	}
 
 	function showWarning(content) {
-		if (initialized)
+		if (initialized && editorBrowser)
 			editorBrowser.runJavaScript("showWarning('" + content + "')");
 	}
 
@@ -58,12 +59,12 @@ Item {
 	}
 
 	function toggleBreakpoint() {
-		if (initialized)
+		if (initialized && editorBrowser)
 			editorBrowser.runJavaScript("toggleBreakpoint()");
 	}
 
 	function changeGeneration() {
-		if (initialized)
+		if (initialized && editorBrowser)
 			editorBrowser.runJavaScript("changeGeneration()", function(result) {});
 	}
 
@@ -84,9 +85,15 @@ Item {
 			console.log("editor: " + sourceID + ":" + lineNumber + ":" + message);
 		}
 
+		Component.onDestruction:
+		{
+			codeModel.onCompilationComplete.disconnect(compilationComplete);
+			codeModel.onCompilationError.disconnect(compilationError);
+		}
+
 		onLoadingChanged:
 		{
-			if (!loading && !unloaded && editorBrowser) {
+			if (!loading && editorBrowser) {
 				initialized = true;
 				setText(currentText, currentMode);
 				runJavaScript("getTextChanged()", function(result) { });
@@ -94,27 +101,31 @@ Item {
 				syncClipboard();
 				if (currentMode === "solidity")
 				{
-					codeModel.onCompilationComplete.connect(function(){
-						if (editorBrowser)
-							editorBrowser.runJavaScript("compilationComplete()", function(result) { });
-					});
-
-					codeModel.onCompilationError.connect(function(error){
-						if (editorBrowser)
-						{
-							var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false);
-							if (errorInfo.line && errorInfo.column)
-								editorBrowser.runJavaScript("compilationError('" +  errorInfo.line + "', '" +  errorInfo.column + "', '" +  errorInfo.errorDetail + "')", function(result) { });
-							else
-								editorBrowser.runJavaScript("compilationComplete()", function(result) { });
-						}
-					});
+					codeModel.onCompilationComplete.connect(compilationComplete);
+					codeModel.onCompilationError.connect(compilationError);
 				}
 				parent.changeGeneration();
-				loadComplete();
 			}
 		}
 
+
+		function compilationComplete()
+		{
+			if (editorBrowser)
+				editorBrowser.runJavaScript("compilationComplete()", function(result) { });
+		}
+
+		function compilationError(error)
+		{
+			if (!editorBrowser || !error)
+				return;
+			var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false);
+			if (errorInfo.line && errorInfo.column)
+				editorBrowser.runJavaScript("compilationError('" +  errorInfo.line + "', '" +  errorInfo.column + "', '" +  errorInfo.errorDetail + "')", function(result) { });
+			else
+				editorBrowser.runJavaScript("compilationComplete()", function(result) { });
+		}
+
 		Timer
 		{
 			id: pollTimer
@@ -122,10 +133,10 @@ Item {
 			running: false
 			repeat: true
 			onTriggered: {
-				if (unloaded)
+				if (!editorBrowser)
 					return;
 				editorBrowser.runJavaScript("getTextChanged()", function(result) {
-					if (result === true) {
+					if (result === true && editorBrowser) {
 						editorBrowser.runJavaScript("getText()" , function(textValue) {
 							currentText = textValue;
 							editorTextChanged();
@@ -133,7 +144,7 @@ Item {
 					}
 				});
 				editorBrowser.runJavaScript("getBreakpointsChanged()", function(result) {
-					if (result === true) {
+					if (result === true && editorBrowser) {
 						editorBrowser.runJavaScript("getBreakpoints()" , function(bp) {
 							if (currentBreakpoints !== bp) {
 								currentBreakpoints = bp;
diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js
index 03e36c927..a9f5c289f 100644
--- a/mix/qml/html/cm/errorannotation.js
+++ b/mix/qml/html/cm/errorannotation.js
@@ -23,12 +23,15 @@ ErrorAnnotation.prototype.init = function()
 
 ErrorAnnotation.prototype.open = function()
 {
-	var node = document.createElement("div");
-	node.id = "annotation"
-	node.innerHTML = this.content;
-	node.className = "CodeMirror-errorannotation-context";
-	this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: false });
-	this.opened = true;
+	if (this.errorMark.find())
+	{
+		var node = document.createElement("div");
+		node.id = "annotation"
+		node.innerHTML = this.content;
+		node.className = "CodeMirror-errorannotation-context";
+		this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: false });
+		this.opened = true;
+	}
 }
 
 ErrorAnnotation.prototype.close = function()
diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js
index 625722c56..177115f83 100644
--- a/mix/qml/js/ProjectModel.js
+++ b/mix/qml/js/ProjectModel.js
@@ -51,6 +51,7 @@ function closeProject(callBack) {
 	}
 	else
 	{
+		projectIsClosing = true;
 		doCloseProject();
 		if (callBack)
 			callBack();
@@ -96,45 +97,45 @@ function saveProjectFile()
 
 function loadProject(path) {
 	closeProject(function() {
-		console.log("Loading project at " + path);
-		var projectFile = path + projectFileName;
-		var json = fileIo.readFile(projectFile);
-		var projectData = JSON.parse(json);
-		if (projectData.deploymentDir)
-			projectModel.deploymentDir = projectData.deploymentDir
-		if (projectData.packageHash)
-			deploymentDialog.packageHash =  projectData.packageHash
-		if (projectData.packageBase64)
-			deploymentDialog.packageBase64 =  projectData.packageBase64
-		if (projectData.applicationUrlEth)
-			deploymentDialog.applicationUrlEth = projectData.applicationUrlEth
-		if (projectData.applicationUrlHttp)
-			deploymentDialog.applicationUrlHttp = projectData.applicationUrlHttp
-		if (!projectData.title) {
-			var parts = path.split("/");
-			projectData.title = parts[parts.length - 2];
-		}
-		deploymentAddresses = projectData.deploymentAddresses ? projectData.deploymentAddresses : [];
-		projectTitle = projectData.title;
-		projectPath = path;
-		if (!projectData.files)
-			projectData.files = [];
-
-		for(var i = 0; i < projectData.files.length; i++) {
-			addFile(projectData.files[i]);
-		}
-		projectSettings.lastProjectPath = path;
-		projectLoading(projectData);
-		projectLoaded()
-
-		//TODO: move this to codemodel
-		var contractSources = {};
-		for (var d = 0; d < listModel.count; d++) {
-			var doc = listModel.get(d);
-			if (doc.isContract)
-				contractSources[doc.documentId] = fileIo.readFile(doc.path);
-		}
-		codeModel.reset(contractSources);
+			console.log("Loading project at " + path);
+			var projectFile = path + projectFileName;
+			var json = fileIo.readFile(projectFile);
+			var projectData = JSON.parse(json);
+			if (projectData.deploymentDir)
+				projectModel.deploymentDir = projectData.deploymentDir
+			if (projectData.packageHash)
+				deploymentDialog.packageHash =  projectData.packageHash
+			if (projectData.packageBase64)
+				deploymentDialog.packageBase64 =  projectData.packageBase64
+			if (projectData.applicationUrlEth)
+				deploymentDialog.applicationUrlEth = projectData.applicationUrlEth
+			if (projectData.applicationUrlHttp)
+				deploymentDialog.applicationUrlHttp = projectData.applicationUrlHttp
+			if (!projectData.title) {
+				var parts = path.split("/");
+				projectData.title = parts[parts.length - 2];
+			}
+			deploymentAddresses = projectData.deploymentAddresses ? projectData.deploymentAddresses : [];
+			projectTitle = projectData.title;
+			projectPath = path;
+			if (!projectData.files)
+				projectData.files = [];
+
+			for(var i = 0; i < projectData.files.length; i++) {
+				addFile(projectData.files[i]);
+			}
+			projectSettings.lastProjectPath = path;
+			projectLoading(projectData);
+			projectLoaded()
+
+			//TODO: move this to codemodel
+			var contractSources = {};
+			for (var d = 0; d < listModel.count; d++) {
+				var doc = listModel.get(d);
+				if (doc.isContract)
+					contractSources[doc.documentId] = fileIo.readFile(doc.path);
+			}
+			codeModel.reset(contractSources);
 	});
 }
 
diff --git a/mix/test/qml/TestTransactionDebug.qml b/mix/test/qml/TestTransactionDebug.qml
deleted file mode 100644
index 5544d4639..000000000
--- a/mix/test/qml/TestTransactionDebug.qml
+++ /dev/null
@@ -1,386 +0,0 @@
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-import QtQuick.Controls.Styles 1.1
-import QtQuick.Dialogs 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Window 2.1
-import QtQuick.PrivateWidgets 1.1
-import Qt.labs.settings 1.0
-import org.ethereum.qml.QEther 1.0
-import org.ethereum.qml.CodeModel 1.0
-import org.ethereum.qml.ClientModel 1.0
-import org.ethereum.qml.FileIo 1.0
-import org.ethereum.qml.Clipboard 1.0
-
-ApplicationWindow {
-
-	id: mainApplication
-	signal loaded;
-	visible: true
-	width: 1200
-	height: 800
-	minimumWidth: 400
-	minimumHeight: 300
-	title: qsTr("Mix")
-
-	CodeModel {
-		id: codeModel
-	}
-
-	ClientModel {
-		id: clientModel
-		codeModel: codeModel
-	}
-
-	ProjectModel {
-		id: projectModel
-	}
-
-	FileIo {
-		id: fileIo
-	}
-
-	Clipboard {
-		id: clipboard
-	}
-
-	Connections {
-		target: mainApplication
-		onClosing:
-		{
-			mainApplication.close();
-			close.accepted = false;
-		}
-	}
-
-	Component.onCompleted:  {
-		loaded();
-	}
-
-	function close() {
-		projectModel.appIsClosing = true;
-		if (projectModel.projectPath !== "")
-			projectModel.closeProject(function() { Qt.quit(); })
-		else
-			Qt.quit();
-	}
-
-	menuBar: MenuBar {
-		Menu {
-			title: qsTr("File")
-			MenuItem { action: createProjectAction }
-			MenuItem { action: openProjectAction }
-			MenuSeparator {}
-			MenuItem { action: saveAllFilesAction }
-			MenuItem { action: saveCurrentDocument }
-			MenuSeparator {}
-			MenuItem { action: addExistingFileAction }
-			MenuItem { action: addNewJsFileAction }
-			MenuItem { action: addNewHtmlFileAction }
-			MenuItem { action: addNewCssFileAction }
-			MenuSeparator {}
-			MenuItem { action: addNewContractAction }
-			MenuItem { action: closeProjectAction }
-			MenuSeparator {}
-			MenuItem { action: exitAppAction }
-		}
-		Menu {
-			title: qsTr("Deploy")
-			MenuItem { action: mineAction }
-			MenuSeparator {}
-			MenuItem { action: editStatesAction }
-			MenuSeparator {}
-			MenuItem { action: deployViaRpcAction }
-			MenuSeparator {}
-			MenuItem { action: toggleRunOnLoadAction }
-		}
-		Menu {
-			title: qsTr("Debug")
-			MenuItem { action: debugRunAction }
-			MenuSeparator {}
-			MenuItem { action: toggleAssemblyDebuggingAction }
-		}
-		Menu {
-			title: qsTr("Windows")
-			MenuItem { action: openNextDocumentAction }
-			MenuItem { action: openPrevDocumentAction }
-			MenuSeparator {}
-			MenuItem { action: toggleProjectNavigatorAction }
-			MenuItem { action: showHideRightPanelAction }
-			MenuItem { action: toggleTransactionLogAction }
-			MenuItem { action: toggleWebPreviewAction }
-			MenuItem { action: toggleWebPreviewOrientationAction }
-			//MenuItem { action: toggleCallsInLog }
-		}
-	}
-
-	MainContent {
-		id: mainContent;
-		anchors.fill: parent
-	}
-
-	ModalDialog {
-		objectName: "dialog"
-		id: dialog
-	}
-
-	AlertMessageDialog {
-		objectName: "alertMessageDialog"
-		id: messageDialog
-	}
-
-	Settings {
-		id: mainWindowSettings
-		property alias mainWidth: mainApplication.width
-		property alias mainHeight: mainApplication.height
-		property alias mainX: mainApplication.x
-		property alias mainY: mainApplication.y
-	}
-
-	Action {
-		id: exitAppAction
-		text: qsTr("Exit")
-		shortcut: "Ctrl+Q"
-		onTriggered:
-		{
-			mainApplication.close();
-		}
-	}
-
-	Action {
-		id: mineAction
-		text: qsTr("New Block")
-		shortcut: "Ctrl+M"
-		onTriggered: clientModel.mine();
-		enabled: codeModel.hasContract && !clientModel.running && !clientModel.mining
-	}
-
-	StateList {
-		id: stateList
-	}
-
-	Action {
-		id: editStatesAction
-		text: qsTr("Edit States")
-		shortcut: "Ctrl+Alt+E"
-		onTriggered: stateList.show();
-	}
-
-	Connections {
-		target: projectModel.stateListModel
-
-		function updateRunLabel()
-		{
-			debugRunAction.text = qsTr("Deploy") + " \"" + projectModel.stateListModel.defaultStateName() + "\"";
-		}
-
-		onDefaultStateChanged: updateRunLabel()
-		onStateListModelReady: updateRunLabel()
-	}
-
-	Action {
-		id: debugRunAction
-		text: qsTr("Deploy")
-		shortcut: "F5"
-		onTriggered: mainContent.startQuickDebugging()
-		enabled: codeModel.hasContract && !clientModel.running
-	}
-
-	Action {
-		id: toggleAssemblyDebuggingAction
-		text: qsTr("Show VM Code")
-		shortcut: "Ctrl+Alt+V"
-		onTriggered: mainContent.rightPane.assemblyMode = !mainContent.rightPane.assemblyMode;
-		checked: mainContent.rightPane.assemblyMode;
-		enabled: true
-	}
-
-	Action {
-		id: toggleWebPreviewAction
-		text: qsTr("Show Web View")
-		shortcut: "F2"
-		checkable: true
-		checked: mainContent.webViewVisible
-		onTriggered: mainContent.toggleWebPreview();
-	}
-
-	Action {
-		id: toggleTransactionLogAction
-		text: qsTr("Show States and Transactions")
-		shortcut: "Alt+1"
-		checkable: true
-		checked: mainContent.rightPane.transactionLog.visible
-		onTriggered: mainContent.rightPane.transactionLog.visible = !mainContent.rightPane.transactionLog.visible
-	}
-
-	Action {
-		id: toggleProjectNavigatorAction
-		text: qsTr("Show Project Navigator")
-		shortcut: "Alt+0"
-		checkable: true
-		checked: mainContent.projectViewVisible
-		onTriggered: mainContent.toggleProjectView();
-	}
-
-	Action {
-		id: toggleWebPreviewOrientationAction
-		text: qsTr("Horizontal Web View")
-		shortcut: ""
-		checkable: true
-		checked: mainContent.webViewHorizontal
-		onTriggered: mainContent.toggleWebPreviewOrientation();
-	}
-
-	Action {
-		id: toggleRunOnLoadAction
-		text: qsTr("Load State on Startup")
-		shortcut: ""
-		checkable: true
-		checked: mainContent.runOnProjectLoad
-		onTriggered: mainContent.runOnProjectLoad = !mainContent.runOnProjectLoad
-	}
-
-	Action {
-		id: showHideRightPanelAction
-		text: qsTr("Show Right View")
-		shortcut: "F7"
-		checkable: true
-		checked: mainContent.rightViewVisible
-		onTriggered: mainContent.toggleRightView();
-	}
-
-	Action {
-		id: createProjectAction
-		text: qsTr("&New Project")
-		shortcut: "Ctrl+N"
-		enabled: true;
-		onTriggered: projectModel.createProject();
-	}
-
-	Action {
-		id: openProjectAction
-		text: qsTr("&Open Project")
-		shortcut: "Ctrl+O"
-		enabled: true;
-		onTriggered: openProjectFileDialog.open()
-	}
-
-	FileDialog {
-		id: openProjectFileDialog
-		visible: false
-		title: qsTr("Open a Project")
-		selectFolder: true
-		onAccepted: {
-			var path = openProjectFileDialog.fileUrl.toString();
-			path += "/";
-			projectModel.loadProject(path);
-		}
-	}
-
-	Action {
-		id: addNewJsFileAction
-		text: qsTr("New JavaScript File")
-		shortcut: "Ctrl+Alt+J"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.newJsFile();
-	}
-
-	Action {
-		id: addNewHtmlFileAction
-		text: qsTr("New HTML File")
-		shortcut: "Ctrl+Alt+H"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.newHtmlFile();
-	}
-
-	Action {
-		id: addNewCssFileAction
-		text: qsTr("New CSS File")
-		shortcut: "Ctrl+Alt+S"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.newCssFile();
-	}
-
-	Action {
-		id: addNewContractAction
-		text: qsTr("New Contract")
-		shortcut: "Ctrl+Alt+C"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.newContract();
-	}
-
-	Action {
-		id: addExistingFileAction
-		text: qsTr("Add Existing File")
-		shortcut: "Ctrl+Alt+A"
-		enabled: !projectModel.isEmpty
-		onTriggered: addExistingFileDialog.open()
-	}
-
-	FileDialog {
-		id: addExistingFileDialog
-		visible: false
-		title: qsTr("Add a File")
-		selectFolder: false
-		onAccepted: {
-			var paths = addExistingFileDialog.fileUrls;
-			projectModel.addExistingFiles(paths);
-		}
-	}
-
-	Action {
-		id: saveAllFilesAction
-		text: qsTr("Save All")
-		shortcut: "Ctrl+Shift+A"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.saveAll();
-	}
-
-	Action {
-		id: saveCurrentDocument
-		text: qsTr("Save Current Document")
-		shortcut: "Ctrl+S"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.saveCurrentDocument();
-	}
-
-	Action {
-		id: closeProjectAction
-		text: qsTr("Close Project")
-		shortcut: "Ctrl+W"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.closeProject();
-	}
-
-	Action {
-		id: openNextDocumentAction
-		text: qsTr("Next Document")
-		shortcut: "Ctrl+Tab"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.openNextDocument();
-	}
-
-	Action {
-		id: openPrevDocumentAction
-		text: qsTr("Previous Document")
-		shortcut: "Ctrl+Shift+Tab"
-		enabled: !projectModel.isEmpty
-		onTriggered: projectModel.openPrevDocument();
-	}
-
-	Action {
-		id: toggleBreakpointAction
-		text: qsTr("Toggle Breakpoint")
-		shortcut: "F9"
-		enabled: mainContent.codeEditor.editingContract();
-		onTriggered: mainContent.toggleBreakpoint();
-	}
-
-	Action {
-		id: deployViaRpcAction
-		text: qsTr("Deploy to Network")
-		shortcut: "Ctrl+Shift+D"
-		enabled: !projectModel.isEmpty && codeModel.hasContract
-		onTriggered: projectModel.deployProject();
-	}
-}
diff --git a/neth/main.cpp b/neth/main.cpp
index a844da92d..e7dde3cc6 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -84,8 +84,9 @@ void help()
 		<< "    --json-rpc-port  Specify JSON-RPC server port (implies '-j', default: 8080)." << endl
 #endif
 		<< "    -K,--kill-blockchain  First kill the blockchain." << endl
-		<< "    -l,--listen <port>  Listen on the given port for incoming connected (default: 30303)." << endl
-		<< "    -L,--local-networking Use peers whose addresses are local." << endl
+		<< "       --listen-ip <ip>  Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
+		<< "    -l,--listen <port>  Listen on the given port for incoming connections (default: 30303)." << endl
+		<< "    -u,--public-ip <ip>  Force public ip to given (default; auto)." << endl
 		<< "    -m,--mining <on/off>  Enable mining (default: off)" << endl
 		<< "    -n,--upnp <on/off>  Use upnp for NAT (default: on)." << endl
 		<< "    -o,--mode <full/peer>  Start a full node or a peer node (Default: full)." << endl
@@ -94,7 +95,6 @@ void help()
 		<< "    -r,--remote <host>  Connect to remote host (default: none)." << endl
 		<< "    -s,--secret <secretkeyhex>  Set the secret key for use with send command (default: auto)." << endl
 		<< "    -t,--miners <number>  Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl
-		<< "    -u,--public-ip <ip>  Force public ip to given (default; auto)." << endl
 		<< "    -v,--verbosity <0..9>  Set the log verbosity from 0 to 9 (tmp forced to 1)." << endl
 		<< "    -x,--peers <number>  Attempt to connect to given number of peers (default: 5)." << endl
 		<< "    -V,--version  Show the version and exit." << endl
@@ -321,7 +321,9 @@ enum class NodeMode
 
 int main(int argc, char** argv)
 {
+	string listenIP;
 	unsigned short listenPort = 30303;
+	string publicIP;
 	string remoteHost;
 	unsigned short remotePort = 30303;
 	string dbPath;
@@ -332,10 +334,8 @@ int main(int argc, char** argv)
 #if ETH_JSONRPC
 	int jsonrpc = 8080;
 #endif
-	string publicIP;
 	bool bootstrap = false;
 	bool upnp = true;
-	bool useLocal = false;
 	bool forceMining = false;
 	bool killChain = false;
 	bool jit = false;
@@ -371,7 +371,9 @@ int main(int argc, char** argv)
 	for (int i = 1; i < argc; ++i)
 	{
 		string arg = argv[i];
-		if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
+		if (arg == "--listen-ip" && i + 1 < argc)
+			listenIP = argv[++i];
+		else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
 			listenPort = (short)atoi(argv[++i]);
 		else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
 			publicIP = argv[++i];
@@ -392,8 +394,6 @@ int main(int argc, char** argv)
 				return -1;
 			}
 		}
-		else if (arg == "-L" || arg == "--local-networking")
-			useLocal = true;
 		else if (arg == "-K" || arg == "--kill-blockchain")
 			killChain = true;
 		else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
@@ -535,6 +535,8 @@ int main(int argc, char** argv)
 		}
 	}
 
+	
+	
 	if (!clientName.empty())
 		clientName += "/";
 
@@ -542,7 +544,7 @@ int main(int argc, char** argv)
 
 	StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
 	VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
-	NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal);
+	auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
 	auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp");
 	std::string clientImplString = "NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
 	dev::WebThreeDirect web3(
@@ -570,9 +572,9 @@ int main(int argc, char** argv)
 	web3.startNetwork();
 
 	if (bootstrap)
-		web3.connect(Host::pocHost());
+		web3.addNode(p2p::NodeId(), Host::pocHost());
 	if (remoteHost.size())
-		web3.connect(remoteHost, remotePort);
+		web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort));
 	if (c && mining)
 		c->startMining();
 
@@ -687,7 +689,9 @@ int main(int argc, char** argv)
 		{
 			unsigned port;
 			iss >> port;
-			web3.setNetworkPreferences(NetworkPreferences((short)port, publicIP, upnp));
+			if (port)
+				netPrefs.listenPort = port;
+			web3.setNetworkPreferences(netPrefs);
 			web3.startNetwork();
 		}
 		else if (cmd == "connect")
@@ -695,7 +699,7 @@ int main(int argc, char** argv)
 			string addr;
 			unsigned port;
 			iss >> addr >> port;
-			web3.connect(addr, (short)port);
+			web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
 		}
 		else if (cmd == "netstop")
 		{
diff --git a/test/blockchain.cpp b/test/blockchain.cpp
index 50ca22c54..17e6c3588 100644
--- a/test/blockchain.cpp
+++ b/test/blockchain.cpp
@@ -20,7 +20,9 @@
  * block test functions.
  */
 
+#include <boost/filesystem.hpp>
 #include <libdevcrypto/FileSystem.h>
+#include <libtestutils/TransientDirectory.h>
 #include <libethereum/CanonBlockChain.h>
 #include "TestHelper.h"
 
@@ -35,8 +37,8 @@ bytes createBlockRLPFromFields(mObject& _tObj);
 void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj);
 BlockInfo constructBlock(mObject& _o);
 void updatePoW(BlockInfo& _bi);
-void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi);
-RLPStream createFullBlockFromHeader(const BlockInfo& _bi, const bytes& _txs = RLPEmptyList, const bytes& _uncles = RLPEmptyList);
+void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi);
+RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList);
 
 void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 {
@@ -75,7 +77,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 		o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out());
 
 		// construct blockchain
-		BlockChain bc(rlpGenesisBlock.out(), string(), true);
+		TransientDirectory td;
+		BlockChain bc(rlpGenesisBlock.out(), td.path(), true);
 
 		if (_fillin)
 		{
@@ -182,18 +185,17 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 				Transactions txList;
 				for (auto const& txi: txs.transactions())
 				{
-					Transaction tx(txi.second, CheckSignature::Sender);
-					txList.push_back(tx);
+					txList.push_back(txi.second);
 					mObject txObject;
-					txObject["nonce"] = toString(tx.nonce());
-					txObject["data"] = "0x" + toHex(tx.data());
-					txObject["gasLimit"] = toString(tx.gas());
-					txObject["gasPrice"] = toString(tx.gasPrice());
-					txObject["r"] = "0x" + toString(tx.signature().r);
-					txObject["s"] = "0x" + toString(tx.signature().s);
-					txObject["v"] = to_string(tx.signature().v + 27);
-					txObject["to"] = tx.isCreation() ? "" : toString(tx.receiveAddress());
-					txObject["value"] = toString(tx.value());
+					txObject["nonce"] = toString(txi.second.nonce());
+					txObject["data"] = "0x" + toHex(txi.second.data());
+					txObject["gasLimit"] = toString(txi.second.gas());
+					txObject["gasPrice"] = toString(txi.second.gasPrice());
+					txObject["r"] = "0x" + toString(txi.second.signature().r);
+					txObject["s"] = "0x" + toString(txi.second.signature().s);
+					txObject["v"] = to_string(txi.second.signature().v + 27);
+					txObject["to"] = txi.second.isCreation() ? "" : toString(txi.second.receiveAddress());
+					txObject["value"] = toString(txi.second.value());
 
 					txArray.push_back(txObject);
 				}
@@ -242,6 +244,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 
 				if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data()))
 					cnote << "uncle list mismatch\n" << RLP(state.blockData())[2].data() << "\n" << RLP(block2.out())[2].data();
+
 				try
 				{
 					state.sync(bc);
@@ -293,7 +296,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 					BOOST_CHECK(blObj.count("uncleHeaders") == 0);
 					continue;
 				}
-				catch(...)
+				catch (...)
 				{
 					cnote << "state sync or block import did throw an exception\n";
 					BOOST_CHECK(blObj.count("blockHeader") == 0);
@@ -389,7 +392,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
 
 					BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions from  rlp and transaction from field do not match");
 					BOOST_CHECK_MESSAGE(txsFromField[i].rlp() == txsFromRlp[i].rlp(), "transactions rlp do not match");
-
 				}
 
 				// check uncle list
@@ -489,12 +491,12 @@ bytes createBlockRLPFromFields(mObject& _tObj)
 	return rlpStream.out();
 }
 
-void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj)
+void overwriteBlockHeader(BlockInfo& _currentBlockHeader, mObject& _blObj)
 {
 	if (_blObj["blockHeader"].get_obj().size() != 14)
 	{
 
-		BlockInfo tmp = _current_BlockHeader;
+		BlockInfo tmp = _currentBlockHeader;
 
 		if (_blObj["blockHeader"].get_obj().count("parentHash"))
 			tmp.parentHash = h256(_blObj["blockHeader"].get_obj()["parentHash"].get_str());
@@ -540,16 +542,16 @@ void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj)
 
 		// find new valid nonce
 
-		if (tmp != _current_BlockHeader)
+		if (tmp != _currentBlockHeader)
 		{
-			_current_BlockHeader = tmp;
+			_currentBlockHeader = tmp;
 
 			ProofOfWork pow;
 			std::pair<MineInfo, Ethash::Proof> ret;
-			while (!ProofOfWork::verify(_current_BlockHeader))
+			while (!ProofOfWork::verify(_currentBlockHeader))
 			{
-				ret = pow.mine(_current_BlockHeader, 1000, true, true);
-				Ethash::assignResult(ret.second, _current_BlockHeader);
+				ret = pow.mine(_currentBlockHeader, 1000, true, true);
+				Ethash::assignResult(ret.second, _currentBlockHeader);
 			}
 		}
 	}
@@ -558,13 +560,12 @@ void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj)
 		// take the blockheader as is
 		const bytes c_blockRLP = createBlockRLPFromFields(_blObj["blockHeader"].get_obj());
 		const RLP c_bRLP(c_blockRLP);
-		_current_BlockHeader.populateFromHeader(c_bRLP, IgnoreNonce);
+		_currentBlockHeader.populateFromHeader(c_bRLP, IgnoreNonce);
 	}
 }
 
 BlockInfo constructBlock(mObject& _o)
 {
-
 	BlockInfo ret;
 	try
 	{
@@ -601,7 +602,7 @@ void updatePoW(BlockInfo& _bi)
 	_bi.hash = _bi.headerHash(WithNonce);
 }
 
-void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi)
+void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
 {
 	_o["parentHash"] = toString(_bi.parentHash);
 	_o["uncleHash"] = toString(_bi.sha3Uncles);
@@ -621,7 +622,7 @@ void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi)
 	_o["hash"] = toString(_bi.hash);
 }
 
-RLPStream createFullBlockFromHeader(const BlockInfo& _bi,const bytes& _txs, const bytes& _uncles )
+RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles)
 {
 	RLPStream rlpStream;
 	_bi.streamRLP(rlpStream, WithNonce);
@@ -633,8 +634,8 @@ RLPStream createFullBlockFromHeader(const BlockInfo& _bi,const bytes& _txs, cons
 
 	return ret;
 }
-} }// Namespace Close
 
+} }// Namespace Close
 
 BOOST_AUTO_TEST_SUITE(BlockChainTests)
 
diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp
index a4d390b16..49aca852f 100644
--- a/test/checkRandomStateTest.cpp
+++ b/test/checkRandomStateTest.cpp
@@ -83,12 +83,11 @@ bool doStateTest(mValue& _v)
 		ImportTest importer(o, false);
 
 		eth::State theState = importer.m_statePre;
-		bytes tx = importer.m_transaction.rlp();
 		bytes output;
 
 		try
 		{
-			output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
+			output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
 		}
 		catch (Exception const& _e)
 		{
diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp
index f422d1717..5758598b9 100644
--- a/test/createRandomStateTest.cpp
+++ b/test/createRandomStateTest.cpp
@@ -183,12 +183,11 @@ void doStateTests(json_spirit::mValue& _v)
 		test::ImportTest importer(o, true);
 
 		eth::State theState = importer.m_statePre;
-		bytes tx = importer.m_transaction.rlp();
 		bytes output;
 
 		try
 		{
-			output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx).output;
+			output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
 		}
 		catch (Exception const& _e)
 		{
diff --git a/test/peer.cpp b/test/peer.cpp
index bfb4680d3..48431504f 100644
--- a/test/peer.cpp
+++ b/test/peer.cpp
@@ -35,8 +35,8 @@ BOOST_AUTO_TEST_CASE(host)
 	auto oldLogVerbosity = g_logVerbosity;
 	g_logVerbosity = 10;
 	
-	NetworkPreferences host1prefs(30301, "127.0.0.1", false, true);
-	NetworkPreferences host2prefs(30302, "127.0.0.1", false, true);
+	NetworkPreferences host1prefs("127.0.0.1", 30301, false);
+	NetworkPreferences host2prefs("127.0.0.1", 30302, false);
 	
 	Host host1("Test", host1prefs);
 	host1.start();
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(host)
 	auto node2 = host2.id();
 	host2.start();
 	
-	host1.addNode(node2, "127.0.0.1", host2prefs.listenPort, host2prefs.listenPort);
+	host1.addNode(node2, bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort);
 	
 	this_thread::sleep_for(chrono::seconds(3));
 	
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(save_nodes)
 	std::list<Host*> hosts;
 	for (auto i:{0,1,2,3,4,5})
 	{
-		Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", false, true));
+		Host* h = new Host("Test", NetworkPreferences("127.0.0.1", 30300 + i, false));
 		h->setIdealPeerCount(10);
 		// starting host is required so listenport is available
 		h->start();
@@ -73,11 +73,11 @@ BOOST_AUTO_TEST_CASE(save_nodes)
 	
 	Host& host = *hosts.front();
 	for (auto const& h: hosts)
-		host.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());
+		host.addNode(h->id(), bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort());
 	
 	Host& host2 = *hosts.back();
 	for (auto const& h: hosts)
-		host2.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort());
+		host2.addNode(h->id(), bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort());
 
 	this_thread::sleep_for(chrono::milliseconds(2000));
 	bytes firstHostNetwork(host.saveNetwork());
@@ -122,7 +122,7 @@ int peerTest(int argc, char** argv)
 	Host ph("Test", NetworkPreferences(listenPort));
 
 	if (!remoteHost.empty() && !remoteAlias)
-		ph.addNode(remoteAlias, remoteHost, remotePort, remotePort);
+		ph.addNode(remoteAlias, bi::address::from_string(remoteHost), remotePort, remotePort);
 
 	this_thread::sleep_for(chrono::milliseconds(200));
 
diff --git a/test/solidityExecutionFramework.h b/test/solidityExecutionFramework.h
index 86062a90b..2451aa381 100644
--- a/test/solidityExecutionFramework.h
+++ b/test/solidityExecutionFramework.h
@@ -142,7 +142,8 @@ protected:
 		try
 		{
 			// this will throw since the transaction is invalid, but it should nevertheless store the transaction
-			executive.setup(&transactionRLP);
+			executive.initialize(&transactionRLP);
+			executive.execute();
 		}
 		catch (...) {}
 		if (_isCreation)
diff --git a/test/state.cpp b/test/state.cpp
index 4ab59f7a1..7c586ec7d 100644
--- a/test/state.cpp
+++ b/test/state.cpp
@@ -57,13 +57,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
 		ImportTest importer(o, _fillin);
 
 		State theState = importer.m_statePre;
-		bytes tx = importer.m_transaction.rlp();
 		bytes output;
 
 		try
 		{
 			Listener::ExecTimeGuard guard{i.first};
-			output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output;
+			output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
 		}
 		catch (Exception const& _e)
 		{
diff --git a/test/stateOriginal.cpp b/test/stateOriginal.cpp
index 5b7b0415e..384d85344 100644
--- a/test/stateOriginal.cpp
+++ b/test/stateOriginal.cpp
@@ -79,13 +79,9 @@ BOOST_AUTO_TEST_CASE(Complex)
 	cout << s;
 
 	// Inject a transaction to transfer funds from miner to me.
-	bytes tx;
-	{
-		Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
-		assert(t.sender() == myMiner.address());
-		tx = t.rlp();
-	}
-	s.execute(bc, tx);
+	Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
+	assert(t.sender() == myMiner.address());
+	s.execute(bc.lastHashes(), t);
 
 	cout << s;