diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1d35280e0..b410d875c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -435,8 +435,8 @@ endif ()
 add_subdirectory(libethcore)
 
 if (GENERAL)
-#	add_subdirectory(libevm)
-#	add_subdirectory(libethereum)
+	add_subdirectory(libevm)
+	add_subdirectory(libethereum)
 #	add_subdirectory(libwebthree)
 endif ()
 
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 4655240e3..2ee8928f5 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -208,7 +208,7 @@ Main::Main(QWidget *parent) :
 	statusBar()->addPermanentWidget(ui->chainStatus);
 	statusBar()->addPermanentWidget(ui->blockCount);
 
-	ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
+	ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ethereum()->sealEngine()->name())).arg(ethereum()->sealEngine()->revision()).arg(dev::Version));
 
 	QSettings s("ethereum", "alethzero");
 	m_networkConfig = s.value("peers").toByteArray();
diff --git a/eth/main.cpp b/eth/main.cpp
index 434860f59..7ce4d49c2 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -32,7 +32,6 @@
 #include <libdevcore/FileSystem.h>
 #include <libevmcore/Instruction.h>
 #include <libdevcore/StructuredLogger.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/EthashAux.h>
 #include <libevm/VM.h>
 #include <libevm/VMFactory.h>
diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h
index 051128669..61fde605d 100644
--- a/ethminer/MinerAux.h
+++ b/ethminer/MinerAux.h
@@ -37,7 +37,6 @@
 #include <libdevcore/StructuredLogger.h>
 #include <libethcore/Exceptions.h>
 #include <libdevcore/SHA3.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/EthashAux.h>
 #include <libethcore/Farm.h>
 #if ETH_ETHASHCL || !ETH_TRUE
@@ -387,7 +386,6 @@ public:
 #endif
 	}
 
-#if ETH_USING_ETHASH
 	enum class MinerType
 	{
 		CPU,
@@ -412,10 +410,10 @@ private:
 		genesis.difficulty = 1 << 18;
 		cdebug << genesis.boundary();
 
-		GenericFarm<Ethash> f;
-		f.onSolutionFound([&](ProofOfWork::Solution) { return false; });
+		GenericFarm<EthashProofOfWork> f;
+		f.onSolutionFound([&](EthashProofOfWork::Solution) { return false; });
 
-		string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : "";
+		string platformInfo = _m == MinerType::CPU ? "CPU" : "GPU";//EthashProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? EthashProofOfWork::GPUMiner::platformInfo() : "";
 		cout << "Benchmarking on platform: " << platformInfo << endl;
 
 		cout << "Preparing DAG..." << endl;
@@ -488,20 +486,20 @@ private:
 		jsonrpc::HttpClient client(_remote);
 
 		Farm rpc(client);
-		GenericFarm<Ethash> f;
+		GenericFarm<EthashProofOfWork> f;
 		if (_m == MinerType::CPU)
 			f.startCPU();
 		else if (_m == MinerType::GPU)
 			f.startGPU();
 
-		ProofOfWork::WorkPackage current;
+		EthashProofOfWork::WorkPackage current;
 		EthashAux::FullType dag;
 		while (true)
 			try
 			{
 				bool completed = false;
-				ProofOfWork::Solution solution;
-				f.onSolutionFound([&](ProofOfWork::Solution sol)
+				EthashProofOfWork::Solution solution;
+				f.onSolutionFound([&](EthashProofOfWork::Solution sol)
 				{
 					solution = sol;
 					return completed = true;
@@ -595,5 +593,4 @@ private:
 	string m_farmURL = "http://127.0.0.1:8545";
 	unsigned m_farmRecheckPeriod = 500;
 	bool m_precompute = true;
-#endif
 };
diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt
index 30f4705f9..5f876a69b 100644
--- a/exp/CMakeLists.txt
+++ b/exp/CMakeLists.txt
@@ -22,12 +22,12 @@ if (JSONRPC)
 endif()
 
 #target_link_libraries(${EXECUTABLE} webthree)
-#target_link_libraries(${EXECUTABLE} ethereum)
-#target_link_libraries(${EXECUTABLE} p2p)
+target_link_libraries(${EXECUTABLE} ethereum)
+target_link_libraries(${EXECUTABLE} p2p)
 if (ETHASHCL)
 #	target_link_libraries(${EXECUTABLE} ethash-cl)
 #	target_link_libraries(${EXECUTABLE} ethash)
-#	target_link_libraries(${EXECUTABLE} ${OpenCL_LIBRARIES})
+#	target_link_libraries(${EXECUTABLE} OpenCL)
 endif()
 target_link_libraries(${EXECUTABLE} ethcore)
 install( TARGETS ${EXECUTABLE} DESTINATION bin)
diff --git a/exp/main.cpp b/exp/main.cpp
index fa8603459..4a35068f1 100644
--- a/exp/main.cpp
+++ b/exp/main.cpp
@@ -46,7 +46,6 @@
 #include <libdevcore/CommonIO.h>
 #include <libdevcrypto/SecretStore.h>
 #include <libp2p/All.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/Farm.h>
 #include <libdevcore/FileSystem.h>
 #include <libethereum/All.h>
@@ -71,13 +70,16 @@ namespace fs = boost::filesystem;
 #include <libethcore/BlockInfo.h>
 #include <libethcore/Ethash.h>
 #include <libethcore/Params.h>
+#include <libethereum/All.h>
+#include <libethereum/AccountDiff.h>
+#include <libethereum/DownloadMan.h>
+#include <libethereum/Client.h>
 using namespace std;
 using namespace dev;
 using namespace eth;
 #endif
 
-#if 1
-
+#if 0
 int main()
 {
 	BlockInfo bi;
@@ -124,9 +126,7 @@ int main()
 
 	return 0;
 }
-
 #elif 0
-
 int main()
 {
 	cdebug << pbkdf2("password", asBytes("salt"), 1, 32);
@@ -135,10 +135,7 @@ int main()
 	cdebug << pbkdf2("testpassword", fromHex("de5742f1f1045c402296422cee5a8a9ecf0ac5bf594deca1170d22aef33a79cf"), 262144, 16);
 	return 0;
 }
-
-
 #elif 0
-
 int main()
 {
 	cdebug << "EXP";
@@ -162,9 +159,7 @@ int main()
 		ret = orderedTrieRoot(data);
 	cdebug << ret;
 }
-
 #elif 0
-
 int main()
 {
 	KeyManager keyman;
@@ -186,7 +181,6 @@ int main()
 	cdebug << "Secret key for " << a2 << "is" << keyman.secret(a2);
 
 }
-
 #elif 0
 int main()
 {
@@ -246,15 +240,15 @@ int main()
 #elif 0
 int main()
 {
-	GenericFarm<Ethash> f;
+	GenericFarm<EthashProofOfWork> f;
 	BlockInfo genesis = CanonBlockChain::genesis();
 	genesis.difficulty = 1 << 18;
 	cdebug << genesis.boundary();
 
-	auto mine = [](GenericFarm<Ethash>& f, BlockInfo const& g, unsigned timeout) {
+	auto mine = [](GenericFarm<EthashProofOfWork>& f, BlockInfo const& g, unsigned timeout) {
 		BlockInfo bi = g;
 		bool completed = false;
-		f.onSolutionFound([&](ProofOfWork::Solution sol)
+		f.onSolutionFound([&](EthashProofOfWork::Solution sol)
 		{
 			bi.proof = sol;
 			return completed = true;
@@ -289,23 +283,16 @@ int main()
 
 	return 0;
 }
-#elif 0
-
-void mine(State& s, BlockChain const& _bc)
+#elif 1
+void mine(State& s, BlockChain const& _bc, SealEngineFace* _se)
 {
 	s.commitToMine(_bc);
-	GenericFarm<ProofOfWork> f;
-	bool completed = false;
-	f.onSolutionFound([&](ProofOfWork::Solution sol)
-	{
-		return completed = s.completeMine<ProofOfWork>(sol);
-	});
-	f.setWork(s.info());
-	f.startCPU();
-	while (!completed)
-		this_thread::sleep_for(chrono::milliseconds(20));
+	Notified<bytes> sealed;
+	_se->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
+	_se->generateSeal(s.info());
+	sealed.waitNot({});
+	s.sealBlock(sealed);
 }
-#elif 0
 int main()
 {
 	cnote << "Testing State...";
@@ -316,47 +303,62 @@ int main()
 
 	Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()));
 
-	OverlayDB stateDB = State::openDB();
-	CanonBlockChain bc;
-	cout << bc;
+	using Sealer = Ethash;
+	CanonBlockChain<Sealer> bc;
+	auto gbb = bc.headerData(bc.genesisHash());
+	assert(Sealer::BlockHeader(bc.headerData(bc.genesisHash()), IgnoreSeal, bc.genesisHash(), HeaderData));
+
+	SealEngineFace* se = Sealer::createSealEngine();
+	KeyPair kp(sha3("test"));
+	se->setOption("authority", rlp(kp.secret()));
+	se->setOption("authorities", rlpList(kp.address()));
 
-	State s(stateDB, BaseState::CanonGenesis, myMiner.address());
-	cout << s;
+	OverlayDB stateDB = State::openDB(bc.genesisHash());
+	cnote << bc;
+
+	State s = bc.genesisState(stateDB);
+	s.setAddress(myMiner.address());
+	cnote << s;
 
 	// Sync up - this won't do much until we use the last state.
 	s.sync(bc);
 
-	cout << s;
+	cnote << s;
 
 	// Mine to get some ether!
-	mine(s, bc);
+	mine(s, bc, se);
 
-	bc.attemptImport(s.blockData(), stateDB);
+	bytes minedBlock = s.blockData();
+	cnote << "Mined block is" << BlockInfo(minedBlock).stateRoot;
+	bc.import(minedBlock, stateDB);
 
-	cout << bc;
+	cnote << bc;
 
 	s.sync(bc);
 
-	cout << s;
+	cnote << s;
+	cnote << "Miner now has" << s.balance(myMiner.address());
+	s.resetCurrent();
+	cnote << "Miner now has" << s.balance(myMiner.address());
 
 	// Inject a transaction to transfer funds from miner to me.
 	Transaction t(1000, 10000, 30000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
 	assert(t.sender() == myMiner.address());
 	s.execute(bc.lastHashes(), t);
 
-	cout << s;
+	cnote << s;
 
 	// Mine to get some ether and set in stone.
 	s.commitToMine(bc);
 	s.commitToMine(bc);
-	mine(s, bc);
+	mine(s, bc, se);
 	bc.attemptImport(s.blockData(), stateDB);
 
-	cout << bc;
+	cnote << bc;
 
 	s.sync(bc);
 
-	cout << s;
+	cnote << s;
 
 	return 0;
 }
diff --git a/libdevcore/Guards.h b/libdevcore/Guards.h
index 44d5969e4..135209d23 100644
--- a/libdevcore/Guards.h
+++ b/libdevcore/Guards.h
@@ -22,6 +22,7 @@
 #pragma once
 
 #include <mutex>
+#include <condition_variable>
 #include <atomic>
 #include <boost/thread.hpp>
 
@@ -33,6 +34,7 @@ using RecursiveMutex = std::recursive_mutex;
 using SharedMutex = boost::shared_mutex;
 
 using Guard = std::lock_guard<std::mutex>;
+using UniqueGuard = std::unique_lock<std::mutex>;
 using RecursiveGuard = std::lock_guard<std::recursive_mutex>;
 using ReadGuard = boost::shared_lock<boost::shared_mutex>;
 using UpgradableGuard = boost::upgrade_lock<boost::shared_mutex>;
@@ -74,6 +76,33 @@ private:
 };
 using SpinGuard = std::lock_guard<SpinLock>;
 
+template <class N>
+class Notified
+{
+public:
+	Notified() {}
+	Notified(N const& _v): m_value(_v) {}
+	Notified(Notified const&) = delete;
+	Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; }
+
+	operator N() const { UniqueGuard l(m_mutex); return m_value; }
+
+	void wait() const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(old); }
+	void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); }
+	void waitNot(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value != _v;}); }
+	template <class F> void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); }
+
+	template <class R, class P> void wait(std::chrono::duration<R, P> _d) const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(_d, old); }
+	template <class R, class P> void wait(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value == _v;}); }
+	template <class R, class P> void waitNot(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value != _v;}); }
+	template <class R, class P, class F> void wait(std::chrono::duration<R, P> _d, F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, _f); }
+
+private:
+	mutable Mutex m_mutex;
+	mutable std::condition_variable m_cv;
+	N m_value;
+};
+
 /** @brief Simple block guard.
  * The expression/block following is guarded though the given mutex.
  * Usage:
diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h
index a94c8ba55..701f4b8e8 100644
--- a/libdevcore/RLP.h
+++ b/libdevcore/RLP.h
@@ -393,6 +393,9 @@ public:
 	/// Read the byte stream.
 	bytes const& out() const { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return m_out; }
 
+	/// Invalidate the object and steal the output byte stream.
+	bytes&& invalidate() { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return std::move(m_out); }
+
 	/// Swap the contents of the output stream out for some other byte array.
 	void swapOut(bytes& _dest) { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); swap(m_out, _dest); }
 
diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h
index 55ca81023..05affa677 100644
--- a/libdevcore/TrieDB.h
+++ b/libdevcore/TrieDB.h
@@ -231,8 +231,11 @@ public:
 		}
 	}
 
-protected:
-	DB* db() const { return m_db; }
+	/// Get the underlying database.
+	/// @warning This can be used to bypass the trie code. Don't use these unless you *really*
+	/// know what you're doing.
+	DB const* db() const { return m_db; }
+	DB* db() { return m_db; }
 
 private:
 	RLPStream& streamNode(RLPStream& _s, bytes const& _b);
@@ -383,6 +386,7 @@ public:
 	using Super::isEmpty;
 
 	using Super::root;
+	using Super::db;
 
 	using Super::leftOvers;
 	using Super::check;
@@ -435,6 +439,7 @@ public:
 	using Super::check;
 	using Super::open;
 	using Super::setRoot;
+	using Super::db;
 
 	std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); }
 	bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); }
diff --git a/libethcore/BasicAuthority.cpp b/libethcore/BasicAuthority.cpp
index 7006107e1..22da67080 100644
--- a/libethcore/BasicAuthority.cpp
+++ b/libethcore/BasicAuthority.cpp
@@ -19,6 +19,7 @@
  * @date 2014
  */
 
+#include <libdevcore/CommonJS.h>
 #include "Exceptions.h"
 #include "BasicAuthority.h"
 #include "BlockInfo.h"
@@ -60,38 +61,38 @@ void BasicAuthority::BlockHeaderRaw::populateFromHeader(RLP const& _header, Stri
 	}
 }
 
+void BasicAuthority::BlockHeaderRaw::verifyParent(BlockHeaderRaw const& _parent)
+{
+	(void)_parent;
+}
 
+void BasicAuthority::BlockHeaderRaw::populateFromParent(BlockHeaderRaw const& _parent)
+{
+	(void)_parent;
+}
 
-class BasicAuthoritySeal: public SealFace
+StringHashMap BasicAuthority::BlockHeaderRaw::jsInfo() const
 {
-public:
-	BasicAuthoritySeal(Signature const& _sig): m_sig(_sig) {}
+	return { { "sig", toJS(m_sig) } };
+}
 
-	virtual bytes sealedHeader(BlockInfo const& _bi) const
-	{
-		BasicAuthority::BlockHeader h(_bi);
-		h.m_sig = m_sig;
-		RLPStream ret;
-		h.streamRLP(ret);
-		return ret.out();
-	}
 
-private:
-	Signature m_sig;
-};
 
-class BasicAuthoritySealEngine: public SealEngineFace
+class BasicAuthoritySealEngine: public SealEngineBase<BasicAuthority>
 {
 public:
 	void setSecret(Secret const& _s) { m_secret = _s; }
 	void generateSeal(BlockInfo const& _bi)
 	{
-		BasicAuthoritySeal s(sign(m_secret, _bi.hashWithout()));
-		m_onSealGenerated(&s);
+		BasicAuthority::BlockHeader h(_bi);
+		h.m_sig = sign(m_secret, _bi.hashWithout());
+		RLPStream ret;
+		h.streamRLP(ret);
+		m_onSealGenerated(ret.out());
 	}
-	void onSealGenerated(std::function<void(SealFace const* s)> const& _f) { m_onSealGenerated = _f; }
-	bool isMining() const { return false; }
-	MiningProgress miningProgress() const { return MiningProgress(); }
+	void onSealGenerated(std::function<void(bytes const&)> const& _f) { m_onSealGenerated = _f; }
+	bool isWorking() const { return false; }
+	WorkingProgress workingProgress() const { return WorkingProgress(); }
 
 private:
 	virtual bool onOptionChanging(std::string const& _name, bytes const& _value)
@@ -107,7 +108,7 @@ private:
 	}
 
 	Secret m_secret;
-	std::function<void(SealFace const* s)> m_onSealGenerated;
+	std::function<void(bytes const& s)> m_onSealGenerated;
 };
 
 SealEngineFace* BasicAuthority::createSealEngine()
diff --git a/libethcore/BasicAuthority.h b/libethcore/BasicAuthority.h
index 9127c1d53..8db47938b 100644
--- a/libethcore/BasicAuthority.h
+++ b/libethcore/BasicAuthority.h
@@ -52,33 +52,31 @@ class BasicAuthority
 	friend class ::BasicAuthoritySealEngine;
 
 public:
-	// TODO: remove
-	struct Result {};
-	struct WorkPackage {};
-	static const WorkPackage NullWorkPackage;
-
 	static std::string name() { return "BasicAuthority"; }
 	static unsigned revision() { return 0; }
 	static SealEngineFace* createSealEngine();
 
 	class BlockHeaderRaw: public BlockInfo
 	{
-		friend class ::BasicAuthoritySeal;
+		friend class ::BasicAuthoritySealEngine;
 
 	public:
+		static const unsigned SealFields = 1;
+
 		bool verify() const;
 		bool preVerify() const;
 
-		WorkPackage package() const { return NullWorkPackage; }
 		Signature sig() const { return m_sig; }
 
+		StringHashMap jsInfo() const;
+
 	protected:
 		BlockHeaderRaw() = default;
 		BlockHeaderRaw(BlockInfo const& _bi): BlockInfo(_bi) {}
 
-		static const unsigned SealFields = 1;
-
 		void populateFromHeader(RLP const& _header, Strictness _s);
+		void populateFromParent(BlockHeaderRaw const& _parent);
+		void verifyParent(BlockHeaderRaw const& _parent);
 		void streamRLPFields(RLPStream& _s) const { _s << m_sig; }
 		void clear() { m_sig = Signature(); }
 		void noteDirty() const {}
diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp
index eb07162fb..64961bc40 100644
--- a/libethcore/BlockInfo.cpp
+++ b/libethcore/BlockInfo.cpp
@@ -36,10 +36,10 @@ BlockInfo::BlockInfo(): timestamp(Invalid256)
 {
 }
 
-BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s)
+BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s, h256 const& _hashWith, BlockDataType _bdt)
 {
-	RLP header = extractHeader(_block);
-	m_hash = sha3(header.data());
+	RLP header = _bdt == BlockData ? extractHeader(_block) : RLP(_block);
+	m_hash = _hashWith ? _hashWith : sha3(header.data());
 	populateFromHeader(header, _s);
 }
 
@@ -58,7 +58,7 @@ void BlockInfo::clear()
 	gasUsed = 0;
 	timestamp = 0;
 	extraData.clear();
-	m_hashWithout = h256();
+	noteDirty();
 }
 
 h256 const& BlockInfo::boundary() const
@@ -133,20 +133,8 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
 	if (number > ~(unsigned)0)
 		BOOST_THROW_EXCEPTION(InvalidNumber());
 
-	if (_s != CheckNothing)
-	{
-		if (gasUsed > gasLimit)
-			BOOST_THROW_EXCEPTION(TooMuchGasUsed() << RequirementError(bigint(gasLimit), bigint(gasUsed)) );
-
-		if (difficulty < c_minimumDifficulty)
-			BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError(bigint(c_minimumDifficulty), bigint(difficulty)) );
-
-		if (gasLimit < c_minGasLimit)
-			BOOST_THROW_EXCEPTION(InvalidGasLimit() << RequirementError(bigint(c_minGasLimit), bigint(gasLimit)) );
-
-		if (number && extraData.size() > c_maximumExtraDataSize)
-			BOOST_THROW_EXCEPTION(ExtraDataTooBig() << RequirementError(bigint(c_maximumExtraDataSize), bigint(extraData.size())));
-	}
+	if (_s != CheckNothing && gasUsed > gasLimit)
+		BOOST_THROW_EXCEPTION(TooMuchGasUsed() << RequirementError(bigint(gasLimit), bigint(gasUsed)) );
 }
 
 struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; };
@@ -198,6 +186,7 @@ void BlockInfo::populateFromParent(BlockInfo const& _parent)
 	gasLimit = selectGasLimit(_parent);
 	gasUsed = 0;
 	difficulty = calculateDifficulty(_parent);
+	parentHash = _parent.hash();
 }
 
 u256 BlockInfo::selectGasLimit(BlockInfo const& _parent) const
@@ -222,15 +211,6 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
 
 void BlockInfo::verifyParent(BlockInfo const& _parent) const
 {
-	// Check difficulty is correct given the two timestamps.
-	if (difficulty != calculateDifficulty(_parent))
-		BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError((bigint)calculateDifficulty(_parent), (bigint)difficulty));
-
-	if (gasLimit < c_minGasLimit ||
-		gasLimit <= _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor ||
-		gasLimit >= _parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor)
-		BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)_parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor) << errinfo_got((bigint)gasLimit) << errinfo_max((bigint)_parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor));
-
 	// Check timestamp is after previous timestamp.
 	if (parentHash)
 	{
diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h
index 710279cb2..b00fa73fb 100644
--- a/libethcore/BlockInfo.h
+++ b/libethcore/BlockInfo.h
@@ -42,10 +42,18 @@ enum Strictness
 {
 	CheckEverything,
 	QuickNonce,
-	IgnoreNonce,
+	IgnoreSeal,
 	CheckNothing
 };
 
+enum BlockDataType
+{
+	HeaderData,
+	BlockData
+};
+
+DEV_SIMPLE_EXCEPTION(NoHashRecorded);
+
 /** @brief Encapsulation of a block header.
  * Class to contain all of a block header's data. It is able to parse a block header and populate
  * from some given RLP block serialisation with the static fromHeader(), through the method
@@ -69,7 +77,10 @@ enum Strictness
  */
 struct BlockInfo
 {
+	friend class BlockChain;
 public:
+	static const unsigned BasicFields = 13;
+
 	// TODO: make them all private!
 	h256 parentHash;
 	h256 sha3Uncles;
@@ -78,7 +89,7 @@ public:
 	h256 transactionsRoot;
 	h256 receiptsRoot;
 	LogBloom logBloom;
-	u256 difficulty;
+	u256 difficulty;		// TODO: pull out into BlockHeader
 	u256 number;
 	u256 gasLimit;
 	u256 gasUsed;
@@ -86,10 +97,12 @@ public:
 	bytes extraData;
 
 	BlockInfo();
-	BlockInfo(bytesConstRef _block, Strictness _s);
+	explicit BlockInfo(bytesConstRef _data, Strictness _s = CheckEverything, h256 const& _hashWith = h256(), BlockDataType _bdt = BlockData);
+	explicit BlockInfo(bytes const& _data, Strictness _s = CheckEverything, h256 const& _hashWith = h256(), BlockDataType _bdt = BlockData): BlockInfo(&_data, _s, _hashWith, _bdt) {}
 
 	static h256 headerHashFromBlock(bytes const& _block) { return headerHashFromBlock(&_block); }
 	static h256 headerHashFromBlock(bytesConstRef _block);
+	static RLP extractHeader(bytesConstRef _block);
 
 	explicit operator bool() const { return timestamp != Invalid256; }
 
@@ -121,17 +134,14 @@ public:
 
 	/// sha3 of the header only.
 	h256 const& hashWithout() const;
-	h256 const& hash() const { return m_hash; }
-
-protected:
-	static RLP extractHeader(bytesConstRef _block);
-	void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce);
-	void streamRLPFields(RLPStream& _s) const;
+	h256 const& hash() const { if (m_hash) return m_hash; throw NoHashRecorded(); }
 
 	void clear();
 	void noteDirty() const { m_hashWithout = m_boundary = m_hash = h256(); }
 
-	static const unsigned BasicFields = 13;
+protected:
+	void populateFromHeader(RLP const& _header, Strictness _s = IgnoreSeal);
+	void streamRLPFields(RLPStream& _s) const;
 
 	mutable h256 m_hash;						///< SHA3 hash of the block header! Not serialised.
 
@@ -152,35 +162,50 @@ template <class BlockInfoSub>
 class BlockHeaderPolished: public BlockInfoSub
 {
 public:
+	static const unsigned Fields = BlockInfoSub::BasicFields + BlockInfoSub::SealFields;
+
 	BlockHeaderPolished() {}
 	BlockHeaderPolished(BlockInfo const& _bi): BlockInfoSub(_bi) {}
-	explicit BlockHeaderPolished(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { populate(&_block, _s, _h); }
-	explicit BlockHeaderPolished(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { populate(_block, _s, _h); }
+	explicit BlockHeaderPolished(bytes const& _data, Strictness _s = IgnoreSeal, h256 const& _h = h256(), BlockDataType _bdt = BlockData) { populate(&_data, _s, _h, _bdt); }
+	explicit BlockHeaderPolished(bytesConstRef _data, Strictness _s = IgnoreSeal, h256 const& _h = h256(), BlockDataType _bdt = BlockData) { populate(_data, _s, _h, _bdt); }
 
-	static BlockHeaderPolished fromHeader(bytes const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { return fromHeader(bytesConstRef(&_header), _s, _h); }
-	static BlockHeaderPolished fromHeader(bytesConstRef _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { BlockHeaderPolished ret; ret.populateFromHeader(RLP(_header), _s, _h); return ret; }
+	// deprecated - just use constructor instead.
+	static BlockHeaderPolished fromHeader(bytes const& _data, Strictness _s = IgnoreSeal, h256 const& _h = h256()) { return BlockHeaderPolished(_data, _s, _h, HeaderData); }
+	static BlockHeaderPolished fromHeader(bytesConstRef _data, Strictness _s = IgnoreSeal, h256 const& _h = h256()) { return BlockHeaderPolished(_data, _s, _h, HeaderData); }
 
-	void populate(bytesConstRef _block, Strictness _s, h256 const& _h = h256()) { populateFromHeader(BlockInfo::extractHeader(_block), _s, _h); }
+	// deprecated for public API - use constructor.
+	// TODO: make private.
+	void populate(bytesConstRef _data, Strictness _s, h256 const& _h = h256(), BlockDataType _bdt = BlockData)
+	{
+		populateFromHeader(_bdt == BlockData ? BlockInfo::extractHeader(_data) : RLP(_data), _s, _h);
+	}
 
 	void populateFromParent(BlockHeaderPolished const& _parent)
 	{
 		noteDirty();
 		BlockInfo::parentHash = _parent.hash();
 		BlockInfo::populateFromParent(_parent);
+		BlockInfoSub::populateFromParent(_parent);
 	}
 
+	// TODO: consider making private.
 	void verifyParent(BlockHeaderPolished const& _parent)
 	{
 		if (BlockInfo::parentHash && BlockInfo::parentHash != _parent.hash())
 			BOOST_THROW_EXCEPTION(InvalidParentHash());
 		BlockInfo::verifyParent(_parent);
+		BlockInfoSub::verifyParent(_parent);
 	}
 
-	void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256())
+	// deprecated for public API - use constructor.
+	// TODO: make private.
+	void populateFromHeader(RLP const& _header, Strictness _s = IgnoreSeal, h256 const& _h = h256())
 	{
 		BlockInfo::m_hash = _h;
 		if (_h)
 			assert(_h == dev::sha3(_header.data()));
+		else
+			BlockInfo::m_hash = dev::sha3(_header.data());
 
 		if (_header.itemCount() != BlockInfo::BasicFields + BlockInfoSub::SealFields)
 			BOOST_THROW_EXCEPTION(InvalidBlockHeaderItemCount());
@@ -213,6 +238,13 @@ public:
 		if (_i == WithProof)
 			BlockInfoSub::streamRLPFields(_s);
 	}
+
+	bytes sealFieldsRLP() const
+	{
+		RLPStream s;
+		BlockInfoSub::streamRLPFields(s);
+		return s.out();
+	}
 };
 
 }
diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp
index 58e506b37..499854584 100644
--- a/libethcore/Common.cpp
+++ b/libethcore/Common.cpp
@@ -29,7 +29,6 @@
 #include <libdevcore/Log.h>
 #include <libdevcore/SHA3.h>
 #include "Exceptions.h"
-#include "ProofOfWork.h"
 #include "BlockInfo.h"
 using namespace std;
 using namespace dev;
@@ -57,7 +56,7 @@ Network const c_network = Network::Frontier;
 Network const c_network = Network::Olympic;
 #endif
 
-const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (ProofOfWork::revision() << 9);
+const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (23 << 9);
 
 vector<pair<u256, string>> const& units()
 {
diff --git a/libethcore/Common.h b/libethcore/Common.h
index 1a688fbd8..5c0a0cc79 100644
--- a/libethcore/Common.h
+++ b/libethcore/Common.h
@@ -124,10 +124,16 @@ struct ImportRequirements
 	using value = unsigned;
 	enum
 	{
-		ValidNonce = 1, ///< Validate nonce
+		ValidSeal = 1, ///< Validate seal
 		DontHave = 2, ///< Avoid old blocks
-		CheckUncles = 4, ///< Check uncle nonces
-		Default = ValidNonce | DontHave | CheckUncles
+		UncleBasic = 4, ///< Check the basic structure of the uncles.
+		TransactionBasic = 8, ///< Check the basic structure of the transactions.
+		UncleSeals = 16, ///< Check the basic structure of the uncles.
+		TransactionSignatures = 32, ///< Check the basic structure of the transactions.
+		CheckUncles = UncleBasic | UncleSeals, ///< Check uncle seals
+		CheckTransactions = TransactionBasic | TransactionSignatures, ///< Check transaction signatures
+		Default = ValidSeal | DontHave | CheckUncles | CheckTransactions,
+		None = 0
 	};
 };
 
@@ -201,7 +207,7 @@ inline void badBlock(bytes const& _header, std::string const& _err) { badBlock(&
 /**
  * @brief Describes the progress of a mining operation.
  */
-struct MiningProgress
+struct WorkingProgress
 {
 //	MiningProgress& operator+=(MiningProgress const& _mp) { hashes += _mp.hashes; ms = std::max(ms, _mp.ms); return *this; }
 	uint64_t hashes = 0;		///< Total number of hashes computed.
diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp
index d385163be..128822b80 100644
--- a/libethcore/Ethash.cpp
+++ b/libethcore/Ethash.cpp
@@ -33,6 +33,7 @@
 #include <libdevcore/Log.h>
 #include <libdevcore/Common.h>
 #include <libdevcore/CommonIO.h>
+#include <libdevcore/CommonJS.h>
 #include <libdevcrypto/CryptoPP.h>
 #include <libdevcore/FileSystem.h>
 #include <libethash/ethash.h>
@@ -49,6 +50,7 @@
 #include "Exceptions.h"
 #include "Farm.h"
 #include "Miner.h"
+#include "Params.h"
 using namespace std;
 using namespace std::chrono;
 
@@ -57,8 +59,6 @@ namespace dev
 namespace eth
 {
 
-const Ethash::WorkPackage Ethash::NullWorkPackage = Ethash::WorkPackage();
-
 h256 const& Ethash::BlockHeaderRaw::seedHash() const
 {
 	if (!m_seedHash)
@@ -78,7 +78,7 @@ void Ethash::BlockHeaderRaw::populateFromHeader(RLP const& _header, Strictness _
 		ex << errinfo_nonce(m_nonce);
 		ex << errinfo_mixHash(m_mixHash);
 		ex << errinfo_seedHash(seedHash());
-		Ethash::Result er = EthashAux::eval(seedHash(), hashWithout(), m_nonce);
+		EthashProofOfWork::Result er = EthashAux::eval(seedHash(), hashWithout(), m_nonce);
 		ex << errinfo_ethashResult(make_tuple(er.value, er.mixHash));
 		ex << errinfo_hash256(hashWithout());
 		ex << errinfo_difficulty(difficulty);
@@ -93,6 +93,35 @@ void Ethash::BlockHeaderRaw::populateFromHeader(RLP const& _header, Strictness _
 		ex << errinfo_nonce(m_nonce);
 		BOOST_THROW_EXCEPTION(ex);
 	}
+
+	if (_s != CheckNothing)
+	{
+		if (difficulty < c_minimumDifficulty)
+			BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError(bigint(c_minimumDifficulty), bigint(difficulty)) );
+
+		if (gasLimit < c_minGasLimit)
+			BOOST_THROW_EXCEPTION(InvalidGasLimit() << RequirementError(bigint(c_minGasLimit), bigint(gasLimit)) );
+
+		if (number && extraData.size() > c_maximumExtraDataSize)
+			BOOST_THROW_EXCEPTION(ExtraDataTooBig() << RequirementError(bigint(c_maximumExtraDataSize), bigint(extraData.size())));
+	}
+}
+
+void Ethash::BlockHeaderRaw::verifyParent(BlockHeaderRaw const& _parent)
+{
+	// Check difficulty is correct given the two timestamps.
+	if (difficulty != calculateDifficulty(_parent))
+		BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError((bigint)calculateDifficulty(_parent), (bigint)difficulty));
+
+	if (gasLimit < c_minGasLimit ||
+		gasLimit <= _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor ||
+		gasLimit >= _parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor)
+		BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)_parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor) << errinfo_got((bigint)gasLimit) << errinfo_max((bigint)_parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor));
+}
+
+void Ethash::BlockHeaderRaw::populateFromParent(BlockHeaderRaw const& _parent)
+{
+	(void)_parent;
 }
 
 bool Ethash::BlockHeaderRaw::preVerify() const
@@ -143,20 +172,15 @@ bool Ethash::BlockHeaderRaw::verify() const
 	return slow;
 }
 
-Ethash::WorkPackage Ethash::BlockHeaderRaw::package() const
-{
-	WorkPackage ret;
-	ret.boundary = boundary();
-	ret.headerHash = hashWithout();
-	ret.seedHash = seedHash();
-	return ret;
-}
-
 void Ethash::BlockHeaderRaw::prep(std::function<int(unsigned)> const& _f) const
 {
 	EthashAux::full(seedHash(), true, _f);
 }
 
+StringHashMap Ethash::BlockHeaderRaw::jsInfo() const
+{
+	return { { "nonce", toJS(m_nonce) }, { "seedHash", toJS(seedHash()) }, { "mixHash", toJS(m_mixHash) } };
+}
 
 
 
@@ -164,10 +188,10 @@ void Ethash::BlockHeaderRaw::prep(std::function<int(unsigned)> const& _f) const
 
 
 
-class EthashCPUMiner: public GenericMiner<Ethash>, Worker
+class EthashCPUMiner: public GenericMiner<EthashProofOfWork>, Worker
 {
 public:
-	EthashCPUMiner(GenericMiner<Ethash>::ConstructionInfo const& _ci): GenericMiner<Ethash>(_ci), Worker("miner" + toString(index())) {}
+	EthashCPUMiner(GenericMiner<EthashProofOfWork>::ConstructionInfo const& _ci): GenericMiner<EthashProofOfWork>(_ci), Worker("miner" + toString(index())) {}
 
 	static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
 	static std::string platformInfo();
@@ -190,7 +214,7 @@ private:
 };
 
 #if ETH_ETHASHCL || !ETH_TRUE
-class EthashGPUMiner: public GenericMiner<Ethash>, Worker
+class EthashGPUMiner: public GenericMiner<EthashProofOfWork>, Worker
 {
 	friend class dev::eth::EthashCLHook;
 
@@ -234,66 +258,84 @@ private:
 };
 #endif
 
-class EthashSeal: public SealFace
+struct EthashSealEngine: public SealEngineBase<Ethash>
 {
-public:
-	EthashSeal(h256 const& _mixHash, h64 const& _nonce): m_mixHash(_mixHash), m_nonce(_nonce) {}
-
-	virtual bytes sealedHeader(BlockInfo const& _bi) const
-	{
-		Ethash::BlockHeader h(_bi);
-		h.m_mixHash = m_mixHash;
-		h.m_nonce = m_nonce;
-		RLPStream ret;
-		h.streamRLP(ret);
-		return ret.out();
-	}
-
-private:
-	h256 m_mixHash;
-	h64 m_nonce;
-};
+	friend class Ethash;
 
-struct EthashSealEngine: public SealEngineFace
-{
 public:
 	EthashSealEngine()
 	{
-		map<string, GenericFarm<Ethash>::SealerDescriptor> sealers;
-		sealers["cpu"] = GenericFarm<Ethash>::SealerDescriptor{&EthashCPUMiner::instances, [](GenericMiner<Ethash>::ConstructionInfo ci){ return new EthashCPUMiner(ci); }};
+		map<string, GenericFarm<EthashProofOfWork>::SealerDescriptor> sealers;
+		sealers["cpu"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashCPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashCPUMiner(ci); }};
 #if ETH_ETHASHCL
-		sealers["opencl"] = GenericFarm<Ethash>::SealerDescriptor{&EthashGPUMiner::instances, [](GenericMiner<Ethash>::ConstructionInfo ci){ return new EthashGPUMiner(ci); }};
+		sealers["opencl"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashGPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashGPUMiner(ci); }};
 #endif
 		m_farm.setSealers(sealers);
 	}
 
-	strings sealers() const override { return { "cpu", "opencl" }; }
+	strings sealers() const override
+	{
+		return {
+			"cpu"
+#if ETH_ETHASHCL
+			, "opencl"
+#endif
+		};
+	}
 	void setSealer(std::string const& _sealer) override { m_sealer = _sealer; }
-	void disable() override { m_farm.stop(); }
+	void cancelGeneration() override { m_farm.stop(); }
 	void generateSeal(BlockInfo const& _bi) override
 	{
-		m_farm.setWork(Ethash::BlockHeader(_bi).package());
+		m_sealing = Ethash::BlockHeader(_bi);
+		m_farm.setWork(m_sealing);
 		m_farm.start(m_sealer);
-		m_farm.setWork(Ethash::BlockHeader(_bi).package());		// TODO: take out one before or one after...
+		m_farm.setWork(m_sealing);		// TODO: take out one before or one after...
 		Ethash::ensurePrecomputed((unsigned)_bi.number);
 	}
-	void onSealGenerated(std::function<void(SealFace const*)> const& _f) override
+	void onSealGenerated(std::function<void(bytes const&)> const& _f) override
 	{
-		m_farm.onSolutionFound([=](Ethash::Solution const& sol)
+		m_farm.onSolutionFound([=](EthashProofOfWork::Solution const& sol)
 		{
 			cdebug << m_farm.work().seedHash << m_farm.work().headerHash << sol.nonce << EthashAux::eval(m_farm.work().seedHash, m_farm.work().headerHash, sol.nonce).value;
-			EthashSeal s(sol.mixHash, sol.nonce);
-			_f(&s);
+			m_sealing.m_mixHash = sol.mixHash;
+			m_sealing.m_nonce = sol.nonce;
+			RLPStream ret;
+			m_sealing.streamRLP(ret);
+			_f(ret.out());
 			return true;
 		});
 	}
 
 private:
 	bool m_opencl = false;
-	eth::GenericFarm<Ethash> m_farm;
-	std::string m_sealer;
+	eth::GenericFarm<EthashProofOfWork> m_farm;
+	std::string m_sealer = "cpu";
+	Ethash::BlockHeader m_sealing;
 };
 
+void Ethash::manuallySubmitWork(SealEngineFace* _engine, h256 const& _mixHash, Nonce _nonce)
+{
+	if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
+		// Go via the farm since the handler function object is stored as a local within the Farm's lambda.
+		// Has the side effect of stopping local workers, which is good, as long as it only does it for
+		// valid submissions.
+		static_cast<GenericFarmFace<EthashProofOfWork>&>(e->m_farm).submitProof(EthashProofOfWork::Solution{_nonce, _mixHash}, nullptr);
+}
+
+bool Ethash::isWorking(SealEngineFace* _engine)
+{
+	if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
+		return e->m_farm.isMining();
+	return false;
+}
+
+WorkingProgress Ethash::workingProgress(SealEngineFace* _engine)
+{
+	if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
+		return e->m_farm.miningProgress();
+	return WorkingProgress();
+}
+
 SealEngineFace* Ethash::createSealEngine()
 {
 	return new EthashSealEngine;
@@ -342,7 +384,7 @@ void EthashCPUMiner::workLoop()
 	{
 		ethashReturn = ethash_full_compute(dag->full, *(ethash_h256_t*)w.headerHash.data(), tryNonce);
 		h256 value = h256((uint8_t*)&ethashReturn.result, h256::ConstructFromPointer);
-		if (value <= boundary && submitProof(Ethash::Solution{(h64)(u64)tryNonce, h256((uint8_t*)&ethashReturn.mix_hash, h256::ConstructFromPointer)}))
+		if (value <= boundary && submitProof(EthashProofOfWork::Solution{(h64)(u64)tryNonce, h256((uint8_t*)&ethashReturn.mix_hash, h256::ConstructFromPointer)}))
 			break;
 		if (!(hashCount % 100))
 			accumulateHashes(100);
@@ -403,29 +445,6 @@ std::string EthashCPUMiner::platformInfo()
 
 #if ETH_ETHASHCL || !ETH_TRUE
 
-using UniqueGuard = std::unique_lock<std::mutex>;
-
-template <class N>
-class Notified
-{
-public:
-	Notified() {}
-	Notified(N const& _v): m_value(_v) {}
-	Notified(Notified const&) = delete;
-	Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; }
-
-	operator N() const { UniqueGuard l(m_mutex); return m_value; }
-
-	void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); }
-	void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); }
-	template <class F> void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); }
-
-private:
-	mutable Mutex m_mutex;
-	mutable std::condition_variable m_cv;
-	N m_value;
-};
-
 class EthashCLHook: public ethash_cl_miner::search_hook
 {
 public:
diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h
index 99baa8a05..576621bd4 100644
--- a/libethcore/Ethash.h
+++ b/libethcore/Ethash.h
@@ -53,59 +53,42 @@ public:
 	static unsigned revision();
 	static SealEngineFace* createSealEngine();
 
-	// TODO: remove or virtualize
-	struct Solution
-	{
-		h64 nonce;
-		h256 mixHash;
-	};
-	// TODO: make private
-	struct Result
-	{
-		h256 value;
-		h256 mixHash;
-	};
-	// TODO: virtualise
-	struct WorkPackage
-	{
-		WorkPackage() = default;
-
-		void reset() { headerHash = h256(); }
-		operator bool() const { return headerHash != h256(); }
+	using Nonce = h64;
 
-		h256 boundary;
-		h256 headerHash;	///< When h256() means "pause until notified a new work package is available".
-		h256 seedHash;
-	};
-	static const WorkPackage NullWorkPackage;
+	static void manuallySubmitWork(SealEngineFace* _engine, h256 const& _mixHash, Nonce _nonce);
+	static bool isWorking(SealEngineFace* _engine);
+	static WorkingProgress workingProgress(SealEngineFace* _engine);
 
 	class BlockHeaderRaw: public BlockInfo
 	{
-		friend class EthashSeal;
+		friend class EthashSealEngine;
 
 	public:
+		static const unsigned SealFields = 2;
+
 		bool verify() const;
 		bool preVerify() const;
 
 		void prep(std::function<int(unsigned)> const& _f = std::function<int(unsigned)>()) const;
-		WorkPackage package() const;
 		h256 const& seedHash() const;
-		h64 const& nonce() const { return m_nonce; }
+		Nonce const& nonce() const { return m_nonce; }
 		h256 const& mixHash() const { return m_mixHash; }
 
+		StringHashMap jsInfo() const;
+
 	protected:
 		BlockHeaderRaw() = default;
 		BlockHeaderRaw(BlockInfo const& _bi): BlockInfo(_bi) {}
 
-		static const unsigned SealFields = 2;
-
 		void populateFromHeader(RLP const& _header, Strictness _s);
-		void clear() { m_mixHash = h256(); m_nonce = h64(); }
+		void populateFromParent(BlockHeaderRaw const& _parent);
+		void verifyParent(BlockHeaderRaw const& _parent);
+		void clear() { m_mixHash = h256(); m_nonce = Nonce(); }
 		void noteDirty() const { m_seedHash = h256(); }
 		void streamRLPFields(RLPStream& _s) const { _s << m_mixHash << m_nonce; }
 
 	private:
-		h64 m_nonce;
+		Nonce m_nonce;
 		h256 m_mixHash;
 
 		mutable h256 m_seedHash;
@@ -115,13 +98,6 @@ public:
 
 	// TODO: Move elsewhere (EthashAux?)
 	static void ensurePrecomputed(unsigned _number);
-
-	/// Default value of the local work size. Also known as workgroup size.
-	static const unsigned defaultLocalWorkSize;
-	/// Default value of the global work size as a multiplier of the local work size
-	static const unsigned defaultGlobalWorkSizeMultiplier;
-	/// Default value of the milliseconds per global work size (per batch)
-	static const unsigned defaultMSPerBatch;
 };
 
 }
diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp
index 00537c21a..c511978db 100644
--- a/libethcore/EthashAux.cpp
+++ b/libethcore/EthashAux.cpp
@@ -45,6 +45,11 @@ const char* DAGChannel::name() { return EthGreen "DAG"; }
 
 EthashAux* dev::eth::EthashAux::s_this = nullptr;
 
+const unsigned EthashProofOfWork::defaultLocalWorkSize = 64;
+const unsigned EthashProofOfWork::defaultGlobalWorkSizeMultiplier = 4096; // * CL_DEFAULT_LOCAL_WORK_SIZE
+const unsigned EthashProofOfWork::defaultMSPerBatch = 0;
+const EthashProofOfWork::WorkPackage EthashProofOfWork::NullWorkPackage = EthashProofOfWork::WorkPackage();
+
 EthashAux::~EthashAux()
 {
 }
@@ -232,29 +237,29 @@ unsigned EthashAux::computeFull(h256 const& _seedHash, bool _createIfMissing)
 	return (get()->m_generatingFullNumber == blockNumber) ? get()->m_fullProgress : 0;
 }
 
-Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const
+EthashProofOfWork::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const
 {
 	ethash_return_value_t r = ethash_full_compute(full, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
 	if (!r.success)
 		BOOST_THROW_EXCEPTION(DAGCreationFailure());
-	return Ethash::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
+	return EthashProofOfWork::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
 }
 
-Ethash::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const
+EthashProofOfWork::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const
 {
 	ethash_return_value r = ethash_light_compute(light, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce);
 	if (!r.success)
 		BOOST_THROW_EXCEPTION(DAGCreationFailure());
-	return Ethash::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
+	return EthashProofOfWork::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)};
 }
 
-Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce)
+EthashProofOfWork::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce)
 {
 	DEV_GUARDED(get()->x_fulls)
 		if (FullType dag = get()->m_fulls[_seedHash].lock())
 			return dag->compute(_headerHash, _nonce);
 	DEV_IF_THROWS(return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce))
 	{
-		return Ethash::Result{ ~h256(), h256() };
+		return EthashProofOfWork::Result{ ~h256(), h256() };
 	}
 }
diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h
index 132b9b436..d42e46d91 100644
--- a/libethcore/EthashAux.h
+++ b/libethcore/EthashAux.h
@@ -34,6 +34,47 @@ namespace eth
 
 struct DAGChannel: public LogChannel { static const char* name(); static const int verbosity = 1; };
 
+/// Proof of work definition for Ethash.
+struct EthashProofOfWork
+{
+	struct Solution
+	{
+		Nonce nonce;
+		h256 mixHash;
+	};
+
+	struct Result
+	{
+		h256 value;
+		h256 mixHash;
+	};
+
+	struct WorkPackage
+	{
+		WorkPackage() = default;
+		WorkPackage(Ethash::BlockHeader const& _bh):
+			boundary(_bh.boundary()),
+			headerHash(_bh.hashWithout()),
+			seedHash(_bh.seedHash())
+		{}
+		void reset() { headerHash = h256(); }
+		operator bool() const { return headerHash != h256(); }
+
+		h256 boundary;
+		h256 headerHash;	///< When h256() means "pause until notified a new work package is available".
+		h256 seedHash;
+	};
+
+	static const WorkPackage NullWorkPackage;
+
+	/// Default value of the local work size. Also known as workgroup size.
+	static const unsigned defaultLocalWorkSize;
+	/// Default value of the global work size as a multiplier of the local work size
+	static const unsigned defaultGlobalWorkSizeMultiplier;
+	/// Default value of the milliseconds per global work size (per batch)
+	static const unsigned defaultMSPerBatch;
+};
+
 class EthashAux
 {
 public:
@@ -46,7 +87,7 @@ public:
 		LightAllocation(h256 const& _seedHash);
 		~LightAllocation();
 		bytesConstRef data() const;
-		Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const;
+		EthashProofOfWork::Result compute(h256 const& _headerHash, Nonce const& _nonce) const;
 		ethash_light_t light;
 		uint64_t size;
 	};
@@ -55,7 +96,7 @@ public:
 	{
 		FullAllocation(ethash_light_t _light, ethash_callback_t _cb);
 		~FullAllocation();
-		Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const;
+		EthashProofOfWork::Result compute(h256 const& _headerHash, Nonce const& _nonce) const;
 		bytesConstRef data() const;
 		uint64_t size() const { return ethash_full_dag_size(full); }
 		ethash_full_t full;
@@ -79,7 +120,7 @@ public:
 	/// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing and _createIfMissing is false.
 	static FullType full(h256 const& _seedHash, bool _createIfMissing = false, std::function<int(unsigned)> const& _f = std::function<int(unsigned)>());
 
-	static Ethash::Result eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce);
+	static EthashProofOfWork::Result eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce);
 
 private:
 	EthashAux() {}
diff --git a/libethcore/Farm.h b/libethcore/Farm.h
index b69f8325a..c86b4804e 100644
--- a/libethcore/Farm.h
+++ b/libethcore/Farm.h
@@ -123,9 +123,9 @@ public:
 	 * @brief Get information on the progress of mining this work package.
 	 * @return The progress with mining so far.
 	 */
-	MiningProgress const& miningProgress() const
+	WorkingProgress const& miningProgress() const
 	{
-		MiningProgress p;
+		WorkingProgress p;
 		p.ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_lastStart).count();
 		{
 			ReadGuard l2(x_minerWork);
@@ -195,7 +195,7 @@ private:
 	std::atomic<bool> m_isMining = {false};
 
 	mutable SharedMutex x_progress;
-	mutable MiningProgress m_progress;
+	mutable WorkingProgress m_progress;
 	std::chrono::steady_clock::time_point m_lastStart;
 
 	SolutionFound m_onSolutionFound;
diff --git a/libethcore/Miner.h b/libethcore/Miner.h
index 03eba9880..90a5902c4 100644
--- a/libethcore/Miner.h
+++ b/libethcore/Miner.h
@@ -36,9 +36,9 @@ namespace dev
 namespace eth
 {
 
-struct MineInfo: public MiningProgress {};
+struct MineInfo: public WorkingProgress {};
 
-inline std::ostream& operator<<(std::ostream& _out, MiningProgress _p)
+inline std::ostream& operator<<(std::ostream& _out, WorkingProgress _p)
 {
 	_out << _p.rate() << " H/s = " <<  _p.hashes << " hashes / " << (double(_p.ms) / 1000) << " s";
 	return _out;
diff --git a/libethcore/ProofOfWork.cpp b/libethcore/ProofOfWork.cpp
deleted file mode 100644
index 843db72c7..000000000
--- a/libethcore/ProofOfWork.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-	This file is part of cpp-ethereum.
-
-	cpp-ethereum is free software: you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation, either version 3 of the License, or
-	(at your option) any later version.
-
-	cpp-ethereum is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/** @file ProofOfWork.cpp
- * @author Gav Wood <i@gavwood.com>
- * @date 2014
- */
-
-#include "ProofOfWork.h"
-#include "BlockInfo.h"
-using namespace std;
-using namespace dev;
-using namespace eth;
-
diff --git a/libethcore/ProofOfWork.h b/libethcore/ProofOfWork.h
deleted file mode 100644
index f55c54df6..000000000
--- a/libethcore/ProofOfWork.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-	This file is part of cpp-ethereum.
-
-	cpp-ethereum is free software: you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation, either version 3 of the License, or
-	(at your option) any later version.
-
-	cpp-ethereum is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/** @file ProofOfWork.h
- * @author Gav Wood <i@gavwood.com>
- * @date 2014
- *
- * Determines the PoW algorithm.
- */
-
-#pragma once
-
-#include <libdevcore/RLP.h>
-#include <libdevcrypto/Common.h>
-#include "Common.h"
-//#include "Ethash.h"
-#include "BasicAuthority.h"
-
-namespace dev
-{
-namespace eth
-{
-
-using ProofOfWork = BasicAuthority;
-
-}
-}
diff --git a/libethcore/Sealer.h b/libethcore/Sealer.h
index 28381444e..137659dfc 100644
--- a/libethcore/Sealer.h
+++ b/libethcore/Sealer.h
@@ -25,6 +25,7 @@
 
 #include <functional>
 #include <libdevcore/Guards.h>
+#include <libdevcore/RLP.h>
 #include "Common.h"
 
 namespace dev
@@ -34,28 +35,22 @@ namespace eth
 
 class BlockInfo;
 
-class SealFace
-{
-public:
-	virtual bool wouldSealHeader(BlockInfo const&) const { return true; }
-	virtual bytes sealedHeader(BlockInfo const& _bi) const = 0;
-};
-
 class SealEngineFace
 {
 public:
+	virtual std::string name() const = 0;
+	virtual unsigned revision() const = 0;
+	virtual unsigned sealFields() const = 0;
+	virtual bytes sealRLP() const = 0;
+
 	bytes option(std::string const& _name) const { Guard l(x_options); return m_options.count(_name) ? m_options.at(_name) : bytes(); }
 	bool setOption(std::string const& _name, bytes const& _value) { Guard l(x_options); try { if (onOptionChanging(_name, _value)) { m_options[_name] = _value; return true; } } catch (...) {} return false; }
 
 	virtual strings sealers() const { return { "default" }; }
 	virtual void setSealer(std::string const&) {}
 	virtual void generateSeal(BlockInfo const& _bi) = 0;
-	virtual void onSealGenerated(std::function<void(SealFace const* s)> const& _f) = 0;
-	virtual void disable() {}
-
-	// TODO: rename & generalise
-	virtual bool isMining() const { return false; }
-	virtual MiningProgress miningProgress() const { return MiningProgress(); }
+	virtual void onSealGenerated(std::function<void(bytes const& s)> const& _f) = 0;
+	virtual void cancelGeneration() {}
 
 protected:
 	virtual bool onOptionChanging(std::string const&, bytes const&) { return true; }
@@ -66,5 +61,15 @@ private:
 	std::unordered_map<std::string, bytes> m_options;
 };
 
+template <class Sealer>
+class SealEngineBase: public SealEngineFace
+{
+public:
+	std::string name() const override { return Sealer::name(); }
+	unsigned revision() const override { return Sealer::revision(); }
+	unsigned sealFields() const override { return Sealer::BlockHeader::SealFields; }
+	bytes sealRLP() const override { RLPStream s(sealFields()); s.appendRaw(typename Sealer::BlockHeader().sealFieldsRLP(), sealFields()); return s.out(); }
+};
+
 }
 }
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index 14b13b90d..aae8cbd10 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -35,12 +35,12 @@
 #include <libdevcore/FileSystem.h>
 #include <libethcore/Exceptions.h>
 #include <libethcore/EthashAux.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/BlockInfo.h>
 #include <libethcore/Params.h>
 #include <liblll/Compiler.h>
 #include "GenesisInfo.h"
 #include "State.h"
+#include "Utility.h"
 #include "Defaults.h"
 
 using namespace std;
@@ -48,7 +48,7 @@ using namespace dev;
 using namespace dev::eth;
 namespace js = json_spirit;
 
-#define ETH_CATCH 1
+#define ETH_CATCH 0
 #define ETH_TIMED_IMPORTS 1
 
 #ifdef _WIN32
@@ -127,7 +127,8 @@ static const unsigned c_minCacheSize = 1024 * 1024 * 32;
 
 #endif
 
-BlockChain::BlockChain(bytes const& _genesisBlock, std::string const& _path, WithExisting _we, ProgressCallback const& _p)
+BlockChain::BlockChain(bytes const& _genesisBlock, std::unordered_map<Address, Account> const& _genesisState, std::string const& _path, WithExisting _we, ProgressCallback const& _p):
+	m_genesisState(_genesisState)
 {
 	// initialise deathrow.
 	m_cacheUsage.resize(c_collectionQueueSize);
@@ -136,6 +137,10 @@ BlockChain::BlockChain(bytes const& _genesisBlock, std::string const& _path, Wit
 	// Initialise with the genesis as the last block on the longest chain.
 	m_genesisBlock = _genesisBlock;
 	m_genesisHash = sha3(RLP(m_genesisBlock)[0].data());
+	m_genesisState = _genesisState;
+
+	// remove the next line real soon. we don't need to be supporting this forever.
+	upgradeDatabase(_path, genesisHash());
 
 	if (open(_path, _we) != c_minorProtocolVersion)
 		rebuild(_path, _p);
@@ -256,7 +261,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
 	ldb::DB::Open(o, extrasPath + "/extras", &m_extrasDB);
 
 	// Open a fresh state DB
-	State s(State::openDB(path, WithExisting::Kill), BaseState::CanonGenesis);
+	State s = genesisState(State::openDB(path, m_genesisHash, WithExisting::Kill));
 
 	// Clear all memos ready for replay.
 	m_details.clear();
@@ -286,9 +291,9 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
 		{
 			bytes b = block(queryExtras<BlockHash, ExtraBlockHash>(h256(u256(d)), m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value);
 
-			BlockInfo bi(b);
+			BlockInfo bi(&b);
 			if (_prepPoW)
-				Ethash::prep(bi);
+				Ethash::ensurePrecomputed((unsigned)bi.number);
 
 			if (bi.parentHash != lastHash)
 			{
@@ -351,7 +356,7 @@ tuple<ImportRoute, bool, unsigned> BlockChain::sync(BlockQueue& _bq, OverlayDB c
 				// Nonce & uncle nonces already verified in verification thread at this point.
 				ImportRoute r;
 				DEV_TIMED_ABOVE("Block import " + toString(block.verified.info.number), 500)
-					r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles);
+					r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidSeal & ~ImportRequirements::CheckUncles);
 				fresh += r.liveBlocks;
 				dead += r.deadBlocks;
 				goodTransactions += r.goodTranactions;
@@ -388,7 +393,7 @@ pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, O
 {
 	try
 	{
-		return make_pair(ImportResult::Success, import(verifyBlock(_block, m_onBad, _ir), _stateDB, _ir));
+		return make_pair(ImportResult::Success, import(verifyBlock(&_block, m_onBad, _ir), _stateDB, _ir));
 	}
 	catch (UnknownParent&)
 	{
@@ -419,7 +424,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
 	try
 #endif
 	{
-		block = verifyBlock(_block, m_onBad, _ir);
+		block = verifyBlock(&_block, m_onBad, _ir);
 	}
 #if ETH_CATCH
 	catch (Exception& ex)
@@ -471,7 +476,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
 		auto parentBlock = block(_block.info.parentHash);
 		clog(BlockChainDebug) << "isKnown:" << isKnown(_block.info.parentHash);
 		clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _block.info.number;
-		clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock);
+		clog(BlockChainDebug) << "Block:" << BlockInfo(&parentBlock);
 		clog(BlockChainDebug) << "RLP:" << RLP(parentBlock);
 		clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
 		exit(-1);
@@ -509,7 +514,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
 		// Check transactions are valid and that they result in a state equivalent to our state_root.
 		// Get total difficulty increase and update state, checking it.
 		State s(_db);
-		auto tdIncrease = s.enactOn(_block, *this, _ir);
+		auto tdIncrease = s.enactOn(_block, *this);
 
 		for (unsigned i = 0; i < s.pending().size(); ++i)
 		{
@@ -852,9 +857,9 @@ void BlockChain::rescue(OverlayDB& _db)
 		try
 		{
 			cout << "block..." << flush;
-			BlockInfo bi = info(h);
-			cout << "details..." << flush;
-			BlockDetails bd = details(h);
+			BlockInfo bi(block(h));
+			cout << "extras..." << flush;
+			details(h);
 			cout << "state..." << flush;
 			if (_db.exists(bi.stateRoot))
 				break;
@@ -1189,69 +1194,58 @@ bytes BlockChain::block(h256 const& _hash) const
 	return m_blocks[_hash];
 }
 
-VerifiedBlockRef BlockChain::verifyBlock(bytes const& _block, function<void(Exception&)> const& _onBad, ImportRequirements::value _ir)
+bytes BlockChain::headerData(h256 const& _hash) const
 {
-	VerifiedBlockRef res;
-	try
-	{
-		Strictness strictness = Strictness::CheckEverything;
-		if (~_ir & ImportRequirements::ValidNonce)
-			strictness = Strictness::IgnoreNonce;
+	if (_hash == m_genesisHash)
+		return BlockInfo::extractHeader(&m_genesisBlock).data().toBytes();
 
-		res.info.populate(_block, strictness);
-		res.info.verifyInternals(&_block);
-	}
-	catch (Exception& ex)
 	{
-		ex << errinfo_phase(1);
-		ex << errinfo_now(time(0));
-		ex << errinfo_block(_block);
-		if (_onBad)
-			_onBad(ex);
-		throw;
+		ReadGuard l(x_blocks);
+		auto it = m_blocks.find(_hash);
+		if (it != m_blocks.end())
+			return BlockInfo::extractHeader(&it->second).data().toBytes();
 	}
 
-	RLP r(_block);
-	unsigned i = 0;
-	for (auto const& uncle: r[2])
-	{
-		try
-		{
-			BlockInfo().populateFromHeader(RLP(uncle.data()), CheckEverything);
-		}
-		catch (Exception& ex)
-		{
-			ex << errinfo_phase(1);
-			ex << errinfo_uncleIndex(i);
-			ex << errinfo_now(time(0));
-			ex << errinfo_block(_block);
-			if (_onBad)
-				_onBad(ex);
-			throw;
-		}
-		++i;
-	}
-	i = 0;
-	for (RLP const& tr: r[1])
+	string d;
+	m_blocksDB->Get(m_readOptions, toSlice(_hash), &d);
+
+	if (d.empty())
 	{
-		bytesConstRef d = tr.data();
-		try
-		{
-			res.transactions.push_back(Transaction(d, CheckTransaction::Everything));
-		}
-		catch (Exception& ex)
-		{
-			ex << errinfo_phase(1);
-			ex << errinfo_transactionIndex(i);
-			ex << errinfo_transaction(d.toBytes());
-			ex << errinfo_block(_block);
-			if (_onBad)
-				_onBad(ex);
-			throw;
-		}
-		++i;
+		cwarn << "Couldn't find requested block:" << _hash;
+		return bytes();
 	}
-	res.block = bytesConstRef(&_block);
-	return res;
+
+	noteUsed(_hash);
+
+	WriteGuard l(x_blocks);
+	m_blocks[_hash].resize(d.size());
+	memcpy(m_blocks[_hash].data(), d.data(), d.size());
+
+	return BlockInfo::extractHeader(&m_blocks[_hash]).data().toBytes();
 }
 
+State BlockChain::genesisState(OverlayDB const& _db)
+{
+	State ret(_db, BaseState::Empty);
+	dev::eth::commit(m_genesisState, ret.m_state);		// bit horrible. maybe consider a better way of constructing it?
+	ret.m_state.db()->commit();			// have to use this db() since it's the one that has been altered with the above commit.
+	ret.m_previousBlock = BlockInfo(&m_genesisBlock);
+	return ret;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index 638c9c3af..50965f2b6 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -37,6 +37,7 @@
 #include "Transaction.h"
 #include "BlockQueue.h"
 #include "VerifiedBlock.h"
+#include "State.h"
 
 namespace std
 {
@@ -86,6 +87,13 @@ enum {
 };
 
 using ProgressCallback = std::function<void(unsigned, unsigned)>;
+using StateDefinition = std::unordered_map<Address, Account>;
+
+class VersionChecker
+{
+public:
+	VersionChecker(std::string const& _dbPath, h256 const& _genesisHash);
+};
 
 /**
  * @brief Implements the blockchain database. All data this gives is disk-backed.
@@ -94,7 +102,7 @@ using ProgressCallback = std::function<void(unsigned, unsigned)>;
 class BlockChain
 {
 public:
-	BlockChain(bytes const& _genesisBlock, std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _p = ProgressCallback());
+	BlockChain(bytes const& _genesisBlock, StateDefinition const& _genesisState, std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _p = ProgressCallback());
 	~BlockChain();
 
 	/// Attempt a database re-open.
@@ -120,14 +128,17 @@ public:
 	/// Returns true if the given block is known (though not necessarily a part of the canon chain).
 	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 const& _hash) const { return BlockInfo(block(_hash), IgnoreNonce, _hash); }
+	/// Get the partial-header of a block (or the most recent mined if none given). Thread-safe.
+	BlockInfo info(h256 const& _hash) const { return BlockInfo(headerData(_hash), CheckNothing, _hash, HeaderData); }
 	BlockInfo info() const { return info(currentHash()); }
 
 	/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
 	bytes block(h256 const& _hash) const;
 	bytes block() const { return block(currentHash()); }
-	bytes oldBlock(h256 const& _hash) const;
+
+	/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
+	bytes headerData(h256 const& _hash) const;
+	bytes headerData() const { return headerData(currentHash()); }
 
 	/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
 	BlockDetails details(h256 const& _hash) const { return queryExtras<BlockDetails, ExtraDetails>(_hash, m_details, x_details, NullBlockDetails); }
@@ -264,13 +275,16 @@ public:
 	/// Deallocate unused data.
 	void garbageCollect(bool _force = false);
 
-	/// Verify block and prepare it for enactment
-	static VerifiedBlockRef verifyBlock(bytes const& _block, std::function<void(Exception&)> const& _onBad = std::function<void(Exception&)>(), ImportRequirements::value _ir = ImportRequirements::Default);
-
 	/// Change the function that is called with a bad block.
 	template <class T> void setOnBad(T const& _t) { m_onBad = _t; }
 
-private:
+	/// Get a pre-made genesis State object.
+	State genesisState(OverlayDB const& _db);
+
+	/// Verify block and prepare it for enactment
+	virtual VerifiedBlockRef verifyBlock(bytesConstRef _block, std::function<void(Exception&)> const& _onBad, ImportRequirements::value _ir) const = 0;
+
+protected:
 	static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); }
 
 	unsigned open(std::string const& _path, WithExisting _we = WithExisting::Trust);
@@ -345,6 +359,7 @@ private:
 	/// Genesis block info.
 	h256 m_genesisHash;
 	bytes m_genesisBlock;
+	std::unordered_map<Address, Account> m_genesisState;
 
 	ldb::ReadOptions m_readOptions;
 	ldb::WriteOptions m_writeOptions;
@@ -354,6 +369,88 @@ private:
 	friend std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);
 };
 
+template <class Sealer>
+class FullBlockChain: public BlockChain
+{
+public:
+	using BlockHeader = typename Sealer::BlockHeader;
+
+	FullBlockChain(bytes const& _genesisBlock, StateDefinition const& _genesisState, std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _p = ProgressCallback()):
+		BlockChain(_genesisBlock, _genesisState, _path, _we, _p)
+	{}
+
+	/// Get the header of a block (or the most recent mined if none given). Thread-safe.
+	typename Sealer::BlockHeader header(h256 const& _hash) const { return typename Sealer::BlockHeader(headerData(_hash), IgnoreSeal, _hash, HeaderData); }
+	typename Sealer::BlockHeader header() const { return header(currentHash()); }
+
+	virtual VerifiedBlockRef verifyBlock(bytesConstRef _block, std::function<void(Exception&)> const& _onBad, ImportRequirements::value _ir) const override
+	{
+		VerifiedBlockRef res;
+
+		try
+		{
+			BlockHeader h(_block, (_ir & ImportRequirements::ValidSeal) ? Strictness::CheckEverything : Strictness::QuickNonce);
+			h.verifyInternals(_block);
+			h.verifyParent(header(h.parentHash));
+			res.info = static_cast<BlockInfo&>(h);
+		}
+		catch (Exception& ex)
+		{
+			ex << errinfo_phase(1);
+			ex << errinfo_now(time(0));
+			ex << errinfo_block(_block.toBytes());
+			if (_onBad)
+				_onBad(ex);
+			throw;
+		}
+
+		RLP r(_block);
+		unsigned i = 0;
+		if (_ir && ImportRequirements::UncleBasic)
+			for (auto const& uncle: r[2])
+			{
+				try
+				{
+					BlockHeader().populateFromHeader(RLP(uncle.data()), (_ir & ImportRequirements::UncleSeals) ? Strictness::CheckEverything : Strictness::IgnoreSeal);
+				}
+				catch (Exception& ex)
+				{
+					ex << errinfo_phase(1);
+					ex << errinfo_uncleIndex(i);
+					ex << errinfo_now(time(0));
+					ex << errinfo_block(_block.toBytes());
+					if (_onBad)
+						_onBad(ex);
+					throw;
+				}
+				++i;
+			}
+		i = 0;
+		if (_ir && ImportRequirements::TransactionBasic)
+			for (RLP const& tr: r[1])
+			{
+				bytesConstRef d = tr.data();
+				try
+				{
+					res.transactions.push_back(Transaction(d, (_ir & ImportRequirements::TransactionSignatures) ? CheckTransaction::Everything : CheckTransaction::None));
+				}
+				catch (Exception& ex)
+				{
+					ex << errinfo_phase(1);
+					ex << errinfo_transactionIndex(i);
+					ex << errinfo_transaction(d.toBytes());
+					ex << errinfo_block(_block.toBytes());
+					if (_onBad)
+						_onBad(ex);
+					throw;
+				}
+				++i;
+			}
+		res.block = bytesConstRef(_block);
+		return res;
+	}
+};
+
 std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);
 
 }
diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp
index 2cf2a7583..a59326b77 100644
--- a/libethereum/BlockChainSync.cpp
+++ b/libethereum/BlockChainSync.cpp
@@ -183,11 +183,11 @@ void BlockChainSync::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const
 
 	for (unsigned i = 0; i < itemCount; ++i)
 	{
-		auto h = BlockInfo::headerHash(_r[i].data());
+		auto h = BlockInfo::headerHashFromBlock(_r[i].data());
 		if (_peer->m_sub.noteBlock(h))
 		{
 			_peer->addRating(10);
-			switch (host().bq().import(_r[i].data(), host().chain()))
+			switch (host().bq().import(_r[i].data()))
 			{
 			case ImportResult::Success:
 				success++;
@@ -219,8 +219,7 @@ void BlockChainSync::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const
 				logNewBlock(h);
 				if (m_state == SyncState::NewBlocks)
 				{
-					BlockInfo bi;
-					bi.populateFromHeader(_r[i][0]);
+					BlockInfo bi(_r[i].data());
 					if (bi.number > maxUnknownNumber)
 					{
 						maxUnknownNumber = bi.number;
@@ -268,13 +267,13 @@ void BlockChainSync::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP con
 {
 	DEV_INVARIANT_CHECK;
 	RecursiveGuard l(x_sync);
-	auto h = BlockInfo::headerHash(_r[0].data());
+	auto h = BlockInfo::headerHashFromBlock(_r[0].data());
 
 	if (_r.itemCount() != 2)
 		_peer->disable("NewBlock without 2 data fields.");
 	else
 	{
-		switch (host().bq().import(_r[0].data(), host().chain()))
+		switch (host().bq().import(_r[0].data()))
 		{
 		case ImportResult::Success:
 			_peer->addRating(100);
diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp
index b6c548c1f..6b400b236 100644
--- a/libethereum/BlockQueue.cpp
+++ b/libethereum/BlockQueue.cpp
@@ -110,7 +110,7 @@ void BlockQueue::verifierBody()
 		swap(work.block, res.blockData);
 		try
 		{
-			res.verified = BlockChain::verifyBlock(res.blockData, m_onBad);
+			res.verified = m_bc->verifyBlock(&res.blockData, m_onBad, CheckEverything);
 		}
 		catch (...)
 		{
@@ -183,11 +183,11 @@ void BlockQueue::drainVerified_WITH_BOTH_LOCKS()
 	}
 }
 
-ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs)
+ImportResult BlockQueue::import(bytesConstRef _block, bool _isOurs)
 {
 	clog(BlockQueueTraceChannel) << std::this_thread::get_id();
 	// Check if we already know this block.
-	h256 h = BlockInfo::headerHash(_block);
+	h256 h = BlockInfo::headerHashFromBlock(_block);
 
 	clog(BlockQueueTraceChannel) << "Queuing block" << h << "for import...";
 
@@ -200,14 +200,12 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
 		return ImportResult::AlreadyKnown;
 	}
 
-	// VERIFY: populates from the block and checks the block is internally coherent.
 	BlockInfo bi;
-
 	try
 	{
-		// TODO: quick verify
-		bi.populate(_block);
-		bi.verifyInternals(_block);
+		// TODO: quick verification of seal - will require BlockQueue to be templated on Sealer
+		// VERIFY: populates from the block and checks the block is internally coherent.
+		bi = m_bc->verifyBlock(_block, m_onBad, ImportRequirements::None).info;
 	}
 	catch (Exception const& _e)
 	{
@@ -218,7 +216,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
 	clog(BlockQueueTraceChannel) << "Block" << h << "is" << bi.number << "parent is" << bi.parentHash;
 
 	// Check block doesn't already exist first!
-	if (_bc.isKnown(h))
+	if (m_bc->isKnown(h))
 	{
 		cblockq << "Already known in chain.";
 		return ImportResult::AlreadyInChain;
@@ -240,7 +238,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
 		m_unknownSize += _block.size();
 		m_unknownCount++;
 		m_difficulty += bi.difficulty;
-		bool unknown =  !m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash);
+		bool unknown =  !m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !m_bc->isKnown(bi.parentHash);
 		return unknown ? ImportResult::FutureTimeUnknown : ImportResult::FutureTimeKnown;
 	}
 	else
@@ -253,7 +251,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
 			// bad parent; this is bad too, note it as such
 			return ImportResult::BadChain;
 		}
-		else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
+		else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !m_bc->isKnown(bi.parentHash))
 		{
 			// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
 			clog(BlockQueueTraceChannel) << "OK - queued as unknown parent:" << bi.parentHash;
@@ -374,7 +372,7 @@ bool BlockQueue::doneDrain(h256s const& _bad)
 	return !m_readySet.empty();
 }
 
-void BlockQueue::tick(BlockChain const& _bc)
+void BlockQueue::tick()
 {
 	vector<pair<h256, bytes>> todo;
 	{
@@ -406,7 +404,7 @@ void BlockQueue::tick(BlockChain const& _bc)
 	cblockq << "Importing" << todo.size() << "past-future blocks.";
 
 	for (auto const& b: todo)
-		import(&b.second, _bc);
+		import(&b.second);
 }
 
 template <class T> T advanced(T _t, unsigned _n)
diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h
index b9e6f5b3b..97fca7c72 100644
--- a/libethereum/BlockQueue.h
+++ b/libethereum/BlockQueue.h
@@ -76,11 +76,13 @@ public:
 	BlockQueue();
 	~BlockQueue();
 
+	void setChain(BlockChain const& _bc) { m_bc = &_bc; }
+
 	/// Import a block into the queue.
-	ImportResult import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs = false);
+	ImportResult import(bytesConstRef _block, bool _isOurs = false);
 
 	/// Notes that time has moved on and some blocks that used to be "in the future" may no be valid.
-	void tick(BlockChain const& _bc);
+	void tick();
 
 	/// Grabs at most @a _max of the blocks that are ready, giving them in the correct order for insertion into the chain.
 	/// Don't forget to call doneDrain() once you're done importing.
@@ -138,6 +140,8 @@ private:
 	void updateBad_WITH_LOCK(h256 const& _bad);
 	void drainVerified_WITH_BOTH_LOCKS();
 
+	BlockChain const* m_bc;												///< The blockchain into which our imports go.
+
 	mutable boost::shared_mutex m_lock;									///< General lock for the sets, m_future and m_unknown.
 	h256Hash m_drainingSet;												///< All blocks being imported.
 	h256Hash m_readySet;												///< All blocks ready for chain import.
diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp
index 4e6d89243..eee4b98b7 100644
--- a/libethereum/CanonBlockChain.cpp
+++ b/libethereum/CanonBlockChain.cpp
@@ -27,7 +27,6 @@
 #include <libdevcore/RLP.h>
 #include <libdevcore/FileSystem.h>
 #include <libethcore/Exceptions.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/BlockInfo.h>
 #include <libethcore/Params.h>
 #include <liblll/Compiler.h>
@@ -41,14 +40,44 @@ namespace js = json_spirit;
 
 #define ETH_CATCH 1
 
-std::unordered_map<Address, Account> const& dev::eth::genesisState()
+std::unique_ptr<Ethash::BlockHeader> CanonBlockChain<Ethash>::s_genesis;
+boost::shared_mutex CanonBlockChain<Ethash>::x_genesis;
+Nonce CanonBlockChain<Ethash>::s_nonce(u64(42));
+std::string CanonBlockChain<Ethash>::s_genesisStateJSON;
+
+CanonBlockChain<Ethash>::CanonBlockChain(std::string const& _path, WithExisting _we, ProgressCallback const& _pc):
+	FullBlockChain<Ethash>(createGenesisBlock(), createGenesisState(), _path, _we, _pc)
+{
+}
+
+bytes CanonBlockChain<Ethash>::createGenesisBlock()
+{
+	RLPStream block(3);
+
+	h256 stateRoot;
+	{
+		MemoryDB db;
+		SecureTrieDB<Address, MemoryDB> state(&db);
+		state.init();
+		dev::eth::commit(createGenesisState(), state);
+		stateRoot = state.root();
+	}
+
+	block.appendList(15)
+			<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << c_genesisGasLimit << 0 << (unsigned)0 << string() << h256() << s_nonce;
+	block.appendRaw(RLPEmptyList);
+	block.appendRaw(RLPEmptyList);
+	return block.out();
+}
+
+unordered_map<Address, Account> CanonBlockChain<Ethash>::createGenesisState()
 {
 	static std::unordered_map<Address, Account> s_ret;
 
 	if (s_ret.empty())
 	{
 		js::mValue val;
-		json_spirit::read_string(c_genesisInfo, val);
+		json_spirit::read_string(s_genesisStateJSON.empty() ? c_genesisInfo : s_genesisStateJSON, val);
 		for (auto account: val.get_obj())
 		{
 			u256 balance;
@@ -68,53 +97,29 @@ std::unordered_map<Address, Account> const& dev::eth::genesisState()
 	return s_ret;
 }
 
-// TODO: place Registry in here.
-
-std::unique_ptr<BlockInfo> CanonBlockChain::s_genesis;
-boost::shared_mutex CanonBlockChain::x_genesis;
-Nonce CanonBlockChain::s_nonce(u64(42));
-
-bytes CanonBlockChain::createGenesisBlock()
-{
-	RLPStream block(3);
-
-	h256 stateRoot;
-	{
-		MemoryDB db;
-		SecureTrieDB<Address, MemoryDB> state(&db);
-		state.init();
-		dev::eth::commit(genesisState(), db, state);
-		stateRoot = state.root();
-	}
-
-	block.appendList(15)
-			<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << c_genesisGasLimit << 0 << (unsigned)0 << string() << h256() << s_nonce;
-	block.appendRaw(RLPEmptyList);
-	block.appendRaw(RLPEmptyList);
-	return block.out();
-}
-
-CanonBlockChain::CanonBlockChain(std::string const& _path, WithExisting _we, ProgressCallback const& _pc):
-	BlockChain(createGenesisBlock(), _path, _we, _pc)
+void CanonBlockChain<Ethash>::setGenesisState(std::string const& _json)
 {
+	WriteGuard l(x_genesis);
+	s_genesisStateJSON = _json;
+	s_genesis.reset();
 }
 
-void CanonBlockChain::setGenesisNonce(Nonce const& _n)
+void CanonBlockChain<Ethash>::setGenesisNonce(Nonce const& _n)
 {
 	WriteGuard l(x_genesis);
 	s_nonce = _n;
 	s_genesis.reset();
 }
 
-BlockInfo const& CanonBlockChain::genesis()
+Ethash::BlockHeader const& CanonBlockChain<Ethash>::genesis()
 {
 	UpgradableGuard l(x_genesis);
 	if (!s_genesis)
 	{
 		auto gb = createGenesisBlock();
 		UpgradeGuard ul(l);
-		s_genesis.reset(new BlockInfo);
-		s_genesis->populate(&gb);
+		s_genesis.reset(new Ethash::BlockHeader);
+		s_genesis->populate(&gb, CheckEverything);
 	}
 	return *s_genesis;
 }
diff --git a/libethereum/CanonBlockChain.h b/libethereum/CanonBlockChain.h
index c16479f0d..d79926703 100644
--- a/libethereum/CanonBlockChain.h
+++ b/libethereum/CanonBlockChain.h
@@ -26,6 +26,7 @@
 #include <libdevcore/Exceptions.h>
 #include <libethcore/Common.h>
 #include <libethcore/BlockInfo.h>
+#include <libethcore/Ethash.h>
 #include <libdevcore/Guards.h>
 #include "BlockDetails.h"
 #include "Account.h"
@@ -45,7 +46,32 @@ std::unordered_map<Address, Account> const& genesisState();
  * @threadsafe
  * @todo Make not memory hog (should actually act as a cache and deallocate old entries).
  */
-class CanonBlockChain: public BlockChain
+template <class Sealer>
+class CanonBlockChain: public FullBlockChain<Sealer>
+{
+public:
+	CanonBlockChain(WithExisting _we = WithExisting::Trust, ProgressCallback const& _pc = ProgressCallback()): CanonBlockChain<Sealer>(std::string(), _we, _pc) {}
+	CanonBlockChain(std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _pc = ProgressCallback()):
+		FullBlockChain<Sealer>(createGenesisBlock(), StateDefinition(), _path, _we, _pc) {}
+	~CanonBlockChain() {}
+
+	/// @returns the genesis block as its RLP-encoded byte array.
+	/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
+	static bytes createGenesisBlock()
+	{
+		RLPStream block(3);
+		block.appendList(Sealer::BlockHeader::Fields)
+				<< h256() << EmptyListSHA3 << h160() << EmptyTrie << EmptyTrie << EmptyTrie << LogBloom() << 1 << 0 << (u256(1) << 255) << 0 << (unsigned)0 << std::string();
+		bytes sealFields = typename Sealer::BlockHeader().sealFieldsRLP();
+		block.appendRaw(sealFields, Sealer::BlockHeader::SealFields);
+		block.appendRaw(RLPEmptyList);
+		block.appendRaw(RLPEmptyList);
+		return block.out();
+	}
+};
+
+template <>
+class CanonBlockChain<Ethash>: public FullBlockChain<Ethash>
 {
 public:
 	CanonBlockChain(WithExisting _we = WithExisting::Trust, ProgressCallback const& _pc = ProgressCallback()): CanonBlockChain(std::string(), _we, _pc) {}
@@ -53,22 +79,35 @@ public:
 	~CanonBlockChain() {}
 
 	/// @returns the genesis block header.
-	static BlockInfo const& genesis();
+	static Ethash::BlockHeader const& genesis();
 
 	/// @returns the genesis block as its RLP-encoded byte array.
 	/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
 	static bytes createGenesisBlock();
 
+	/// @returns the genesis block as its RLP-encoded byte array.
+	/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
+	static std::unordered_map<Address, Account> createGenesisState();
+
 	/// Alter the value of the genesis block's nonce.
 	/// @warning Unless you're very careful, make sure you call this right at the start of the
 	/// program, before anything has had the chance to use this class at all.
 	static void setGenesisNonce(Nonce const& _n);
 
+	/// Alter all the genesis block's state by giving a JSON string with account details.
+	/// @TODO implement.
+	/// @warning Unless you're very careful, make sure you call this right at the start of the
+	/// program, before anything has had the chance to use this class at all.
+	static void setGenesisState(std::string const&);
+
+	// TODO: setGenesisTimestamp, ...ExtraData, ...Difficulty, ...GasLimit,
+
 private:
 	/// Static genesis info and its lock.
 	static boost::shared_mutex x_genesis;
-	static std::unique_ptr<BlockInfo> s_genesis;
+	static std::unique_ptr<Ethash::BlockHeader> s_genesis;
 	static Nonce s_nonce;
+	static std::string s_genesisStateJSON;
 };
 
 }
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index 918480263..ec37302a2 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -72,47 +72,43 @@ static const Addresses c_canaries =
 	Address("ace7813896a84d3f5f80223916a5353ab16e46e6")			// christoph
 };
 
-VersionChecker::VersionChecker(string const& _dbPath)
+Client::Client(std::shared_ptr<GasPricer> _gp):
+	Worker("eth", 0),
+	m_gp(_gp ? _gp : make_shared<TrivialGasPricer>())
 {
-	upgradeDatabase(_dbPath);
 }
 
-Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId):
-	Client(_extNet, make_shared<TrivialGasPricer>(), _dbPath, _forceAction, _networkId)
+void Client::init(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId)
 {
-	startWorking();
-}
+	// Cannot be opened until after blockchain is open, since BlockChain may upgrade the database.
+	// TODO: consider returning the upgrade mechanism here. will delaying the opening of the blockchain database
+	// until after the construction.
+	m_stateDB = State::openDB(_dbPath, bc().genesisHash(), _forceAction);
+	m_preMine = State(m_stateDB);
+	m_postMine = State(m_stateDB);
+	// LAZY. TODO: move genesis state construction/commiting to stateDB openning and have this just take the root from the genesis block.
+	m_preMine = bc().genesisState(m_stateDB);
 
-Client::Client(p2p::Host* _extNet, std::shared_ptr<GasPricer> _gp, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId):
-	Worker("eth", 0),
-	m_vc(_dbPath),
-	m_bc(_dbPath, _forceAction, [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }),
-	m_gp(_gp),
-	m_stateDB(State::openDB(_dbPath, _forceAction)),
-	m_preMine(m_stateDB, BaseState::CanonGenesis),
-	m_postMine(m_stateDB)
-{
-	if (_forceAction == WithExisting::Rescue)
-		m_bc.rescue(m_stateDB);
+	m_bq.setChain(bc());
 
 	m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30);
 	m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); });	// TODO: should read m_tq->onReady(thisThread, syncTransactionQueue);
 	m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); });			// TODO: should read m_bq->onReady(thisThread, syncBlockQueue);
 	m_bq.setOnBad([=](Exception& ex){ this->onBadBlock(ex); });
-	m_bc.setOnBad([=](Exception& ex){ this->onBadBlock(ex); });
-	m_sealEngine = shared_ptr<SealEngineFace>(Ethash::createSealEngine());
-	m_sealEngine->onSolutionFound([=](Ethash::Solution const& s){ return this->submitWork(s); });
+	bc().setOnBad([=](Exception& ex){ this->onBadBlock(ex); });
 
-	m_gp->update(m_bc);
+	if (_forceAction == WithExisting::Rescue)
+		m_bc.rescue(m_stateDB);
+
+	m_gp->update(bc());
 
-	auto host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId));
+	auto host = _extNet->registerCapability(new EthereumHost(bc(), m_tq, m_bq, _networkId));
 	m_host = host;
 	_extNet->addCapability(host, EthereumHost::staticName(), EthereumHost::c_oldProtocolVersion); //TODO: remove this one v61+ protocol is common
 
 	if (_dbPath.size())
 		Defaults::setDBPath(_dbPath);
 	doWork();
-
 	startWorking();
 }
 
@@ -125,13 +121,13 @@ ImportResult Client::queueBlock(bytes const& _block, bool _isSafe)
 {
 	if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 10000)
 		this_thread::sleep_for(std::chrono::milliseconds(500));
-	return m_bq.import(&_block, bc(), _isSafe);
+	return m_bq.import(&_block, _isSafe);
 }
 
 tuple<ImportRoute, bool, unsigned> Client::syncQueue(unsigned _max)
 {
 	stopWorking();
-	return m_bc.sync(m_bq, m_stateDB, _max);
+	return bc().sync(m_bq, m_stateDB, _max);
 }
 
 void Client::onBadBlock(Exception& _ex) const
@@ -294,7 +290,7 @@ void Client::startedWorking()
 	clog(ClientTrace) << "startedWorking()";
 
 	DEV_WRITE_GUARDED(x_preMine)
-		m_preMine.sync(m_bc);
+		m_preMine.sync(bc());
 	DEV_READ_GUARDED(x_preMine)
 	{
 		DEV_WRITE_GUARDED(x_working)
@@ -309,7 +305,7 @@ void Client::doneWorking()
 	// Synchronise the state according to the head of the block chain.
 	// TODO: currently it contains keys for *all* blocks. Make it remove old ones.
 	DEV_WRITE_GUARDED(x_preMine)
-		m_preMine.sync(m_bc);
+		m_preMine.sync(bc());
 	DEV_READ_GUARDED(x_preMine)
 	{
 		DEV_WRITE_GUARDED(x_working)
@@ -328,7 +324,7 @@ void Client::killChain()
 
 	m_tq.clear();
 	m_bq.clear();
-	m_farm.disable();
+	m_sealEngine->cancelGeneration();
 
 	{
 		WriteGuard l(x_postMine);
@@ -340,10 +336,10 @@ void Client::killChain()
 		m_working = State();
 
 		m_stateDB = OverlayDB();
-		m_stateDB = State::openDB(Defaults::dbPath(), WithExisting::Kill);
-		m_bc.reopen(Defaults::dbPath(), WithExisting::Kill);
+		m_stateDB = State::openDB(Defaults::dbPath(), bc().genesisHash(), WithExisting::Kill);
+		bc().reopen(Defaults::dbPath(), WithExisting::Kill);
 
-		m_preMine = State(m_stateDB, BaseState::CanonGenesis);
+		m_preMine = bc().genesisState(m_stateDB);
 		m_postMine = State(m_stateDB);
 	}
 
@@ -415,8 +411,8 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Hash&
 void Client::appendFromNewBlock(h256 const& _block, h256Hash& io_changed)
 {
 	// TODO: more precise check on whether the txs match.
-	auto d = m_bc.info(_block);
-	auto receipts = m_bc.receipts(_block).receipts;
+	auto d = bc().info(_block);
+	auto receipts = bc().receipts(_block).receipts;
 
 	Guard l(x_filtersWatches);
 	io_changed.insert(ChainChangedFilter);
@@ -449,17 +445,22 @@ void Client::setForceMining(bool _enable)
 		startMining();
 }
 
-MiningProgress Client::miningProgress() const
+bool Client::isMining() const
 {
-	if (m_farm.isMining())
-		return m_farm.miningProgress();
-	return MiningProgress();
+	return Ethash::isWorking(m_sealEngine.get());
+}
+
+WorkingProgress Client::miningProgress() const
+{
+	if (Ethash::isWorking(m_sealEngine.get()))
+		return Ethash::workingProgress(m_sealEngine.get());
+	return WorkingProgress();
 }
 
 uint64_t Client::hashrate() const
 {
-	if (m_farm.isMining())
-		return m_farm.miningProgress().rate();
+	if (Ethash::isWorking(m_sealEngine.get()))
+		return Ethash::workingProgress(m_sealEngine.get()).rate();
 	return 0;
 }
 
@@ -504,45 +505,6 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
 	return ret;
 }
 
-ProofOfWork::WorkPackage Client::getWork()
-{
-	// lock the work so a later submission isn't invalidated by processing a transaction elsewhere.
-	// this will be reset as soon as a new block arrives, allowing more transactions to be processed.
-	bool oldShould = shouldServeWork();
-	m_lastGetWork = chrono::system_clock::now();
-
-	if (!m_mineOnBadChain && isChainBad())
-		return ProofOfWork::WorkPackage();
-
-	// if this request has made us bother to serve work, prep it now.
-	if (!oldShould && shouldServeWork())
-		onPostStateChanged();
-	else
-		// otherwise, set this to true so that it gets prepped next time.
-		m_remoteWorking = true;
-	return ProofOfWork::package(m_miningInfo);
-}
-
-bool Client::submitWork(ProofOfWork::Solution const& _solution)
-{
-	bytes newBlock;
-	DEV_WRITE_GUARDED(x_working)
-		if (!m_working.completeMine<ProofOfWork>(_solution))
-			return false;
-
-	DEV_READ_GUARDED(x_working)
-	{
-		DEV_WRITE_GUARDED(x_postMine)
-			m_postMine = m_working;
-		newBlock = m_working.blockData();
-	}
-
-	// OPTIMISE: very inefficient to not utilise the existing OverlayDB in m_postMine that contains all trie changes.
-	m_bq.import(&newBlock, m_bc, true);
-
-	return true;
-}
-
 unsigned static const c_syncMin = 1;
 unsigned static const c_syncMax = 1000;
 double static const c_targetDuration = 1;
@@ -553,7 +515,7 @@ void Client::syncBlockQueue()
 	ImportRoute ir;
 	unsigned count;
 	Timer t;
-	tie(ir, m_syncBlockQueue, count) = m_bc.sync(m_bq, m_stateDB, m_syncAmount);
+	tie(ir, m_syncBlockQueue, count) = bc().sync(m_bq, m_stateDB, m_syncAmount);
 	double elapsed = t.elapsed();
 
 	if (count)
@@ -577,7 +539,7 @@ void Client::syncTransactionQueue()
 	TransactionReceipts newPendingReceipts;
 
 	DEV_WRITE_GUARDED(x_working)
-		tie(newPendingReceipts, m_syncTransactionQueue) = m_working.sync(m_bc, m_tq, *m_gp);
+		tie(newPendingReceipts, m_syncTransactionQueue) = m_working.sync(bc(), m_tq, *m_gp);
 
 	if (newPendingReceipts.empty())
 		return;
@@ -590,7 +552,7 @@ void Client::syncTransactionQueue()
 		for (size_t i = 0; i < newPendingReceipts.size(); i++)
 			appendFromNewPending(newPendingReceipts[i], changeds, m_postMine.pending()[i].sha3());
 
-	// Tell farm about new transaction (i.e. restartProofOfWork mining).
+	// Tell farm about new transaction (i.e. restart mining).
 	onPostStateChanged();
 
 	// Tell watches about the new transactions.
@@ -607,7 +569,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
 	for (auto const& h: _ir.deadBlocks)
 	{
 		clog(ClientTrace) << "Dead block:" << h;
-		for (auto const& t: m_bc.transactions(h))
+		for (auto const& t: bc().transactions(h))
 		{
 			clog(ClientTrace) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None);
 			m_tq.import(t, IfDropped::Retry);
@@ -641,7 +603,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
 			newPreMine = m_preMine;
 
 		// TODO: use m_postMine to avoid re-evaluating our own blocks.
-		preChanged = newPreMine.sync(m_bc);
+		preChanged = newPreMine.sync(bc());
 
 		if (preChanged || m_postMine.address() != m_preMine.address())
 		{
@@ -700,7 +662,7 @@ void Client::rejigMining()
 	{
 		clog(ClientTrace) << "Rejigging mining...";
 		DEV_WRITE_GUARDED(x_working)
-			m_working.commitToMine(m_bc, m_extraData);
+			m_working.commitToMine(bc(), m_extraData);
 		DEV_READ_GUARDED(x_working)
 		{
 			DEV_WRITE_GUARDED(x_postMine)
@@ -709,10 +671,10 @@ void Client::rejigMining()
 		}
 
 		if (m_wouldMine)
-			m_farm.sealBlock(m_miningInfo);
+			m_sealEngine->generateSeal(m_miningInfo);
 	}
 	if (!m_wouldMine)
-		m_farm.disable();
+		m_sealEngine->cancelGeneration();
 }
 
 void Client::noteChanged(h256Hash const& _filters)
@@ -768,7 +730,7 @@ void Client::tick()
 	{
 		m_report.ticks++;
 		checkWatchGarbage();
-		m_bq.tick(m_bc);
+		m_bq.tick();
 		m_lastTick = chrono::system_clock::now();
 		if (m_report.ticks == 15)
 			clog(ClientTrace) << activityReport();
@@ -792,7 +754,7 @@ void Client::checkWatchGarbage()
 			uninstallWatch(i);
 
 		// blockchain GC
-		m_bc.garbageCollect();
+		bc().garbageCollect();
 
 		m_lastGarbageCollection = chrono::system_clock::now();
 	}
@@ -824,7 +786,7 @@ State Client::state(unsigned _txi, h256 _block) const
 	try
 	{
 		State ret(m_stateDB);
-		ret.populateFromChain(m_bc, _block);
+		ret.populateFromChain(bc(), _block);
 		return ret.fromPending(_txi);
 	}
 	catch (Exception& ex)
@@ -840,7 +802,7 @@ State Client::state(h256 const& _block, PopulationStatistics* o_stats) const
 	try
 	{
 		State ret(m_stateDB);
-		PopulationStatistics s = ret.populateFromChain(m_bc, _block);
+		PopulationStatistics s = ret.populateFromChain(bc(), _block);
 		if (o_stats)
 			swap(s, *o_stats);
 		return ret;
@@ -871,3 +833,61 @@ SyncStatus Client::syncStatus() const
 	auto h = m_host.lock();
 	return h ? h->status() : SyncStatus();
 }
+
+bool Client::submitSealed(bytes const& _header)
+{
+	DEV_WRITE_GUARDED(x_working)
+		if (!m_working.sealBlock(_header))
+			return false;
+
+	bytes newBlock;
+	DEV_READ_GUARDED(x_working)
+	{
+		DEV_WRITE_GUARDED(x_postMine)
+			m_postMine = m_working;
+		newBlock = m_working.blockData();
+	}
+
+	// OPTIMISE: very inefficient to not utilise the existing OverlayDB in m_postMine that contains all trie changes.
+	return m_bq.import(&newBlock, true) == ImportResult::Success;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+std::tuple<h256, h256, h256> EthashClient::getEthashWork()
+{
+	// lock the work so a later submission isn't invalidated by processing a transaction elsewhere.
+	// this will be reset as soon as a new block arrives, allowing more transactions to be processed.
+	bool oldShould = shouldServeWork();
+	m_lastGetWork = chrono::system_clock::now();
+
+	if (!m_mineOnBadChain && isChainBad())
+		return std::tuple<h256, h256, h256>();
+
+	// if this request has made us bother to serve work, prep it now.
+	if (!oldShould && shouldServeWork())
+		onPostStateChanged();
+	else
+		// otherwise, set this to true so that it gets prepped next time.
+		m_remoteWorking = true;
+	Ethash::BlockHeader bh = Ethash::BlockHeader(m_miningInfo);
+	return std::tuple<h256, h256, h256>(bh.boundary(), bh.hashWithout(), bh.seedHash());
+}
+
+bool EthashClient::submitEthashWork(h256 const& _mixHash, h64 const& _nonce)
+{
+	Ethash::manuallySubmitWork(m_sealEngine.get(), _mixHash, _nonce);
+	return true;
+}
+
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 9ae7c7e09..73609bd71 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -60,12 +60,6 @@ enum ClientWorkState
 	Deleted
 };
 
-class VersionChecker
-{
-public:
-	VersionChecker(std::string const& _dbPath);
-};
-
 struct ClientNote: public LogChannel { static const char* name(); static const int verbosity = 2; };
 struct ClientChat: public LogChannel { static const char* name(); static const int verbosity = 4; };
 struct ClientTrace: public LogChannel { static const char* name(); static const int verbosity = 7; };
@@ -81,25 +75,14 @@ std::ostream& operator<<(std::ostream& _out, ActivityReport const& _r);
 
 /**
  * @brief Main API hub for interfacing with Ethereum.
+ * Not to be used directly - subclass.
  */
 class Client: public ClientBase, Worker
 {
 public:
 	/// New-style Constructor.
-	explicit Client(
-		p2p::Host* _host,
-		std::string const& _dbPath = std::string(),
-		WithExisting _forceAction = WithExisting::Trust,
-		u256 _networkId = 0
-	);
-
-	explicit Client(
-		p2p::Host* _host,
-		std::shared_ptr<GasPricer> _gpForAdoption,		// pass it in with new.
-		std::string const& _dbPath = std::string(),
-		WithExisting _forceAction = WithExisting::Trust,
-		u256 _networkId = 0
-	);
+	/// Any final derived class's constructor should make sure they call init().
+	explicit Client(std::shared_ptr<GasPricer> _gpForAdoption);
 
 	/// Destructor.
 	virtual ~Client();
@@ -129,7 +112,7 @@ public:
 	/// Get the object representing the current state of Ethereum.
 	dev::eth::State postState() const { ReadGuard l(x_postMine); return m_postMine; }
 	/// Get the object representing the current canonical blockchain.
-	CanonBlockChain const& blockChain() const { return m_bc; }
+	BlockChain const& blockChain() const { return bc(); }
 	/// Get some information on the block queue.
 	BlockQueueStatus blockQueueStatus() const { return m_bq.status(); }
 	/// Get some information on the block queue.
@@ -176,26 +159,16 @@ public:
 	/// NOT thread-safe
 	void stopMining() override { m_wouldMine = false; rejigMining(); }
 	/// Are we mining now?
-	bool isMining() const override { return m_farm.isMining(); }
+	bool isMining() const override;
 	/// Are we mining now?
 	bool wouldMine() const override { return m_wouldMine; }
 	/// The hashrate...
 	uint64_t hashrate() const override;
 	/// Check the progress of the mining.
-	MiningProgress miningProgress() const override;
+	WorkingProgress miningProgress() const override;
 	/// Get and clear the mining history.
 	std::list<MineInfo> miningHistory();
 
-	/// Update to the latest transactions and get hash of the current block to be mined minus the
-	/// nonce (the 'work hash') and the difficulty to be met.
-	virtual ProofOfWork::WorkPackage getWork() override;
-
-	/** @brief Submit the proof for the proof-of-work.
-	 * @param _s A valid solution.
-	 * @return true if the solution was indeed valid and accepted.
-	 */
-	virtual bool submitWork(ProofOfWork::Solution const& _proof) override;
-
 	// Debug stuff:
 
 	DownloadMan const* downloadMan() const;
@@ -218,12 +191,20 @@ public:
 	/// Set the extra data that goes into mined blocks.
 	void setExtraData(bytes const& _extraData) { m_extraData = _extraData; }
 	/// Rewind to a prior head.
-	void rewind(unsigned _n) { m_bc.rewind(_n); }
+	void rewind(unsigned _n) { bc().rewind(_n); }
+	/// Rescue the chain.
+	void rescue() { bc().rescue(m_stateDB); }
+	/// Get the seal engine.
+	SealEngineFace* sealEngine() const { return m_sealEngine.get(); }
 
 protected:
+	/// Perform critical setup functions.
+	/// Must be called in the constructor of the finally derived class.
+	void init(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId);
+
 	/// InterfaceStub methods
-	virtual BlockChain& bc() override { return m_bc; }
-	virtual BlockChain const& bc() const override { return m_bc; }
+	virtual BlockChain& bc() override = 0;
+	virtual BlockChain const& bc() const override = 0;
 
 	/// Returns the state object for the full block (i.e. the terminal state) for index _h.
 	/// Works properly with LatestBlock and PendingBlock.
@@ -245,7 +226,10 @@ protected:
 	/// This doesn't actually make any callbacks, but incrememnts some counters in m_watches.
 	void noteChanged(h256Hash const& _filters);
 
-private:
+	/// Submit
+	bool submitSealed(bytes const& _s);
+
+protected:
 	/// Called when Worker is starting.
 	void startedWorking() override;
 
@@ -291,8 +275,6 @@ private:
 	/// @warning May be called from any thread.
 	void onBadBlock(Exception& _ex) const;
 
-	VersionChecker m_vc;					///< Dummy object to check & update the protocol version.
-	CanonBlockChain m_bc;					///< Maintains block database.
 	BlockQueue m_bq;						///< Maintains a list of incoming blocks not yet on the blockchain (to be imported).
 	std::shared_ptr<GasPricer> m_gp;		///< The gas pricer.
 
@@ -339,5 +321,64 @@ private:
 	bytes m_extraData;
 };
 
+template <class Sealer>
+class SpecialisedClient: public Client
+{
+public:
+	explicit SpecialisedClient(
+		p2p::Host* _host,
+		std::shared_ptr<GasPricer> _gpForAdoption,
+		std::string const& _dbPath = std::string(),
+		WithExisting _forceAction = WithExisting::Trust,
+		u256 _networkId = 0
+	):
+		Client(_gpForAdoption),
+		m_bc(_dbPath, _forceAction, [](unsigned d, unsigned t){ std::cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; })
+	{
+		m_sealEngine = std::shared_ptr<SealEngineFace>(Ethash::createSealEngine());
+		m_sealEngine->onSealGenerated([=](bytes const& header){
+			return this->submitSealed(header);
+		});
+		init(_host, _dbPath, _forceAction, _networkId);
+	}
+
+	/// Get the object representing the current canonical blockchain.
+	CanonBlockChain<Sealer> const& blockChain() const { return m_bc; }
+
+protected:
+	virtual BlockChain& bc() override { return m_bc; }
+	virtual BlockChain const& bc() const override { return m_bc; }
+
+protected:
+	CanonBlockChain<Sealer> m_bc;			///< Maintains block database.
+};
+
+class EthashClient: public SpecialisedClient<Ethash>
+{
+public:
+	/// Trivial forwarding constructor.
+	explicit EthashClient(
+		p2p::Host* _host,
+		std::shared_ptr<GasPricer> _gpForAdoption,
+		std::string const& _dbPath = std::string(),
+		WithExisting _forceAction = WithExisting::Trust,
+		u256 _networkId = 0
+	): SpecialisedClient<Ethash>(_host, _gpForAdoption, _dbPath, _forceAction, _networkId) {}
+
+	/// Update to the latest transactions and get hash of the current block to be mined minus the
+	/// nonce (the 'work hash') and the difficulty to be met.
+	virtual std::tuple<h256, h256, h256> getEthashWork() override;
+
+	/** @brief Submit the proof for the proof-of-work.
+	 * @param _s A valid solution.
+	 * @return true if the solution was indeed valid and accepted.
+	 */
+	virtual bool submitEthashWork(h256 const& _mixHash, h64 const& _nonce) override;
+
+protected:
+	virtual BlockChain& bc() override { return m_bc; }
+	virtual BlockChain const& bc() const override { return m_bc; }
+};
+
 }
 }
diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp
index f463b0195..769880269 100644
--- a/libethereum/ClientBase.cpp
+++ b/libethereum/ClientBase.cpp
@@ -357,7 +357,7 @@ BlockInfo ClientBase::uncle(h256 _blockHash, unsigned _i) const
 	auto bl = bc().block(_blockHash);
 	RLP b(bl);
 	if (_i < b[2].itemCount())
-		return BlockInfo::fromHeader(b[2][_i].data());
+		return BlockInfo(b[2][_i].data(), CheckNothing, h256(), HeaderData);
 	else
 		return BlockInfo();
 }
diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h
index 82f03def0..874f10548 100644
--- a/libethereum/ClientBase.h
+++ b/libethereum/ClientBase.h
@@ -156,9 +156,7 @@ public:
 	virtual bool isMining() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::isMining")); }
 	virtual bool wouldMine() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::wouldMine")); }
 	virtual uint64_t hashrate() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::hashrate")); }
-	virtual MiningProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::miningProgress")); }
-	virtual ProofOfWork::WorkPackage getWork() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::getWork")); }
-	virtual bool submitWork(ProofOfWork::Solution const&) override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::submitWork")); }
+	virtual WorkingProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::miningProgress")); }
 
 	State asOf(BlockNumber _h) const;
 
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index 973433af9..213e7fb26 100644
--- a/libethereum/Interface.h
+++ b/libethereum/Interface.h
@@ -25,7 +25,7 @@
 #include <libdevcore/CommonIO.h>
 #include <libdevcore/Guards.h>
 #include <libdevcrypto/Common.h>
-#include <libethcore/ProofOfWork.h>
+#include <libethcore/Ethash.h>
 #include "LogFilter.h"
 #include "Transaction.h"
 #include "AccountDiff.h"
@@ -207,12 +207,12 @@ public:
 	virtual uint64_t hashrate() const = 0;
 
 	/// Get hash of the current block to be mined minus the nonce (the 'work hash').
-	virtual ProofOfWork::WorkPackage getWork() = 0;
+	virtual std::tuple<h256, h256, h256> getEthashWork() { BOOST_THROW_EXCEPTION(InterfaceNotSupported("Interface::getEthashWork")); }
 	/// Submit the nonce for the proof-of-work.
-	virtual bool submitWork(ProofOfWork::Solution const& _proof) = 0;
+	virtual bool submitEthashWork(h256 const&, h64 const&) { BOOST_THROW_EXCEPTION(InterfaceNotSupported("Interface::submitEthashWork")); }
 
 	/// Check the progress of the mining.
-	virtual MiningProgress miningProgress() const = 0;
+	virtual WorkingProgress miningProgress() const = 0;
 
 protected:
 	int m_default = PendingBlock;
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 1656109a9..ee2078a07 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -55,7 +55,7 @@ const char* StateDetail::name() { return EthViolet "⚙" EthWhite " ◌"; }
 const char* StateTrace::name() { return EthViolet "⚙" EthGray " ◎"; }
 const char* StateChat::name() { return EthViolet "⚙" EthWhite " ◌"; }
 
-OverlayDB State::openDB(std::string const& _basePath, WithExisting _we)
+OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash, WithExisting _we)
 {
 	std::string path = _basePath.empty() ? Defaults::get()->m_dbPath : _basePath;
 
@@ -65,7 +65,7 @@ OverlayDB State::openDB(std::string const& _basePath, WithExisting _we)
 		boost::filesystem::remove_all(path + "/state");
 	}
 
-	path += "/" + toHex(CanonBlockChain::genesis().hash().ref().cropped(0, 4)) + "/" + toString(c_databaseVersion);
+	path += "/" + toHex(_genesisHash.ref().cropped(0, 4)) + "/" + toString(c_databaseVersion);
 	boost::filesystem::create_directories(path);
 
 	ldb::Options o;
@@ -103,20 +103,9 @@ State::State(OverlayDB const& _db, BaseState _bs, Address _coinbaseAddress):
 
 	paranoia("beginning of Genesis construction.", true);
 
-	if (_bs == BaseState::CanonGenesis)
-	{
-		dev::eth::commit(genesisState(), m_db, m_state);
-		m_db.commit();
-
-		paranoia("after DB commit of Genesis construction.", true);
-		m_previousBlock = CanonBlockChain::genesis();
-	}
-	else
-		m_previousBlock.clear();
-
-	resetCurrent();
-
-	assert(m_state.root() == m_previousBlock.stateRoot);
+	m_previousBlock.clear();
+	m_currentBlock.clear();
+//	assert(m_state.root() == m_previousBlock.stateRoot);
 
 	paranoia("end of normal construction.", true);
 }
@@ -139,17 +128,16 @@ PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const&
 		// Non-genesis:
 
 		// 1. Start at parent's end state (state root).
-		BlockInfo bip;
-		bip.populate(_bc.block(bi.parentHash));
-		sync(_bc, bi.parentHash, bip, _ir);
+		BlockInfo bip(_bc.block(bi.parentHash));
+		sync(_bc, bi.parentHash, bip);
 
 		// 2. Enact the block's transactions onto this state.
 		m_ourAddress = bi.coinbaseAddress;
 		Timer t;
-		auto vb = BlockChain::verifyBlock(b);
+		auto vb = _bc.verifyBlock(&b, function<void(Exception&)>(), _ir);
 		ret.verify = t.elapsed();
 		t.restart();
-		enact(vb, _bc, _ir);
+		enact(vb, _bc);
 		ret.enact = t.elapsed();
 	}
 	else
@@ -157,7 +145,7 @@ PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const&
 		// Genesis required:
 		// We know there are no transactions, so just populate directly.
 		m_state.init();
-		sync(_bc, _h, bi, _ir);
+		sync(_bc, _h, bi);
 	}
 
 	return ret;
@@ -294,7 +282,7 @@ void State::ensureCached(std::unordered_map<Address, Account>& _cache, Address _
 
 void State::commit()
 {
-	m_touched += dev::eth::commit(m_cache, m_db, m_state);
+	m_touched += dev::eth::commit(m_cache, m_state);
 	m_cache.clear();
 }
 
@@ -303,9 +291,8 @@ bool State::sync(BlockChain const& _bc)
 	return sync(_bc, _bc.currentHash());
 }
 
-bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, ImportRequirements::value _ir)
+bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi)
 {
-	(void)_ir;
 	bool ret = false;
 	// BLOCK
 	BlockInfo bi = _bi ? _bi : _bc.info(_block);
@@ -355,7 +342,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor
 		{
 			cwarn << "Unable to sync to" << bi.hash() << "; state root" << bi.stateRoot << "not found in database.";
 			cwarn << "Database corrupt: contains block without stateRoot:" << bi;
-			cwarn << "Bailing.";
+			cwarn << "Try rescuing the database by running: eth --rescue";
 			exit(-1);
 		}
 		m_previousBlock = bi;
@@ -404,7 +391,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor
 	return ret;
 }
 
-u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir)
+u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc)
 {
 #if ETH_TIMED_ENACTMENTS
 	Timer t;
@@ -432,7 +419,7 @@ u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, Impor
 	t.restart();
 #endif
 
-	sync(_bc, _block.info.parentHash, BlockInfo(), _ir);
+	sync(_bc, _block.info.parentHash, BlockInfo());
 	resetCurrent();
 
 #if ETH_TIMED_ENACTMENTS
@@ -441,7 +428,7 @@ u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, Impor
 #endif
 
 	m_previousBlock = biParent;
-	auto ret = enact(_block, _bc, _ir);
+	auto ret = enact(_block, _bc);
 
 #if ETH_TIMED_ENACTMENTS
 	enactment = t.elapsed();
@@ -591,7 +578,7 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire
 	RLP rlp(_block);
 
 	cleanup(false);
-	BlockInfo bi(_block, (_ir & ImportRequirements::ValidNonce) ? CheckEverything : IgnoreNonce);
+	BlockInfo bi(_block, (_ir & ImportRequirements::ValidSeal) ? CheckEverything : IgnoreSeal);
 	m_currentBlock = bi;
 	m_currentBlock.verifyInternals(_block);
 	m_currentBlock.noteDirty();
@@ -611,7 +598,7 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire
 	return ret.empty() ? "[]" : (ret + "]");
 }
 
-u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir)
+u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc)
 {
 	DEV_TIMED_FUNCTION_ABOVE(500);
 
@@ -627,8 +614,8 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
 		BOOST_THROW_EXCEPTION(InvalidParentHash());
 
 	// Populate m_currentBlock with the correct values.
-	m_currentBlock = _block.info;
 	m_currentBlock.noteDirty();
+	m_currentBlock = _block.info;
 
 //	cnote << "playback begins:" << m_state.root();
 //	cnote << m_state;
@@ -672,7 +659,7 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
 		InvalidReceiptsStateRoot ex;
 		ex << Hash256RequirementError(receiptsRoot, m_currentBlock.receiptsRoot);
 		ex << errinfo_receipts(receipts);
-		ex << errinfo_vmtrace(vmTrace(_block.block, _bc, _ir));
+		ex << errinfo_vmtrace(vmTrace(_block.block, _bc, ImportRequirements::None));
 		BOOST_THROW_EXCEPTION(ex);
 	}
 
@@ -719,7 +706,8 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
 				}
 				excluded.insert(h);
 
-				BlockInfo uncle = BlockInfo::fromHeader(i.data(), (_ir & ImportRequirements::CheckUncles) ? CheckEverything : IgnoreNonce,  h);
+				// IgnoreSeal since it's a VerifiedBlock.
+				BlockInfo uncle(i.data(), IgnoreSeal, h, HeaderData);
 
 				BlockInfo uncleParent;
 				if (!_bc.isKnown(uncle.parentHash))
@@ -829,6 +817,8 @@ void State::uncommitToMine()
 
 bool State::amIJustParanoid(BlockChain const& _bc)
 {
+	(void)_bc;
+	/*
 	commitToMine(_bc);
 
 	// Update difficulty according to timestamp.
@@ -848,7 +838,7 @@ bool State::amIJustParanoid(BlockChain const& _bc)
 		cnote << "PARANOIA root:" << s.rootHash();
 //		s.m_currentBlock.populate(&block.out(), false);
 //		s.m_currentBlock.verifyInternals(&block.out());
-		s.enact(BlockChain::verifyBlock(block.out()), _bc, false);	// don't check nonce for this since we haven't mined it yet.
+		s.enact(BlockChain::verifyBlock(block.out(), std::function<void(Exception&)>(), ImportRequirements::CheckUncles | ImportRequirements::CheckTransactions), _bc);	// don't check nonce for this since we haven't mined it yet.
 		s.cleanup(false);
 		return true;
 	}
@@ -860,7 +850,7 @@ bool State::amIJustParanoid(BlockChain const& _bc)
 	{
 		cwarn << "Bad block: " << _e.what();
 	}
-
+*/
 	return false;
 }
 
@@ -901,10 +891,9 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData)
 			for (auto const& u: us)
 				if (!excluded.count(u))	// ignore any uncles/mainline blocks that we know about.
 				{
-					BlockInfo ubi(_bc.block(u));
-					ubi.streamRLP(unclesData, WithProof);
+					uncleBlockHeaders.push_back(_bc.info(u));
+					unclesData.appendRaw(_bc.headerData(u));
 					++unclesCount;
-					uncleBlockHeaders.push_back(ubi);
 					if (unclesCount == 2)
 						break;
 				}
@@ -962,26 +951,30 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData)
 	m_committedToMine = true;
 }
 
-void State::completeMine()
+bool State::sealBlock(bytesConstRef _header)
 {
-	cdebug << "Completing mine!";
+	if (!m_committedToMine)
+		return false;
+
+	cdebug << "Sealing block!";
 	// Got it!
 
 	// Compile block:
 	RLPStream ret;
 	ret.appendList(3);
-	m_currentBlock.streamRLP(ret, WithProof);
+	ret.appendRaw(_header);
 	ret.appendRaw(m_currentTxs);
 	ret.appendRaw(m_currentUncles);
 	ret.swapOut(m_currentBytes);
-	m_currentBlock.noteDirty();
+	m_currentBlock = BlockInfo(_header, CheckNothing, h256(), HeaderData);
 	cnote << "Mined " << m_currentBlock.hash() << "(parent: " << m_currentBlock.parentHash << ")";
-/*	StructuredLogger::minedNewBlock(
+	// TODO: move into Sealer
+	StructuredLogger::minedNewBlock(
 		m_currentBlock.hash().abridged(),
-		m_currentBlock.proof.nonce.abridged(),
+		"",	// Can't give the nonce here.
 		"", //TODO: chain head hash here ??
 		m_currentBlock.parentHash.abridged()
-	);*/
+	);
 
 	// Quickly reset the transactions.
 	// TODO: Leave this in a better state than this limbo, or at least record that it's in limbo.
@@ -989,6 +982,8 @@ void State::completeMine()
 	m_receipts.clear();
 	m_transactionSet.clear();
 	m_lastTx = m_db;
+
+	return true;
 }
 
 bool State::addressInUse(Address _id) const
diff --git a/libethereum/State.h b/libethereum/State.h
index f6a8471ea..805215ee5 100644
--- a/libethereum/State.h
+++ b/libethereum/State.h
@@ -29,7 +29,6 @@
 #include <libdevcrypto/OverlayDB.h>
 #include <libethcore/Exceptions.h>
 #include <libethcore/BlockInfo.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/Miner.h>
 #include <libevm/ExtVMFace.h>
 #include "Account.h"
@@ -77,8 +76,7 @@ struct StateSafeExceptions: public LogChannel { static const char* name(); stati
 enum class BaseState
 {
 	PreExisting,
-	Empty,
-	CanonGenesis
+	Empty
 };
 
 enum class Permanence
@@ -104,6 +102,7 @@ class State
 	friend class dev::test::ImportTest;
 	friend class dev::test::StateLoader;
 	friend class Executive;
+	friend class BlockChain;
 
 public:
 	/// Default constructor; creates with a blank database prepopulated with the genesis block.
@@ -125,7 +124,7 @@ public:
 	~State();
 
 	/// Construct state object from arbitrary point in blockchain.
-	PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::Default);
+	PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::None);
 
 	/// Set the coinbase address for any transactions we do.
 	/// This causes a complete reset of current block.
@@ -133,8 +132,8 @@ public:
 	Address address() const { return m_ourAddress; }
 
 	/// Open a DB - useful for passing into the constructor & keeping for other states that are necessary.
-	static OverlayDB openDB(std::string const& _path, WithExisting _we = WithExisting::Trust);
-	static OverlayDB openDB(WithExisting _we = WithExisting::Trust) { return openDB(std::string(), _we); }
+	static OverlayDB openDB(std::string const& _path, h256 const& _genesisHash, WithExisting _we = WithExisting::Trust);
+	static OverlayDB openDB(h256 const& _genesisHash, WithExisting _we = WithExisting::Trust) { return openDB(std::string(), _genesisHash, _we); }
 	OverlayDB const& db() const { return m_db; }
 	OverlayDB& db() { return m_db; }
 
@@ -163,22 +162,20 @@ public:
 
 	/// Pass in a solution to the proof-of-work.
 	/// @returns true iff we were previously committed to mining.
-	template <class PoW>
-	bool completeMine(typename PoW::Solution const& _result)
-	{
-		if (!m_committedToMine)
-			return false;
-
-		m_currentBlock.proof = _result;
-		if (!PoW::verify(m_currentBlock))
-			return false;
-
-//		cnote << "Completed" << m_currentBlock.headerHash(WithoutProof) << m_currentBlock.proof.nonce << m_currentBlock.difficulty << PoW::verify(m_currentBlock);
-
-		completeMine();
-
-		return true;
-	}
+	/// TODO: verify it prior to calling this.
+	/** Commit to DB and build the final block if the previous call to mine()'s result is completion.
+	 * Typically looks like:
+	 * @code
+	 * while (notYetMined)
+	 * {
+	 * // lock
+	 * commitToMine(_blockChain);  // will call uncommitToMine if a repeat.
+	 * completeMine();
+	 * // unlock
+	 * @endcode
+	 */
+	bool sealBlock(bytes const& _header) { return sealBlock(&_header); }
+	bool sealBlock(bytesConstRef _header);
 
 	/// Get the complete current block, including valid nonce.
 	/// Only valid after mine() returns true.
@@ -295,11 +292,11 @@ public:
 	bool sync(BlockChain const& _bc);
 
 	/// Sync with the block chain, but rather than synching to the latest block, instead sync to the given block.
-	bool sync(BlockChain const& _bc, h256 _blockHash, BlockInfo const& _bi = BlockInfo(), ImportRequirements::value _ir = ImportRequirements::Default);
+	bool sync(BlockChain const& _bc, h256 const& _blockHash, BlockInfo const& _bi = BlockInfo());
 
 	/// Execute all transactions within a given block.
 	/// @returns the additional total difficulty.
-	u256 enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
+	u256 enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc);
 
 	/// Returns back to a pristine state after having done a playback.
 	/// @arg _fullCommit if true flush everything out to disk. If false, this effectively only validates
@@ -313,19 +310,6 @@ public:
 	void resetCurrent();
 
 private:
-	/** Commit to DB and build the final block if the previous call to mine()'s result is completion.
-	 * Typically looks like:
-	 * @code
-	 * while (notYetMined)
-	 * {
-	 * // lock
-	 * commitToMine(_blockChain);  // will call uncommitToMine if a repeat.
-	 * completeMine();
-	 * // unlock
-	 * @endcode
-	 */
-	void completeMine();
-
 	/// Undo the changes to the state for committing to mine.
 	void uncommitToMine();
 
@@ -340,7 +324,7 @@ private:
 
 	/// Execute the given block, assuming it corresponds to m_currentBlock.
 	/// Throws on failure.
-	u256 enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir = ImportRequirements::Default);
+	u256 enact(VerifiedBlockRef const& _block, BlockChain const& _bc);
 
 	/// Finalise the block, applying the earned rewards.
 	void applyRewards(std::vector<BlockInfo> const& _uncleBlockHeaders);
@@ -386,7 +370,7 @@ private:
 std::ostream& operator<<(std::ostream& _out, State const& _s);
 
 template <class DB>
-AddressHash commit(std::unordered_map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state)
+AddressHash commit(std::unordered_map<Address, Account> const& _cache, SecureTrieDB<Address, DB>& _state)
 {
 	AddressHash ret;
 	for (auto const& i: _cache)
@@ -406,7 +390,7 @@ AddressHash commit(std::unordered_map<Address, Account> const& _cache, DB& _db,
 				}
 				else
 				{
-					SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
+					SecureTrieDB<h256, DB> storageDB(_state.db(), i.second.baseRoot());
 					for (auto const& j: i.second.storageOverlay())
 						if (j.second)
 							storageDB.insert(j.first, rlp(j.second));
@@ -419,7 +403,7 @@ AddressHash commit(std::unordered_map<Address, Account> const& _cache, DB& _db,
 				if (i.second.isFreshCode())
 				{
 					h256 ch = sha3(i.second.code());
-					_db.insert(ch, &i.second.code());
+					_state.db()->insert(ch, &i.second.code());
 					s << ch;
 				}
 				else
diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp
index e02012cd5..1b97f82e7 100644
--- a/libethereum/Utility.cpp
+++ b/libethereum/Utility.cpp
@@ -91,7 +91,7 @@ bytes dev::eth::parseData(string const& _args)
 	return m_data;
 }
 
-void dev::eth::upgradeDatabase(std::string const& _basePath)
+void dev::eth::upgradeDatabase(std::string const& _basePath, h256 const& _genesisHash)
 {
 	std::string path = _basePath.empty() ? Defaults::get()->dbPath() : _basePath;
 
@@ -105,7 +105,7 @@ void dev::eth::upgradeDatabase(std::string const& _basePath)
 		{
 			auto minorProtocolVersion = (unsigned)status[1];
 			auto databaseVersion = (unsigned)status[2];
-			auto genesisHash = status.itemCount() > 3 ? (h256)status[3] : CanonBlockChain::genesis().hash();
+			auto genesisHash = status.itemCount() > 3 ? (h256)status[3] : _genesisHash;
 
 			string chainPath = path + "/" + toHex(genesisHash.ref().cropped(0, 4));
 			string extrasPath = chainPath + "/" + toString(databaseVersion);
diff --git a/libethereum/Utility.h b/libethereum/Utility.h
index 0dfe8509b..df48269ec 100644
--- a/libethereum/Utility.h
+++ b/libethereum/Utility.h
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <libdevcore/Common.h>
+#include <libdevcore/FixedHash.h>
 
 namespace dev
 {
@@ -42,7 +43,7 @@ namespace eth
  */
 bytes parseData(std::string const& _args);
 
-void upgradeDatabase(std::string const& _basePath);
+void upgradeDatabase(std::string const& _basePath, h256 const& _genesisHash);
 
 }
 }
diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp
index 7d63ed165..15d39bded 100644
--- a/libweb3jsonrpc/JsonHelper.cpp
+++ b/libweb3jsonrpc/JsonHelper.cpp
@@ -102,11 +102,9 @@ Json::Value toJson(dev::eth::BlockInfo const& _bi)
 		res["logsBloom"] = toJS(_bi.logBloom);
 		res["target"] = toJS(_bi.boundary());
 
-#if ETH_USING_ETHASH
 		// TODO: move into ProofOfWork.
-		res["nonce"] = toJS(_bi.proof.nonce);
-		res["seedHash"] = toJS(_bi.proofCache());
-#endif
+//		res["nonce"] = toJS(_bi.proof.nonce);
+//		res["seedHash"] = toJS(_bi.proofCache());
 	}
 	return res;
 }
diff --git a/libweb3jsonrpc/JsonHelper.h b/libweb3jsonrpc/JsonHelper.h
index 421d11b78..624a73e54 100644
--- a/libweb3jsonrpc/JsonHelper.h
+++ b/libweb3jsonrpc/JsonHelper.h
@@ -23,6 +23,7 @@
 
 #include <json/json.h>
 #include <libethcore/Common.h>
+#include <libethcore/BlockInfo.h>
 #include <libethereum/LogFilter.h>
 #include <libwhisper/Message.h>
 
@@ -65,6 +66,19 @@ TransactionSkeleton toTransactionSkeleton(Json::Value const& _json);
 LogFilter toLogFilter(Json::Value const& _json);
 LogFilter toLogFilter(Json::Value const& _json, Interface const& _client);	// commented to avoid warning. Uncomment once in use @ PoC-7.
 
+template <class BlockInfoSub>
+Json::Value toJson(BlockHeaderPolished<BlockInfoSub> const& _bh)
+{
+	Json::Value res;
+	if (_bh)
+	{
+		res = toJson(static_cast<BlockInfo const&>(_bh));
+		for (auto const& i: _bh.jsInfo())
+			res[i.first] = i.second;
+	}
+	return res;
+}
+
 }
 
 namespace shh
diff --git a/test/libethcore/dagger.cpp b/test/libethcore/dagger.cpp
index 1743882e5..061b5ae79 100644
--- a/test/libethcore/dagger.cpp
+++ b/test/libethcore/dagger.cpp
@@ -24,7 +24,6 @@
 #include <random>
 #include "../JsonSpiritHeaders.h"
 #include <libdevcore/CommonIO.h>
-#include <libethcore/ProofOfWork.h>
 #include <libethcore/EthashAux.h>
 #include <boost/test/unit_test.hpp>
 #include "../TestHelper.h"
@@ -74,7 +73,7 @@ BOOST_AUTO_TEST_CASE(basic_test)
 #endif
 
 		h256 result(o["result"].get_str());
-		Ethash::Result r = EthashAux::eval(header);
+		EthashProofOfWork::Result r = EthashAux::eval(header);
 		BOOST_REQUIRE_EQUAL(r.value, result);
 		BOOST_REQUIRE_EQUAL(r.mixHash, header.mixHash);
 	}
diff --git a/test/libethereum/stateOriginal.cpp b/test/libethereum/stateOriginal.cpp
index 452163061..e3f8ac29f 100644
--- a/test/libethereum/stateOriginal.cpp
+++ b/test/libethereum/stateOriginal.cpp
@@ -63,7 +63,8 @@ BOOST_AUTO_TEST_CASE(Complex)
 	CanonBlockChain bc;
 	cout << bc;
 
-	State s(stateDB, BaseState::CanonGenesis, myMiner.address());
+	State s = bc.genesisState(stateDB);
+	s.setAddress(myMiner.address());
 	cout << s;
 
 	// Sync up - this won't do much until we use the last state.