Browse Source

Basic Proof-of-Authority sealent.

cl-refactor
Gav Wood 9 years ago
parent
commit
1bc77af041
  1. 3
      eth/main.cpp
  2. 28
      ethminer/MinerAux.h
  3. 5
      libdevcrypto/Common.cpp
  4. 3
      libdevcrypto/Common.h
  5. 4
      libethcore/Common.cpp
  6. 13
      libethcore/Common.h
  7. 26
      libethcore/Ethash.cpp
  8. 31
      libethcore/Ethash.h
  9. 11
      libethcore/EthashAux.cpp
  10. 1
      libethcore/EthashAux.h
  11. 1
      libethcore/Farm.h
  12. 11
      libethcore/Miner.h
  13. 25
      libethcore/ProofOfWork.cpp
  14. 76
      libethcore/ProofOfWork.h
  15. 4
      libethereum/BlockChain.cpp
  16. 12
      libethereum/BlockQueue.cpp
  17. 15
      libethereum/Client.cpp
  18. 2
      libethereum/Client.h
  19. 4
      libethereum/State.cpp
  20. 2
      libethereum/State.h
  21. 2
      libweb3jsonrpc/JsonHelper.cpp
  22. 10
      libweb3jsonrpc/WebThreeStubServerBase.cpp

3
eth/main.cpp

@ -1700,7 +1700,10 @@ int main(int argc, char** argv)
{
c->setGasPricer(gasPricer);
c->setForceMining(forceMining);
// TODO: expose sealant interface.
#if ETH_USING_ETHASH
c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU);
#endif
c->setAddress(beneficiary);
c->setNetworkId(networkId);
}

28
ethminer/MinerAux.h

@ -99,10 +99,16 @@ public:
Farm
};
#if ETH_USING_ETHASH
MinerCLI(OperationMode _mode = OperationMode::None): mode(_mode) {}
#else
MinerCLI(OperationMode = OperationMode::None) {}
#endif
bool interpretOption(int& i, int argc, char** argv)
{
#if ETH_USING_ETHASH
string arg = argv[i];
if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
{
@ -289,22 +295,29 @@ public:
else
return false;
return true;
#else
(void)i;
(void)argc;
(void)argv;
return false;
#endif
}
void execute()
{
#if ETH_USING_ETHASH
if (m_shouldListDevices)
{
ProofOfWork::GPUMiner::listDevices();
Ethash::GPUMiner::listDevices();
exit(0);
}
if (m_minerType == MinerType::CPU)
ProofOfWork::CPUMiner::setNumInstances(m_miningThreads);
Ethash::CPUMiner::setNumInstances(m_miningThreads);
else if (m_minerType == MinerType::GPU)
{
#if ETH_ETHASHCL || !ETH_TRUE
if (!ProofOfWork::GPUMiner::configureGPU(
if (!Ethash::GPUMiner::configureGPU(
m_localWorkSize,
m_globalWorkSizeMultiplier,
m_msPerBatch,
@ -315,7 +328,7 @@ public:
m_currentBlock
))
exit(1);
ProofOfWork::GPUMiner::setNumInstances(m_miningThreads);
Ethash::GPUMiner::setNumInstances(m_miningThreads);
#else
cerr << "Selected GPU mining without having compiled with -DETHASHCL=1" << endl;
exit(1);
@ -327,10 +340,12 @@ public:
doBenchmark(m_minerType, m_phoneHome, m_benchmarkWarmup, m_benchmarkTrial, m_benchmarkTrials);
else if (mode == OperationMode::Farm)
doFarm(m_minerType, m_farmURL, m_farmRecheckPeriod);
#endif
}
static void streamHelp(ostream& _out)
{
#if ETH_USING_ETHASH
_out
#if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl
@ -367,8 +382,12 @@ public:
<< " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(ethash_cl_miner::c_defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl
#endif
;
#else
(void)_out;
#endif
}
#if ETH_USING_ETHASH
enum class MinerType
{
CPU,
@ -576,4 +595,5 @@ private:
string m_farmURL = "http://127.0.0.1:8545";
unsigned m_farmRecheckPeriod = 500;
bool m_precompute = true;
#endif
};

5
libdevcrypto/Common.cpp

@ -63,6 +63,11 @@ bool dev::SignatureStruct::isValid() const noexcept
return true;
}
Public SignatureStruct::recover(h256 const& _hash) const
{
return dev::recover((Signature)*this, _hash);
}
Address dev::ZeroAddress = Address();
Public dev::toPublic(Secret const& _secret)

3
libdevcrypto/Common.h

@ -54,6 +54,9 @@ struct SignatureStruct
/// @returns true if r,s,v values are valid, otherwise false
bool isValid() const noexcept;
/// @returns the public part of the key that signed @a _hash to give this sig.
Public recover(h256 const& _hash) const;
h256 r;
h256 s;
byte v = 0;

4
libethcore/Common.cpp

@ -23,6 +23,10 @@
#include <random>
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Base64.h>
#include <libdevcore/Terminal.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include "Exceptions.h"
#include "ProofOfWork.h"

13
libethcore/Common.h

@ -192,11 +192,22 @@ struct TransactionSkeleton
u256 nonce = UndefinedU256;
u256 gas = UndefinedU256;
u256 gasPrice = UndefinedU256;
u256 nonce = UndefinedU256;
};
void badBlock(bytesConstRef _header, std::string const& _err);
inline void badBlock(bytes const& _header, std::string const& _err) { badBlock(&_header, _err); }
// TODO: move back into a mining subsystem and have it be accessible from Sealant only via a dynamic_cast.
/**
* @brief Describes the progress of a mining operation.
*/
struct MiningProgress
{
// MiningProgress& operator+=(MiningProgress const& _mp) { hashes += _mp.hashes; ms = std::max(ms, _mp.ms); return *this; }
uint64_t hashes = 0; ///< Total number of hashes computed.
uint64_t ms = 0; ///< Total number of milliseconds of mining thus far.
uint64_t rate() const { return ms == 0 ? 0 : hashes * 1000 / ms; }
};
}
}

26
libethcore/Ethash.cpp

@ -65,16 +65,26 @@ void Ethash::ensureHeaderCacheValid(HeaderCache& io_out, BlockInfo const& _h)
void Ethash::composeException(Exception& _ex, BlockInfo& _bi)
{
#if ETH_USING_ETHASH
_ex << errinfo_nonce(_bi.proof.nonce);
_ex << errinfo_mixHash(_bi.proof.mixHash);
_ex << errinfo_seedHash(_bi.proofCache());
Ethash::Result er = EthashAux::eval(_bi.proofCache(), _bi.headerHash(WithoutProof), _bi.proof.nonce);
_ex << errinfo_ethashResult(make_tuple(er.value, er.mixHash));
#else
(void)_ex;
(void)_bi;
#endif
}
void Ethash::composeExceptionPre(Exception& _ex, BlockInfo& _bi)
{
#if ETH_USING_ETHASH
_ex << errinfo_nonce(_bi.proof.nonce);
#else
(void)_ex;
(void)_bi;
#endif
}
std::string Ethash::name()
@ -103,7 +113,9 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi)
WorkPackage ret;
ret.boundary = _bi.boundary();
ret.headerHash = _bi.headerHash(WithoutProof);
#if ETH_USING_ETHASH
ret.seedHash = _bi.proofCache();
#endif
return ret;
}
@ -116,7 +128,12 @@ void Ethash::ensurePrecomputed(unsigned _number)
void Ethash::prep(BlockInfo const& _header, std::function<int(unsigned)> const& _f)
{
#if ETH_USING_ETHASH
EthashAux::full(_header.proofCache(), true, _f);
#else
(void)_header;
(void)_f;
#endif
}
bool Ethash::preVerify(BlockInfo const& _header)
@ -124,6 +141,7 @@ bool Ethash::preVerify(BlockInfo const& _header)
if (_header.number >= ETHASH_EPOCH_LENGTH * 2048)
return false;
#if ETH_USING_ETHASH
h256 boundary = u256((bigint(1) << 256) / _header.difficulty);
bool ret = !!ethash_quick_check_difficulty(
@ -131,8 +149,10 @@ bool Ethash::preVerify(BlockInfo const& _header)
(uint64_t)(u64)_header.proof.nonce,
(ethash_h256_t const*)_header.proof.mixHash.data(),
(ethash_h256_t const*)boundary.data());
return ret;
#else
return false;
#endif
}
bool Ethash::verify(BlockInfo const& _header)
@ -146,6 +166,7 @@ bool Ethash::verify(BlockInfo const& _header)
}
#endif
#if ETH_USING_ETHASH
auto result = EthashAux::eval(_header);
bool slow = result.value <= _header.boundary() && result.mixHash == _header.proof.mixHash;
@ -168,6 +189,9 @@ bool Ethash::verify(BlockInfo const& _header)
#endif
return slow;
#else
return false;
#endif
}
unsigned Ethash::CPUMiner::s_numInstances = 0;

31
libethcore/Ethash.h

@ -29,6 +29,7 @@
#include <libdevcore/CommonIO.h>
#include "Common.h"
#include "Miner.h"
#include "Farm.h"
class ethash_cl_miner;
@ -162,6 +163,36 @@ public:
#else
using GPUMiner = CPUMiner;
#endif
/// Default value of the local work size. Also known as workgroup size.
static const unsigned defaultLocalWorkSize;
/// Default value of the global work size as a multiplier of the local work size
static const unsigned defaultGlobalWorkSizeMultiplier;
/// Default value of the milliseconds per global work size (per batch)
static const unsigned defaultMSPerBatch;
struct Farm: public eth::GenericFarm<Ethash>
{
public:
strings sealers() const { return { "cpu", "opencl" }; }
void setSealer(std::string const& _sealer) { m_opencl = (_sealer == "opencl"); }
void sealBlock(BlockInfo const& _bi)
{
setWork(_bi);
if (m_opencl)
startGPU();
else
startCPU();
setWork(_bi);
ensurePrecomputed((unsigned)_bi.number);
}
void disable() { stop(); }
private:
bool m_opencl = false;
};
};
}

11
libethcore/EthashAux.cpp

@ -202,7 +202,12 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing
Ethash::Result EthashAux::eval(BlockInfo const& _header)
{
#if ETH_USING_ETHASH
return eval(_header, _header.proof.nonce);
#else
(void)_header;
return Ethash::Result();
#endif
}
#define DEV_IF_THROWS(X) try { X; } catch (...)
@ -257,7 +262,13 @@ Ethash::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonc
Ethash::Result EthashAux::eval(BlockInfo const& _header, Nonce const& _nonce)
{
#if ETH_USING_ETHASH
return eval(_header.proofCache(), _header.headerHash(WithoutProof), _nonce);
#else
(void)_header;
(void)_nonce;
return Ethash::Result();
#endif
}
Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce)

1
libethcore/EthashAux.h

@ -23,6 +23,7 @@
#include <condition_variable>
#include <libethash/ethash.h>
#include <libdevcore/Log.h>
#include <libdevcore/Worker.h>
#include "Ethash.h"

1
libethcore/Farm.h

@ -29,7 +29,6 @@
#include <libethcore/Common.h>
#include <libethcore/Miner.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/ProofOfWork.h>
namespace dev
{

11
libethcore/Miner.h

@ -36,17 +36,6 @@ namespace dev
namespace eth
{
/**
* @brief Describes the progress of a mining operation.
*/
struct MiningProgress
{
// MiningProgress& operator+=(MiningProgress const& _mp) { hashes += _mp.hashes; ms = std::max(ms, _mp.ms); return *this; }
uint64_t hashes = 0; ///< Total number of hashes computed.
uint64_t ms = 0; ///< Total number of milliseconds of mining thus far.
uint64_t rate() const { return ms == 0 ? 0 : hashes * 1000 / ms; }
};
struct MineInfo: public MiningProgress {};
inline std::ostream& operator<<(std::ostream& _out, MiningProgress _p)

25
libethcore/ProofOfWork.cpp

@ -20,5 +20,30 @@
*/
#include "ProofOfWork.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace eth;
const Address BasicAuthority::Authority = Address("1234567890123456789012345678901234567890");
bool BasicAuthority::verify(BlockInfo const& _header)
{
return toAddress(recover(_header.proof.sig, _header.headerHash(WithoutProof))) == Authority;
}
bool BasicAuthority::preVerify(BlockInfo const& _header)
{
return SignatureStruct(_header.proof.sig).isValid();
}
BasicAuthority::WorkPackage BasicAuthority::package(BlockInfo const& _header)
{
return WorkPackage{_header.headerHash(WithoutProof)};
}
void BasicAuthority::Farm::sealBlock(BlockInfo const& _bi)
{
m_onSolutionFound(Solution{sign(m_secret, _bi.headerHash(WithoutProof))});
}

76
libethcore/ProofOfWork.h

@ -23,13 +23,18 @@
#pragma once
#include "Ethash.h"
#include <libdevcore/RLP.h>
#include <libdevcrypto/Common.h>
#include "Common.h"
//#include "Ethash.h"
namespace dev
{
namespace eth
{
class BlockInfo;
/**
* The proof of work algorithm base type.
*
@ -40,7 +45,74 @@ namespace eth
* typename GPUMiner
* and a few others. TODO
*/
using ProofOfWork = Ethash;
class BasicAuthority
{
public:
struct HeaderCache {};
static void ensureHeaderCacheValid(HeaderCache&, BlockInfo const&) {}
static void composeException(Exception&, BlockInfo&) {}
static void composeExceptionPre(Exception&, BlockInfo&) {}
struct Solution
{
bool operator==(Solution const& _v) const { return sig == _v.sig; }
void populateFromRLP(RLP const& io_rlp, int& io_field)
{
sig = io_rlp[io_field++].toHash<dev::Signature>(RLP::VeryStrict);
}
void streamRLP(RLPStream& io_rlp) const
{
io_rlp << sig;
}
static const unsigned Fields = 1;
Signature sig;
};
struct Result
{
Signature sig;
};
struct WorkPackage
{
void reset() { headerHash = h256(); }
operator bool() const { return headerHash != h256(); }
h256 headerHash; ///< When h256() means "pause until notified a new work package is available".
};
static const WorkPackage NullWorkPackage;
static std::string name() { return "BasicAuthority"; }
static unsigned revision() { return 0; }
static void prep(BlockInfo const&, std::function<int(unsigned)> const& = std::function<int(unsigned)>()) {}
static void ensurePrecomputed(unsigned) {}
static bool verify(BlockInfo const& _header);
static bool preVerify(BlockInfo const& _header);
static WorkPackage package(BlockInfo const& _header);
static const Address Authority;
struct Farm
{
public:
strings sealers() const { return { "default" }; }
void setSealer(std::string const&) {}
void setSecret(Secret const& _s) { m_secret = _s; }
void sealBlock(BlockInfo const& _bi);
void disable() {}
void onSolutionFound(std::function<void(Solution const& s)> const& _f) { m_onSolutionFound = _f; }
bool isMining() const { return false; }
MiningProgress miningProgress() const { return MiningProgress(); }
private:
Secret m_secret;
std::function<void(Solution const& s)> m_onSolutionFound;
};
};
using ProofOfWork = BasicAuthority;
}
}

4
libethereum/BlockChain.cpp

@ -574,6 +574,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
}
#endif
#if ETH_USING_ETHASH
StructuredLogger::chainReceivedNewBlock(
_block.info.headerHash(WithoutProof).abridged(),
_block.info.proof.nonce.abridged(),
@ -581,6 +582,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
"", // TODO: remote id ??
_block.info.parentHash.abridged()
);
#endif
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
h256s route;
@ -665,12 +667,14 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
clog(BlockChainNote) << " Imported and best" << td << " (#" << _block.info.number << "). Has" << (details(_block.info.parentHash).children.size() - 1) << "siblings. Route:" << route;
#if ETH_USING_ETHASH
StructuredLogger::chainNewHead(
_block.info.headerHash(WithoutProof).abridged(),
_block.info.proof.nonce.abridged(),
currentHash().abridged(),
_block.info.parentHash.abridged()
);
#endif
}
else
{

12
libethereum/BlockQueue.cpp

@ -101,7 +101,7 @@ void BlockQueue::verifierBody()
swap(work, m_unverified.front());
m_unverified.pop_front();
BlockInfo bi;
bi.proof.mixHash = work.hash;
bi.sha3Uncles = work.hash;
bi.parentHash = work.parentHash;
m_verifying.emplace_back(move(bi));
}
@ -121,7 +121,7 @@ void BlockQueue::verifierBody()
m_readySet.erase(work.hash);
m_knownBad.insert(work.hash);
for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it)
if (it->verified.info.proof.mixHash == work.hash)
if (it->verified.info.sha3Uncles == work.hash)
{
m_verifying.erase(it);
goto OK1;
@ -136,7 +136,7 @@ void BlockQueue::verifierBody()
{
WriteGuard l2(m_lock);
unique_lock<Mutex> l(m_verification);
if (!m_verifying.empty() && m_verifying.front().verified.info.proof.mixHash == work.hash)
if (!m_verifying.empty() && m_verifying.front().verified.info.sha3Uncles == work.hash)
{
// we're next!
m_verifying.pop_front();
@ -154,7 +154,7 @@ void BlockQueue::verifierBody()
else
{
for (auto& i: m_verifying)
if (i.verified.info.proof.mixHash == work.hash)
if (i.verified.info.sha3Uncles == work.hash)
{
i = move(res);
goto OK;
@ -323,9 +323,9 @@ void BlockQueue::updateBad_WITH_LOCK(h256 const& _bad)
std::deque<VerifiedBlock> oldVerifying;
swap(m_verifying, oldVerifying);
for (auto& b: oldVerifying)
if (m_knownBad.count(b.verified.info.parentHash) || m_knownBad.count(b.verified.info.proof.mixHash))
if (m_knownBad.count(b.verified.info.parentHash) || m_knownBad.count(b.verified.info.sha3Uncles))
{
h256 const& h = b.blockData.size() != 0 ? b.verified.info.hash() : b.verified.info.proof.mixHash;
h256 const& h = b.blockData.size() != 0 ? b.verified.info.hash() : b.verified.info.sha3Uncles;
m_knownBad.insert(h);
m_readySet.erase(h);
collectUnknownBad_WITH_BOTH_LOCKS(h);

15
libethereum/Client.cpp

@ -325,7 +325,7 @@ void Client::killChain()
m_tq.clear();
m_bq.clear();
m_farm.stop();
m_farm.disable();
{
WriteGuard l(x_postMine);
@ -706,19 +706,10 @@ void Client::rejigMining()
}
if (m_wouldMine)
{
m_farm.setWork(m_miningInfo);
if (m_turboMining)
m_farm.startGPU();
else
m_farm.startCPU();
m_farm.setWork(m_miningInfo);
Ethash::ensurePrecomputed(m_bc.number());
}
m_farm.sealBlock(m_miningInfo);
}
if (!m_wouldMine)
m_farm.stop();
m_farm.disable();
}
void Client::noteChanged(h256Hash const& _filters)

2
libethereum/Client.h

@ -310,7 +310,7 @@ private:
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
GenericFarm<ProofOfWork> m_farm; ///< Our mining farm.
ProofOfWork::Farm m_farm; ///< Our mining farm.
Handler<> m_tqReady;
Handler<> m_bqReady;

4
libethereum/State.cpp

@ -976,12 +976,12 @@ void State::completeMine()
ret.swapOut(m_currentBytes);
m_currentBlock.noteDirty();
cnote << "Mined " << m_currentBlock.hash() << "(parent: " << m_currentBlock.parentHash << ")";
StructuredLogger::minedNewBlock(
/* StructuredLogger::minedNewBlock(
m_currentBlock.hash().abridged(),
m_currentBlock.proof.nonce.abridged(),
"", //TODO: chain head hash here ??
m_currentBlock.parentHash.abridged()
);
);*/
// Quickly reset the transactions.
// TODO: Leave this in a better state than this limbo, or at least record that it's in limbo.

2
libethereum/State.h

@ -173,7 +173,7 @@ public:
if (!PoW::verify(m_currentBlock))
return false;
cnote << "Completed" << m_currentBlock.headerHash(WithoutProof) << m_currentBlock.proof.nonce << m_currentBlock.difficulty << PoW::verify(m_currentBlock);
// cnote << "Completed" << m_currentBlock.headerHash(WithoutProof) << m_currentBlock.proof.nonce << m_currentBlock.difficulty << PoW::verify(m_currentBlock);
completeMine();

2
libweb3jsonrpc/JsonHelper.cpp

@ -102,9 +102,11 @@ Json::Value toJson(dev::eth::BlockInfo const& _bi)
res["logsBloom"] = toJS(_bi.logBloom);
res["target"] = toJS(_bi.boundary());
#if ETH_USING_ETHASH
// TODO: move into ProofOfWork.
res["nonce"] = toJS(_bi.proof.nonce);
res["seedHash"] = toJS(_bi.proofCache());
#endif
}
return res;
}

10
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -733,10 +733,12 @@ Json::Value WebThreeStubServerBase::eth_getLogs(Json::Value const& _json)
Json::Value WebThreeStubServerBase::eth_getWork()
{
Json::Value ret(Json::arrayValue);
#if ETH_USING_ETHASH
auto r = client()->getWork();
ret.append(toJS(r.headerHash));
ret.append(toJS(r.seedHash));
ret.append(toJS(r.boundary));
#endif
return ret;
}
@ -744,7 +746,13 @@ bool WebThreeStubServerBase::eth_submitWork(string const& _nonce, string const&,
{
try
{
return client()->submitWork(ProofOfWork::Solution{jsToFixed<Nonce::size>(_nonce), jsToFixed<32>(_mixHash)});
#if ETH_USING_ETHASH
return client()->submitWork(Ethash::Solution{jsToFixed<Nonce::size>(_nonce), jsToFixed<32>(_mixHash)});
#else
(void)_nonce;
(void)_mixHash;
return false;
#endif
}
catch (...)
{

Loading…
Cancel
Save