Browse Source

Flatten SealEngine

cl-refactor
Paweł Bylica 8 years ago
parent
commit
cdc8a2ca10
No known key found for this signature in database GPG Key ID: 7A0C037434FE77EF
  1. 4
      ethminer/main.cpp
  2. 1
      libdevcore/CommonData.cpp
  3. 3
      libethcore/CMakeLists.txt
  4. 189
      libethcore/Ethash.cpp
  5. 29
      libethcore/Ethash.h
  6. 27
      libethcore/EthashSealEngine.cpp
  7. 12
      libethcore/EthashSealEngine.h
  8. 26
      libethcore/Sealer.cpp
  9. 77
      libethcore/Sealer.h

4
ethminer/main.cpp

@ -29,12 +29,8 @@
#endif
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#include "MinerAux.h"
using namespace std;
using namespace dev;

1
libdevcore/CommonData.cpp

@ -21,7 +21,6 @@
#include "CommonData.h"
#include <random>
#include <boost/random/uniform_int_distribution.hpp>
#include "Exceptions.h"
#include "Log.h"

3
libethcore/CMakeLists.txt

@ -1,7 +1,6 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
file(GLOB SRC_LIST "*.cpp")
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})

189
libethcore/Ethash.cpp

@ -20,31 +20,7 @@
*/
#include "Ethash.h"
#include <boost/detail/endian.hpp>
#include <boost/filesystem.hpp>
#include <chrono>
#include <array>
#include <thread>
#include <thread>
#include <libdevcore/Guards.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libethash/ethash.h>
#include <libethash/internal.h>
#include "BlockInfo.h"
#include "EthashAux.h"
#include "Exceptions.h"
#include "Farm.h"
#include "Miner.h"
#include "Params.h"
#include "EthashSealEngine.h"
#include "EthashCPUMiner.h"
#include "EthashGPUMiner.h"
#include "EthashCUDAMiner.h"
using namespace std;
using namespace std::chrono;
namespace dev
{
@ -58,170 +34,5 @@ h256 const& Ethash::BlockHeaderRaw::seedHash() const
return m_seedHash;
}
void Ethash::BlockHeaderRaw::populateFromHeader(RLP const& _header, Strictness _s)
{
m_mixHash = _header[BlockInfo::BasicFields].toHash<h256>();
m_nonce = _header[BlockInfo::BasicFields + 1].toHash<h64>();
// check it hashes according to proof of work or that it's the genesis block.
if (_s == CheckEverything && m_parentHash && !verify())
{
InvalidBlockNonce ex;
ex << errinfo_nonce(m_nonce);
ex << errinfo_mixHash(m_mixHash);
ex << errinfo_seedHash(seedHash());
EthashProofOfWork::Result er = EthashAux::eval(seedHash(), hashWithout(), m_nonce);
ex << errinfo_ethashResult(make_tuple(er.value, er.mixHash));
ex << errinfo_hash256(hashWithout());
ex << errinfo_difficulty(m_difficulty);
ex << errinfo_target(boundary());
BOOST_THROW_EXCEPTION(ex);
}
else if (_s == QuickNonce && m_parentHash && !preVerify())
{
InvalidBlockNonce ex;
ex << errinfo_hash256(hashWithout());
ex << errinfo_difficulty(m_difficulty);
ex << errinfo_nonce(m_nonce);
BOOST_THROW_EXCEPTION(ex);
}
if (_s != CheckNothing)
{
if (m_difficulty < c_minimumDifficulty)
BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError(bigint(c_minimumDifficulty), bigint(m_difficulty)) );
if (m_gasLimit < c_minGasLimit)
BOOST_THROW_EXCEPTION(InvalidGasLimit() << RequirementError(bigint(c_minGasLimit), bigint(m_gasLimit)) );
if (m_number && m_extraData.size() > c_maximumExtraDataSize)
BOOST_THROW_EXCEPTION(ExtraDataTooBig() << RequirementError(bigint(c_maximumExtraDataSize), bigint(m_extraData.size())) << errinfo_extraData(m_extraData));
}
}
void Ethash::BlockHeaderRaw::verifyParent(BlockHeaderRaw const& _parent)
{
// Check difficulty is correct given the two timestamps.
if (m_difficulty != calculateDifficulty(_parent))
BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError((bigint)calculateDifficulty(_parent), (bigint)m_difficulty));
if (m_gasLimit < c_minGasLimit ||
m_gasLimit <= _parent.m_gasLimit - _parent.m_gasLimit / c_gasLimitBoundDivisor ||
m_gasLimit >= _parent.m_gasLimit + _parent.m_gasLimit / c_gasLimitBoundDivisor)
BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)(_parent.m_gasLimit - _parent.m_gasLimit / c_gasLimitBoundDivisor)) << errinfo_got((bigint)m_gasLimit) << errinfo_max((bigint)(_parent.m_gasLimit + _parent.m_gasLimit / c_gasLimitBoundDivisor)));
}
void Ethash::BlockHeaderRaw::populateFromParent(BlockHeaderRaw const& _parent)
{
(void)_parent;
}
bool Ethash::BlockHeaderRaw::preVerify() const
{
if (m_number >= ETHASH_EPOCH_LENGTH * 2048)
return false;
bool ret = !!ethash_quick_check_difficulty(
(ethash_h256_t const*)hashWithout().data(),
(uint64_t)(u64)m_nonce,
(ethash_h256_t const*)m_mixHash.data(),
(ethash_h256_t const*)boundary().data());
return ret;
}
bool Ethash::BlockHeaderRaw::verify() const
{
bool pre = preVerify();
#if !ETH_DEBUG
if (!pre)
{
cwarn << "Fail on preVerify";
return false;
}
#endif
auto result = EthashAux::eval(seedHash(), hashWithout(), m_nonce);
bool slow = result.value <= boundary() && result.mixHash == m_mixHash;
// cdebug << (slow ? "VERIFY" : "VERYBAD");
// cdebug << result.value.hex() << _header.boundary().hex();
// cdebug << result.mixHash.hex() << _header.mixHash.hex();
#if ETH_DEBUG || !ETH_TRUE
if (!pre && slow)
{
cwarn << "WARNING: evaluated result gives true whereas ethash_quick_check_difficulty gives false.";
cwarn << "headerHash:" << hashWithout();
cwarn << "nonce:" << m_nonce;
cwarn << "mixHash:" << m_mixHash;
cwarn << "difficulty:" << m_difficulty;
cwarn << "boundary:" << boundary();
cwarn << "result.value:" << result.value;
cwarn << "result.mixHash:" << result.mixHash;
}
#endif
return slow;
}
void Ethash::BlockHeaderRaw::prep(std::function<int(unsigned)> const& _f) const
{
EthashAux::full(seedHash(), true, _f);
}
void Ethash::manuallySetWork(SealEngineFace* _engine, BlockHeader const& _work)
{
// set m_sealing to the current problem.
if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
e->m_sealing = _work;
}
void Ethash::manuallySubmitWork(SealEngineFace* _engine, h256 const& _mixHash, Nonce _nonce)
{
if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_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<GenericFarmFace<EthashProofOfWork>&>(e->m_farm).submitProof(EthashProofOfWork::Solution{_nonce, _mixHash}, nullptr);
}
}
bool Ethash::isWorking(SealEngineFace* _engine)
{
if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
return e->m_farm.isMining();
return false;
}
WorkingProgress Ethash::workingProgress(SealEngineFace* _engine)
{
if (EthashSealEngine* e = dynamic_cast<EthashSealEngine*>(_engine))
return e->m_farm.miningProgress();
return WorkingProgress();
}
SealEngineFace* Ethash::createSealEngine()
{
return new EthashSealEngine;
}
std::string Ethash::name()
{
return "Ethash";
}
unsigned Ethash::revision()
{
return ETHASH_REVISION;
}
void Ethash::ensurePrecomputed(unsigned _number)
{
if (_number % ETHASH_EPOCH_LENGTH > ETHASH_EPOCH_LENGTH * 9 / 10)
// 90% of the way to the new epoch
EthashAux::computeFull(EthashAux::seedHash(_number + ETHASH_EPOCH_LENGTH), true);
}
}
}

29
libethcore/Ethash.h

@ -30,7 +30,6 @@
#include "Common.h"
#include "Miner.h"
#include "Farm.h"
#include "Sealer.h"
class ethash_cl_miner;
class ethash_cuda_miner;
@ -51,58 +50,30 @@ class EthashCUDAHook;
class Ethash
{
public:
static std::string name();
static unsigned revision();
static SealEngineFace* createSealEngine();
using Nonce = h64;
static void manuallySubmitWork(SealEngineFace* _engine, h256 const& _mixHash, Nonce _nonce);
static bool isWorking(SealEngineFace* _engine);
static WorkingProgress workingProgress(SealEngineFace* _engine);
class BlockHeaderRaw: public BlockInfo
{
friend class EthashSealEngine;
public:
static const unsigned SealFields = 2;
bool verify() const;
bool preVerify() const;
void prep(std::function<int(unsigned)> const& _f = std::function<int(unsigned)>()) const;
h256 const& seedHash() const;
Nonce const& nonce() const { return m_nonce; }
h256 const& mixHash() const { return m_mixHash; }
void setNonce(Nonce const& _n) { m_nonce = _n; noteDirty(); }
void setMixHash(h256 const& _n) { m_mixHash = _n; noteDirty(); }
protected:
BlockHeaderRaw() = default;
BlockHeaderRaw(BlockInfo const& _bi): BlockInfo(_bi) {}
void populateFromHeader(RLP const& _header, Strictness _s);
void populateFromParent(BlockHeaderRaw const& _parent);
void verifyParent(BlockHeaderRaw const& _parent);
void clear() { m_mixHash = h256(); m_nonce = Nonce(); }
void noteDirty() const { m_seedHash = h256(); }
void streamRLPFields(RLPStream& _s) const { _s << m_mixHash << m_nonce; }
private:
Nonce m_nonce;
h256 m_mixHash;
mutable h256 m_seedHash;
mutable h256 m_hash; ///< SHA3 hash of the block header! Not serialised.
};
using BlockHeader = BlockHeaderPolished<BlockHeaderRaw>;
static void manuallySetWork(SealEngineFace* _engine, BlockHeader const& _work);
// TODO: Move elsewhere (EthashAux?)
static void ensurePrecomputed(unsigned _number);
};
}

27
libethcore/EthashSealEngine.cpp

@ -54,30 +54,3 @@ strings EthashSealEngine::sealers() const
#endif
};
}
void EthashSealEngine::generateSeal(BlockInfo const& _bi)
{
m_sealing = Ethash::BlockHeader(_bi);
m_farm.setWork(m_sealing);
m_farm.start(m_sealer, false);
m_farm.setWork(m_sealing); // TODO: take out one before or one after...
bytes shouldPrecompute = option("precomputeDAG");
if (!shouldPrecompute.empty() && shouldPrecompute[0] == 1)
Ethash::ensurePrecomputed((unsigned)_bi.number());
}
void EthashSealEngine::onSealGenerated(std::function<void(bytes const&)> const& _f)
{
m_farm.onSolutionFound([=](EthashProofOfWork::Solution const& sol)
{
// cdebug << m_farm.work().seedHash << m_farm.work().headerHash << sol.nonce << EthashAux::eval(m_farm.work().seedHash, m_farm.work().headerHash, sol.nonce).value;
m_sealing.m_mixHash = sol.mixHash;
m_sealing.m_nonce = sol.nonce;
if (!m_sealing.preVerify())
return false;
RLPStream ret;
m_sealing.streamRLP(ret);
_f(ret.out());
return true;
});
}

12
libethcore/EthashSealEngine.h

@ -23,7 +23,6 @@
#pragma once
#include "Sealer.h"
#include "Ethash.h"
#include "EthashAux.h"
@ -32,24 +31,17 @@ namespace dev
namespace eth
{
class EthashSealEngine: public SealEngineBase<Ethash>
class EthashSealEngine
{
friend class Ethash;
public:
EthashSealEngine();
strings sealers() const override;
void setSealer(std::string const& _sealer) override { m_sealer = _sealer; }
void cancelGeneration() override { m_farm.stop(); }
void generateSeal(BlockInfo const& _bi) override;
void onSealGenerated(std::function<void(bytes const&)> const& _f) override;
strings sealers() const;
private:
bool m_opencl = false;
eth::GenericFarm<EthashProofOfWork> m_farm;
std::string m_sealer = "cpu";
Ethash::BlockHeader m_sealing;
};
}

26
libethcore/Sealer.cpp

@ -1,26 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Sealer.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "Sealer.h"
using namespace std;
using namespace dev;
using namespace eth;

77
libethcore/Sealer.h

@ -1,77 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Sealer.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* Determines the PoW algorithm.
*/
#pragma once
#include <functional>
#include <libdevcore/Guards.h>
#include <libdevcore/RLP.h>
#include "Common.h"
namespace dev
{
namespace eth
{
class BlockInfo;
class SealEngineFace
{
public:
virtual ~SealEngineFace() {}
virtual std::string name() const = 0;
virtual unsigned revision() const = 0;
virtual unsigned sealFields() const = 0;
virtual bytes sealRLP() const = 0;
bytes option(std::string const& _name) const { Guard l(x_options); return m_options.count(_name) ? m_options.at(_name) : bytes(); }
bool setOption(std::string const& _name, bytes const& _value) { Guard l(x_options); try { if (onOptionChanging(_name, _value)) { m_options[_name] = _value; return true; } } catch (...) {} return false; }
virtual strings sealers() const { return { "default" }; }
virtual void setSealer(std::string const&) {}
virtual void generateSeal(BlockInfo const& _bi) = 0;
virtual void onSealGenerated(std::function<void(bytes const& s)> const& _f) = 0;
virtual void cancelGeneration() {}
protected:
virtual bool onOptionChanging(std::string const&, bytes const&) { return true; }
void injectOption(std::string const& _name, bytes const& _value) { Guard l(x_options); m_options[_name] = _value; }
private:
mutable Mutex x_options;
std::unordered_map<std::string, bytes> m_options;
};
template <class Sealer>
class SealEngineBase: public SealEngineFace
{
public:
std::string name() const override { return Sealer::name(); }
unsigned revision() const override { return Sealer::revision(); }
unsigned sealFields() const override { return Sealer::BlockHeader::SealFields; }
bytes sealRLP() const override { RLPStream s(sealFields()); s.appendRaw(typename Sealer::BlockHeader().sealFieldsRLP(), sealFields()); return s.out(); }
};
}
}
Loading…
Cancel
Save