diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index c936b1f1b..8a15cd80f 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -25,7 +25,7 @@ class InvalidBlockHeaderFormat: public dev::Exception { public: InvalidBlockHead class InvalidUnclesHash: public dev::Exception {}; class InvalidUncle: public dev::Exception {}; class UncleTooOld: public dev::Exception {}; -class UncleInChain: public dev::Exception {}; +class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual std::string description() const { return "Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")"; } }; class DuplicateUncleNonce: public dev::Exception {}; class InvalidStateRoot: public dev::Exception {}; class InvalidTransactionsHash: public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual std::string description() const { return "Invalid transactions hash: header says: " + toHex(m_head.ref()) + " block is:" + toHex(m_real.ref()); } }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a74b6ba18..8fa6141a5 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -577,6 +577,9 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) set knownUncles = _bc ? _bc->allUnclesFrom(m_currentBlock.parentHash) : set(); for (auto const& i: RLP(_block)[2]) { + if (knownUncles.count(sha3(i.data()))) + throw UncleInChain(knownUncles, sha3(i.data())); + BlockInfo uncle = BlockInfo::fromHeader(i.data()); if (nonces.count(uncle.nonce)) throw DuplicateUncleNonce(); @@ -585,8 +588,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) BlockInfo uncleParent(_bc->block(uncle.parentHash)); if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 6) throw UncleTooOld(); - if (knownUncles.count(sha3(i.data()))) - throw UncleInChain(); uncle.verifyParent(uncleParent); } @@ -725,7 +726,7 @@ void State::commitToMine(BlockChain const& _bc) auto us = _bc.details(p).children; assert(us.size() >= 1); // must be at least 1 child of our grandparent - it's our own parent! for (auto const& u: us) - if (!knownUncles.count(BlockInfo::headerHash(_bc.block(u)))) // ignore any uncles/mainline blocks that we know about. We use header-hash for this. + if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about. { BlockInfo ubi(_bc.block(u)); ubi.fillStream(unclesData, true);