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;