diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index bbe9d9f02..30bbe8243 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1362,11 +1362,16 @@ 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 << "
Mix hash: " << info.mixHash << "";
s << "
Nonce: " << info.nonce << "";
s << "
Hash w/o nonce: " << info.headerHash(WithoutNonce) << "";
s << "
Difficulty: " << info.difficulty << "";
if (info.number)
- s << "
Proof-of-Work: " << ProofOfWork::eval(info) << " <= " << (h256)u256((bigint(1) << 256) / info.difficulty) << "";
+ {
+ auto e = ProofOfWork::eval(info);
+ s << "
Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / info.difficulty) << " (mixhash: " << e.mixHash.abridged() << ")";
+ }
else
s << "
Proof-of-Work: Phil has nothing to prove";
s << "
Parent: " << info.parentHash << "";
@@ -1378,9 +1383,18 @@ void Main::on_blocks_currentItemChanged()
for (auto u: block[2])
{
BlockInfo uncle = BlockInfo::fromHeader(u.data());
- s << "
Hash: " << uncle.hash << "";
- s << "
Parent: " << uncle.parentHash << "";
- s << "
Number: " << uncle.number << "";
+ char const* line = "
";
+ s << line << "Hash: " << uncle.hash << "";
+ 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 << "Mix hash: " << uncle.mixHash << "";
+ s << line << "Nonce: " << uncle.nonce << "";
+ s << line << "Hash w/o nonce: " << uncle.headerHash(WithoutNonce) << "";
+ s << line << "Difficulty: " << uncle.difficulty << "";
+ auto e = ProofOfWork::eval(uncle);
+ s << line << "Proof-of-Work: " << e.value << " <= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << " (mixhash: " << e.mixHash.abridged() << ")";
}
if (info.parentHash)
s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "";
diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp
index 71cd0d110..c04f6fc29 100644
--- a/libethcore/BlockInfo.cpp
+++ b/libethcore/BlockInfo.cpp
@@ -57,7 +57,7 @@ void BlockInfo::setEmpty()
timestamp = 0;
extraData.clear();
seedHash = h256();
- mixBytes = h256();
+ mixHash = h256();
nonce = Nonce();
hash = headerHash(WithNonce);
}
@@ -82,7 +82,7 @@ void BlockInfo::streamRLP(RLPStream& _s, IncludeNonce _n) const
<< parentHash << sha3Uncles << coinbaseAddress << stateRoot << transactionsRoot << receiptsRoot << logBloom
<< difficulty << number << gasLimit << gasUsed << timestamp << extraData << seedHash;
if (_n == WithNonce)
- _s << mixBytes << nonce;
+ _s << mixHash << nonce;
}
h256 BlockInfo::headerHash(bytesConstRef _block)
@@ -111,7 +111,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
timestamp = _header[field = 11].toInt();
extraData = _header[field = 12].toBytes();
seedHash = _header[field = 13].toHash();
- mixBytes = _header[field = 14].toHash();
+ mixHash = _header[field = 14].toHash();
nonce = _header[field = 15].toHash();
}
@@ -180,7 +180,12 @@ void BlockInfo::populateFromParent(BlockInfo const& _parent)
gasLimit = calculateGasLimit(_parent);
gasUsed = 0;
difficulty = calculateDifficulty(_parent);
- seedHash = number % 30 == 0 ? sha3(_parent.seedHash.asBytes() /*+ _parent.hash.asBytes()*/) : _parent.seedHash;
+ seedHash = calculateSeedHash(_parent);
+}
+
+h256 BlockInfo::calculateSeedHash(BlockInfo const& _parent) const
+{
+ return number % 30 == 0 ? sha3(_parent.seedHash.asBytes()) : _parent.seedHash;
}
u256 BlockInfo::calculateGasLimit(BlockInfo const& _parent) const
@@ -196,7 +201,7 @@ u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const
if (!parentHash)
return c_genesisDifficulty;
else
- return max(2048, timestamp >= _parent.timestamp + (c_protocolVersion == 49 ? 5 : 8) ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
+ return max(2048, timestamp >= _parent.timestamp + 8 ? _parent.difficulty - (_parent.difficulty / 2048) : (_parent.difficulty + (_parent.difficulty / 2048)));
}
template inline N diff(N const& _a, N const& _b) { return max(_a, _b) - min(_a, _b); }
@@ -209,6 +214,9 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const
if (diff(gasLimit, _parent.gasLimit) <= _parent.gasLimit / 2048)
BOOST_THROW_EXCEPTION(InvalidGasLimit(gasLimit, calculateGasLimit(_parent), diff(gasLimit, _parent.gasLimit), _parent.gasLimit / 2048));
+ 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 fbc459b76..d2072046d 100644
--- a/libethcore/BlockInfo.h
+++ b/libethcore/BlockInfo.h
@@ -76,7 +76,7 @@ public:
u256 gasUsed;
u256 timestamp;
bytes extraData;
- h256 mixBytes;
+ h256 mixHash;
h256 seedHash;
Nonce nonce;
@@ -106,7 +106,7 @@ public:
gasUsed == _cmp.gasUsed &&
timestamp == _cmp.timestamp &&
extraData == _cmp.extraData &&
- mixBytes == _cmp.mixBytes &&
+ mixHash == _cmp.mixHash &&
seedHash == _cmp.seedHash &&
nonce == _cmp.nonce;
}
@@ -123,6 +123,7 @@ public:
u256 calculateDifficulty(BlockInfo const& _parent) const;
u256 calculateGasLimit(BlockInfo const& _parent) const;
+ h256 calculateSeedHash(BlockInfo const& _parent) const;
/// sha3 of the header only.
h256 headerHash(IncludeNonce _n) const;
@@ -133,7 +134,7 @@ 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.mixBytes << " " << _bi.seedHash << " " << _bi.nonce;
+ _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.seedHash << " " << _bi.nonce;
return _out;
}
diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h
index bc9441c6b..45667f44a 100644
--- a/libethcore/Exceptions.h
+++ b/libethcore/Exceptions.h
@@ -57,6 +57,7 @@ struct InvalidGasUsed: virtual dev::Exception {};
class InvalidTransactionsHash: virtual public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real); h256 head; h256 real; };
struct InvalidTransaction: virtual dev::Exception {};
struct InvalidDifficulty: virtual dev::Exception {};
+struct InvalidSeedHash: virtual dev::Exception {};
class InvalidGasLimit: virtual public dev::Exception { public: InvalidGasLimit(u256 _provided = 0, u256 _valid = 0, u256 _gD = 0, u256 _mD = 0): provided(_provided), valid(_valid), givenDiff(_gD), maxDiff(_mD) {} u256 provided; u256 valid; u256 givenDiff; u256 maxDiff; virtual const char* what() const noexcept; };
class InvalidMinGasPrice: virtual public dev::Exception { public: InvalidMinGasPrice(u256 _provided = 0, u256 _limit = 0): provided(_provided), limit(_limit) {} u256 provided; u256 limit; virtual const char* what() const noexcept; };
struct InvalidTransactionGasUsed: virtual dev::Exception {};
diff --git a/libethcore/ProofOfWork.cpp b/libethcore/ProofOfWork.cpp
index 04e4249b6..c879df2ce 100644
--- a/libethcore/ProofOfWork.cpp
+++ b/libethcore/ProofOfWork.cpp
@@ -118,16 +118,16 @@ Ethasher* Ethasher::s_this = nullptr;
bool Ethash::verify(BlockInfo const& _header)
{
bigint boundary = (bigint(1) << 256) / _header.difficulty;
- u256 e(eval(_header, _header.nonce));
- return e <= boundary;
+ auto e = eval(_header, _header.nonce);
+ return (u256)e.value <= boundary && e.mixHash == _header.mixHash;
}
-h256 Ethash::eval(BlockInfo const& _header, Nonce const& _nonce)
+Ethash::Result Ethash::eval(BlockInfo const& _header, Nonce const& _nonce)
{
auto p = Ethasher::params(_header);
ethash_return_value r;
ethash_compute_light(&r, Ethasher::get()->cache(_header).data(), &p, _header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_nonce);
- return h256(r.result, h256::ConstructFromPointer);
+ return Result{h256(r.result, h256::ConstructFromPointer), h256(r.mix_hash, h256::ConstructFromPointer)};
}
std::pair Ethash::mine(BlockInfo const& _header, unsigned _msTimeout, bool _continue, bool _turbo)
diff --git a/libethcore/ProofOfWork.h b/libethcore/ProofOfWork.h
index 7b9787f61..fdf51f0d4 100644
--- a/libethcore/ProofOfWork.h
+++ b/libethcore/ProofOfWork.h
@@ -55,12 +55,17 @@ public:
Nonce nonce;
h256 mixHash;
};
+ struct Result
+ {
+ h256 value;
+ h256 mixHash;
+ };
- static h256 eval(BlockInfo const& _header) { return eval(_header, _header.nonce); }
- static h256 eval(BlockInfo const& _header, Nonce const& _nonce);
+ static Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); }
+ static Result eval(BlockInfo const& _header, Nonce const& _nonce);
static bool verify(BlockInfo const& _header);
std::pair mine(BlockInfo const& _header, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
- static void assignResult(Proof const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixBytes = _r.mixHash; }
+ static void assignResult(Proof const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; }
protected:
Nonce m_last;