From 2513561a33286254bbff68b203ff32113d86fee4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Jul 2015 23:31:12 +0200 Subject: [PATCH] Avoid mining invalid blocks. Actually allow external mining. --- libethcore/BlockInfo.cpp | 2 +- libethcore/Ethash.cpp | 9 ++++++++- libethcore/Ethash.h | 2 ++ libethereum/Client.cpp | 1 + libethereum/State.cpp | 6 +++++- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 6252497b5..5cf909959 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -176,7 +176,7 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const } clog(BlockInfoDiagnosticsChannel) << "Expected uncle hash:" << toString(sha3(root[2].data())); if (m_sha3Uncles != sha3(root[2].data())) - BOOST_THROW_EXCEPTION(InvalidUnclesHash()); + BOOST_THROW_EXCEPTION(InvalidUnclesHash() << Hash256RequirementError(sha3(root[2].data()), m_sha3Uncles)); } void BlockInfo::populateFromParent(BlockInfo const& _parent) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 101fd1611..511146b75 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -177,15 +177,22 @@ StringHashMap Ethash::BlockHeaderRaw::jsInfo() const return { { "nonce", toJS(m_nonce) }, { "seedHash", toJS(seedHash()) }, { "mixHash", toJS(m_mixHash) } }; } - +void Ethash::manuallySetWork(SealEngineFace* _engine, BlockHeader const& _work) +{ + // set m_sealing to the current problem. + if (EthashSealEngine* e = dynamic_cast(_engine)) + e->m_sealing = _work; +} void Ethash::manuallySubmitWork(SealEngineFace* _engine, h256 const& _mixHash, Nonce _nonce) { if (EthashSealEngine* e = dynamic_cast(_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&>(e->m_farm).submitProof(EthashProofOfWork::Solution{_nonce, _mixHash}, nullptr); + } } bool Ethash::isWorking(SealEngineFace* _engine) diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 0ea80f5e1..a0904fa62 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -99,6 +99,8 @@ public: }; using BlockHeader = BlockHeaderPolished; + static void manuallySetWork(SealEngineFace* _engine, BlockHeader const& _work); + // TODO: Move elsewhere (EthashAux?) static void ensurePrecomputed(unsigned _number); }; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 7a9172a90..2322d1e46 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -924,6 +924,7 @@ std::tuple EthashClient::getEthashWork() // otherwise, set this to true so that it gets prepped next time. m_remoteWorking = true; Ethash::BlockHeader bh = Ethash::BlockHeader(m_miningInfo); + Ethash::manuallySetWork(m_sealEngine.get(), bh); return std::tuple(bh.hashWithout(), bh.seedHash(), bh.boundary()); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 3127ad1f6..b8c0ce89c 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -906,8 +906,12 @@ bool State::sealBlock(bytesConstRef _header) if (!m_committedToMine) return false; + // Check that this header is indeed for this block. + if (BlockInfo(_header, CheckNothing, h256{}, HeaderData).hashWithout() != m_currentBlock.hashWithout()) + return false; + + // Looks good! clog(StateDetail) << "Sealing block!"; - // Got it! // Compile block: RLPStream ret;