diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 5a47d991a..c85685d92 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1355,7 +1355,7 @@ void Main::on_blocks_currentItemChanged()
s << " Children: " << details.children.size() << "";
s << "
Gas used/limit: " << info.gasUsed << "/" << info.gasLimit << "";
s << "
Coinbase: " << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress;
- s << "
Seed hash: " << info.seedHash << "";
+ s << "
Seed hash: " << info.seedHash() << "";
s << "
Mix hash: " << info.mixHash << "";
s << "
Nonce: " << info.nonce << "";
s << "
Hash w/o nonce: " << info.headerHash(WithoutNonce) << "";
@@ -1381,7 +1381,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Parent: " << uncle.parentHash << "";
s << line << "Number: " << uncle.number << "";
s << line << "Coinbase: " << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress;
- s << line << "Seed hash: " << uncle.seedHash << "";
+ s << line << "Seed hash: " << uncle.seedHash() << "";
s << line << "Mix hash: " << uncle.mixHash << "";
s << line << "Nonce: " << uncle.nonce << "";
s << line << "Hash w/o nonce: " << uncle.headerHash(WithoutNonce) << "";
diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp
index 0f37294c2..654dd9e1a 100644
--- a/libethcore/BlockInfo.cpp
+++ b/libethcore/BlockInfo.cpp
@@ -55,12 +55,20 @@ void BlockInfo::setEmpty()
gasUsed = 0;
timestamp = 0;
extraData.clear();
- seedHash = h256();
mixHash = h256();
nonce = Nonce();
+ m_seedHash = h256();
hash = headerHash(WithNonce);
}
+h256 BlockInfo::seedHash() const
+{
+ if (!m_seedHash)
+ for (u256 n = number; n >= c_epochDuration; n -= c_epochDuration)
+ m_seedHash = sha3(m_seedHash);
+ return m_seedHash;
+}
+
BlockInfo BlockInfo::fromHeader(bytesConstRef _block, Strictness _s)
{
BlockInfo ret;
@@ -77,9 +85,9 @@ h256 BlockInfo::headerHash(IncludeNonce _n) const
void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
{
- _s.appendList(_n == WithNonce ? 16 : 14)
+ _s.appendList(_n == WithNonce ? 15 : 13)
<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
- << difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
+ << difficulty << number << gasLimit << gasUsed << timestamp << extraData;
if (_n == WithNonce)
_s << mixHash << nonce;
}
@@ -109,9 +117,8 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
gasUsed = _header[field = 10].toInt();
timestamp = _header[field = 11].toInt();
extraData = _header[field = 12].toBytes();
- seedHash = _header[field = 13].toHash(RLP::VeryStrict);
- mixHash = _header[field = 14].toHash(RLP::VeryStrict);
- nonce = _header[field = 15].toHash(RLP::VeryStrict);
+ mixHash = _header[field = 13].toHash(RLP::VeryStrict);
+ nonce = _header[field = 14].toHash(RLP::VeryStrict);
}
catch (Exception const& _e)
@@ -188,12 +195,6 @@ void BlockInfo::populateFromParent(BlockInfo const& _parent)
gasLimit = calculateGasLimit(_parent);
gasUsed = 0;
difficulty = calculateDifficulty(_parent);
- seedHash = calculateSeedHash(_parent);
-}
-
-h256 BlockInfo::calculateSeedHash(BlockInfo const& _parent) const
-{
- return number % c_epochDuration == 0 ? sha3(_parent.seedHash.asBytes()) : _parent.seedHash;
}
u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
@@ -222,9 +223,6 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const
gasLimit > _parent.gasLimit * (c_gasLimitBoundDivisor + 1) / c_gasLimitBoundDivisor)
BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)_parent.gasLimit * (c_gasLimitBoundDivisor - 1) / c_gasLimitBoundDivisor) << errinfo_got((bigint)gasLimit) << errinfo_max((bigint)_parent.gasLimit * (c_gasLimitBoundDivisor + 1) / c_gasLimitBoundDivisor));
- if (seedHash != calculateSeedHash(_parent))
- BOOST_THROW_EXCEPTION(InvalidSeedHash());
-
// Check timestamp is after previous timestamp.
if (parentHash)
{
diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h
index 20134f059..714adb375 100644
--- a/libethcore/BlockInfo.h
+++ b/libethcore/BlockInfo.h
@@ -67,6 +67,7 @@ enum Strictness
struct BlockInfo
{
public:
+ // TODO: make them all private!
h256 hash; ///< SHA3 hash of the block header! Not serialised (the only member not contained in a block header).
h256 parentHash;
h256 sha3Uncles;
@@ -82,7 +83,6 @@ public:
u256 timestamp;
bytes extraData;
h256 mixHash;
- h256 seedHash;
Nonce nonce;
BlockInfo();
@@ -113,7 +113,6 @@ public:
timestamp == _cmp.timestamp &&
extraData == _cmp.extraData &&
mixHash == _cmp.mixHash &&
- seedHash == _cmp.seedHash &&
nonce == _cmp.nonce;
}
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
@@ -129,18 +128,21 @@ public:
u256 calculateDifficulty(BlockInfo const& _parent) const;
u256 calculateGasLimit(BlockInfo const& _parent) const;
- h256 calculateSeedHash(BlockInfo const& _parent) const;
+ h256 seedHash() const;
/// sha3 of the header only.
h256 headerHash(IncludeNonce _n) const;
void streamRLP(RLPStream& _s, IncludeNonce _n) const;
+
+private:
+ mutable h256 m_seedHash;
};
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " <<
_bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " <<
- _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.seedHash << " " << _bi.nonce;
+ _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")";
return _out;
}
diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp
index 8bd4ef143..c821bf057 100644
--- a/libethcore/Common.cpp
+++ b/libethcore/Common.cpp
@@ -32,7 +32,7 @@ namespace dev
namespace eth
{
-const unsigned c_protocolVersion = 56;
+const unsigned c_protocolVersion = 57;
const unsigned c_databaseBaseVersion = 8;
#if ETH_FATDB
const unsigned c_databaseVersionModifier = 1000;
diff --git a/libethcore/Ethasher.cpp b/libethcore/Ethasher.cpp
index 52a1d17d7..f80277cb2 100644
--- a/libethcore/Ethasher.cpp
+++ b/libethcore/Ethasher.cpp
@@ -25,11 +25,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
+#include
#include
#include "BlockInfo.h"
#include "Ethasher.h"
@@ -49,19 +50,19 @@ bytes const& Ethasher::cache(BlockInfo const& _header)
throw std::invalid_argument( error.str() );
}
- if (!m_caches.count(_header.seedHash))
+ if (!m_caches.count(_header.seedHash()))
{
ethash_params p = params((unsigned)_header.number);
- m_caches[_header.seedHash].resize(p.cache_size);
- ethash_prep_light(m_caches[_header.seedHash].data(), &p, _header.seedHash.data());
+ m_caches[_header.seedHash()].resize(p.cache_size);
+ ethash_prep_light(m_caches[_header.seedHash()].data(), &p, _header.seedHash().data());
}
- return m_caches[_header.seedHash];
+ return m_caches[_header.seedHash()];
}
bytesConstRef Ethasher::full(BlockInfo const& _header)
{
RecursiveGuard l(x_this);
- if (!m_fulls.count(_header.seedHash))
+ if (!m_fulls.count(_header.seedHash()))
{
if (!m_fulls.empty())
{
@@ -71,18 +72,18 @@ bytesConstRef Ethasher::full(BlockInfo const& _header)
try {
boost::filesystem::create_directories(getDataDir() + "/ethashcache");
} catch (...) {}
- std::string memoFile = getDataDir() + "/ethashcache/" + toHex(_header.seedHash.ref().cropped(0, 4)) + ".full";
- m_fulls[_header.seedHash] = contentsNew(memoFile);
- if (!m_fulls[_header.seedHash])
+ std::string memoFile = getDataDir() + "/ethashcache/" + toHex(_header.seedHash().ref().cropped(0, 4)) + ".full";
+ m_fulls[_header.seedHash()] = contentsNew(memoFile);
+ if (!m_fulls[_header.seedHash()])
{
ethash_params p = params((unsigned)_header.number);
- m_fulls[_header.seedHash] = bytesRef(new byte[p.full_size], p.full_size);
+ m_fulls[_header.seedHash()] = bytesRef(new byte[p.full_size], p.full_size);
auto c = cache(_header);
- ethash_prep_full(m_fulls[_header.seedHash].data(), &p, c.data());
- writeFile(memoFile, m_fulls[_header.seedHash]);
+ ethash_prep_full(m_fulls[_header.seedHash()].data(), &p, c.data());
+ writeFile(memoFile, m_fulls[_header.seedHash()]);
}
}
- return m_fulls[_header.seedHash];
+ return m_fulls[_header.seedHash()];
}
ethash_params Ethasher::params(BlockInfo const& _header)
diff --git a/test/blockchain.cpp b/test/blockchain.cpp
index eca08d09e..045f2de5b 100644
--- a/test/blockchain.cpp
+++ b/test/blockchain.cpp
@@ -313,7 +313,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!");
BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!");
BOOST_CHECK_MESSAGE(blockHeaderFromFields.mixHash == blockFromRlp.mixHash, "mixHash in given RLP not matching the block mixHash!");
- BOOST_CHECK_MESSAGE(blockHeaderFromFields.seedHash == blockFromRlp.seedHash, "transactionsRoot in given RLP not matching the block transactionsRoot!");
BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!");
BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!");
@@ -466,9 +465,6 @@ bytes createBlockRLPFromFields(mObject& _tObj)
if (_tObj.count("extraData"))
rlpStream << fromHex(_tObj["extraData"].get_str());
- if (_tObj.count("seedHash"))
- rlpStream << importByteArray(_tObj["seedHash"].get_str());
-
if (_tObj.count("mixHash"))
rlpStream << importByteArray(_tObj["mixHash"].get_str());
@@ -527,9 +523,6 @@ void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj)
if (_blObj["blockHeader"].get_obj().count("mixHash"))
tmp.mixHash = h256(_blObj["blockHeader"].get_obj()["mixHash"].get_str());
- if (_blObj["blockHeader"].get_obj().count("seedHash"))
- tmp.seedHash = h256(_blObj["blockHeader"].get_obj()["seedHash"].get_str());
-
// find new valid nonce
if (tmp != _current_BlockHeader)
@@ -609,7 +602,6 @@ void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi)
_o["timestamp"] = toString(_bi.timestamp);
_o["extraData"] ="0x" + toHex(_bi.extraData);
_o["mixHash"] = toString(_bi.mixHash);
- _o["seedHash"] = toString(_bi.seedHash);
_o["nonce"] = toString(_bi.nonce);
_o["hash"] = toString(_bi.hash);
}