Browse Source

Various fixes for mining.

cl-refactor
Gav Wood 10 years ago
parent
commit
2693659e56
  1. 1
      alethzero/DownloadView.h
  2. 10
      alethzero/MainWin.cpp
  3. 11
      alethzero/MiningView.cpp
  4. 4
      alethzero/MiningView.h
  5. 17
      eth/main.cpp
  6. 54
      exp/main.cpp
  7. 3
      libdevcore/Worker.h
  8. 52
      libethcore/Ethash.cpp
  9. 22
      libethcore/Ethash.h
  10. 35
      libethcore/Miner.h
  11. 45
      libethereum/Farm.h
  12. 23
      mix/MixClient.cpp
  13. 4
      mix/MixClient.h
  14. 10
      neth/main.cpp
  15. 31
      test/TestHelper.cpp
  16. 5
      test/TestHelper.h
  17. 111
      test/blockchain.cpp
  18. 12
      test/dagger.cpp
  19. 11
      test/stateOriginal.cpp
  20. 2
      third/MainWin.cpp

1
alethzero/DownloadView.h

@ -32,7 +32,6 @@
#endif #endif
namespace dev { namespace eth { namespace dev { namespace eth {
struct MineInfo;
class DownloadMan; class DownloadMan;
}} }}

10
alethzero/MainWin.cpp

@ -45,7 +45,7 @@
#endif #endif
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libethcore/Ethasher.h> #include <libethcore/EthashAux.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <liblll/CodeFragment.h> #include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
@ -164,7 +164,7 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->chainStatus); statusBar()->addPermanentWidget(ui->chainStatus);
statusBar()->addPermanentWidget(ui->blockCount); statusBar()->addPermanentWidget(ui->blockCount);
ui->blockCount->setText(QString("PV%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(ProofOfWork::name()).arg(ProofOfWork::revision()).arg(dev::Version)); ui->blockCount->setText(QString("PV%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
@ -952,7 +952,7 @@ void Main::on_preview_triggered()
void Main::refreshMining() void Main::refreshMining()
{ {
MineProgress p = ethereum()->miningProgress(); MiningProgress p = ethereum()->miningProgress();
ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining");
if (!ui->miningView->isVisible()) if (!ui->miningView->isVisible())
return; return;
@ -1481,7 +1481,7 @@ void Main::on_blocks_currentItemChanged()
s << "<div>Difficulty: <b>" << info.difficulty << "</b>" << "</div>"; s << "<div>Difficulty: <b>" << info.difficulty << "</b>" << "</div>";
if (info.number) if (info.number)
{ {
auto e = Ethasher::eval(info); auto e = EthashAux::eval(info);
s << "<div>Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / info.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>"; s << "<div>Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / info.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>";
s << "<div>Parent: <b>" << info.parentHash << "</b>" << "</div>"; s << "<div>Parent: <b>" << info.parentHash << "</b>" << "</div>";
} }
@ -1510,7 +1510,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>"; s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>";
s << line << "Hash w/o nonce: <b>" << uncle.headerHash(WithoutNonce) << "</b>" << "</div>"; s << line << "Hash w/o nonce: <b>" << uncle.headerHash(WithoutNonce) << "</b>" << "</div>";
s << line << "Difficulty: <b>" << uncle.difficulty << "</b>" << "</div>"; s << line << "Difficulty: <b>" << uncle.difficulty << "</b>" << "</div>";
auto e = Ethasher::eval(uncle); auto e = EthashAux::eval(uncle);
s << line << "Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>"; s << line << "Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>";
} }
if (info.parentHash) if (info.parentHash)

11
alethzero/MiningView.cpp

@ -36,7 +36,7 @@ using namespace dev::eth;
// types // types
using dev::eth::MineInfo; using dev::eth::MineInfo;
using dev::eth::MineProgress; using dev::eth::MiningProgress;
// functions // functions
using dev::toString; using dev::toString;
@ -50,12 +50,13 @@ MiningView::MiningView(QWidget* _p): QWidget(_p)
{ {
} }
void MiningView::appendStats(list<MineInfo> const& _i, MineProgress const& _p) void MiningView::appendStats(list<MineInfo> const& _i, MiningProgress const& _p)
{ {
(void)_p;
if (_i.empty()) if (_i.empty())
return; return;
unsigned o = m_values.size(); /* unsigned o = m_values.size();
for (MineInfo const& i: _i) for (MineInfo const& i: _i)
{ {
m_values.push_back(i.best); m_values.push_back(i.best);
@ -91,7 +92,7 @@ void MiningView::appendStats(list<MineInfo> const& _i, MineProgress const& _p)
m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end()); m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end());
m_progress = _p; m_progress = _p;
update(); update();*/
} }
void MiningView::resetStats() void MiningView::resetStats()
@ -101,6 +102,7 @@ void MiningView::resetStats()
void MiningView::paintEvent(QPaintEvent*) void MiningView::paintEvent(QPaintEvent*)
{ {
/*
Grapher g; Grapher g;
QPainter p(this); QPainter p(this);
@ -115,4 +117,5 @@ void MiningView::paintEvent(QPaintEvent*)
g.ruleY(r - 1, QColor(128, 128, 128)); g.ruleY(r - 1, QColor(128, 128, 128));
for (auto r: m_completes) for (auto r: m_completes)
g.ruleY(r, QColor(192, 64, 64)); g.ruleY(r, QColor(192, 64, 64));
*/
} }

4
alethzero/MiningView.h

@ -42,14 +42,14 @@ class MiningView: public QWidget
public: public:
MiningView(QWidget* _p = nullptr); MiningView(QWidget* _p = nullptr);
void appendStats(std::list<dev::eth::MineInfo> const& _l, dev::eth::MineProgress const& _p); void appendStats(std::list<dev::eth::MineInfo> const& _l, dev::eth::MiningProgress const& _p);
void resetStats(); void resetStats();
protected: protected:
virtual void paintEvent(QPaintEvent*); virtual void paintEvent(QPaintEvent*);
private: private:
dev::eth::MineProgress m_progress; dev::eth::MiningProgress m_progress;
unsigned m_duration = 300; unsigned m_duration = 300;
std::vector<float> m_values; std::vector<float> m_values;
std::vector<float> m_bests; std::vector<float> m_bests;

17
eth/main.cpp

@ -126,20 +126,22 @@ void help()
#if ETH_JSONRPC #if ETH_JSONRPC
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
#endif
#if ETH_EVMJIT
<< " -J,--jit Enable EVM JIT (default: off)." << endl
#endif #endif
<< " -K,--kill First kill the blockchain." << endl << " -K,--kill First kill the blockchain." << endl
<< " --listen-ip <port> Listen on the given port for incoming connections (default: 30303)." << endl << " --listen-ip <port> Listen on the given port for incoming connections (default: 30303)." << endl
<< " -l,--listen <ip> Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl << " -l,--listen <ip> Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
<< " -u,--public-ip <ip> Force public ip to given (default: auto)." << endl << " -u,--public-ip <ip> Force public ip to given (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (Default: off)" << endl << " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (Default: off)" << endl
<< " -n,--upnp <on/off> Use upnp for NAT (default: on)." << endl << " -n,-u,--upnp <on/off> Use upnp for NAT (default: on)." << endl
<< " -o,--mode <full/peer> Start a full node or a peer node (Default: full)." << endl << " -o,--mode <full/peer> Start a full node or a peer node (Default: full)." << endl
<< " -p,--port <port> Connect to remote port (default: 30303)." << endl << " -p,--port <port> Connect to remote port (default: 30303)." << endl
<< " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl
<< " -R,--rebuild First rebuild the blockchain from the existing database." << endl << " -R,--rebuild First rebuild the blockchain from the existing database." << endl
<< " -r,--remote <host> Connect to remote host (default: none)." << endl << " -r,--remote <host> Connect to remote host (default: none)." << endl
<< " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl << " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl
<< " -t,--miners <number> Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (Default: 5)." << endl << " -x,--peers <number> Attempt to connect to given number of peers (Default: 5)." << endl
<< " -V,--version Show the version and exit." << endl << " -V,--version Show the version and exit." << endl
@ -337,7 +339,7 @@ int main(int argc, char** argv)
exportFrom = argv[++i]; exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc) else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i]; exportTo = exportFrom = argv[++i];
else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc) else if ((arg == "-n" || arg == "-u" || arg == "--upnp") && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
if (isTrue(m)) if (isTrue(m))
@ -489,15 +491,12 @@ int main(int argc, char** argv)
return -1; return -1;
} }
} }
else if (arg == "--jit")
{
#if ETH_EVMJIT #if ETH_EVMJIT
else if (arg == "-J" || arg == "--jit")
{
jit = true; jit = true;
#else
cerr << "EVM JIT not enabled" << endl;
return -1;
#endif
} }
#endif
else if (arg == "-h" || arg == "--help") else if (arg == "-h" || arg == "--help")
help(); help();
else if (arg == "-V" || arg == "--version") else if (arg == "-V" || arg == "--version")

54
exp/main.cpp

@ -34,9 +34,9 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieDB.h> #include <libdevcrypto/TrieDB.h>
#include <libp2p/All.h> #include <libp2p/All.h>
#include <libethcore/Ethasher.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#include <libethereum/Farm.h>
#include <libethereum/AccountDiff.h> #include <libethereum/AccountDiff.h>
#include <libethereum/DownloadMan.h> #include <libethereum/DownloadMan.h>
#include <liblll/All.h> #include <liblll/All.h>
@ -109,18 +109,50 @@ int main()
#else #else
int main() int main()
{ {
#if ETH_ETHASHCL GenericFarm<Ethash> f;
EthashCL ecl;
BlockInfo genesis = CanonBlockChain::genesis(); BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18; genesis.difficulty = 1 << 18;
cdebug << (h256)u256((bigint(1) << 256) / genesis.difficulty); cdebug << genesis.boundary();
std::pair<MineInfo, Ethash::Solution> r;
while (!r.first.completed) auto mine = [](GenericFarm<Ethash>& f, BlockInfo const& g, unsigned timeout) {
r = ecl.mine(genesis, 1000); BlockInfo bi = g;
cdebug << r.second.mixHash << r.second.nonce; bool completed = false;
EthashCL::assignResult(r.second, genesis); f.onSolutionFound([&](ProofOfWork::Solution sol)
assert(EthashCPU::verify(genesis)); {
#endif ProofOfWork::assignResult(sol, bi);
return completed = true;
});
f.setWork(bi);
for (unsigned i = 0; !completed && i < timeout * 10; ++i, cout << f.miningProgress() << "\r" << flush)
this_thread::sleep_for(chrono::milliseconds(100));
cdebug << bi.mixHash << bi.nonce << (Ethash::verify(bi) ? "GOOD" : "bad");
};
f.startCPU();
mine(f, genesis, 10);
mine(f, genesis, 10);
f.startGPU();
cdebug << "Good:";
genesis.difficulty = 1 << 18;
genesis.noteDirty();
mine(f, genesis, 3);
cdebug << "Bad:";
genesis.difficulty = (u256(1) << 40);
genesis.noteDirty();
mine(f, genesis, 3);
cdebug << "Good:";
genesis.difficulty = 1 << 18;
genesis.noteDirty();
mine(f, genesis, 3);
cdebug << "Bad:";
genesis.difficulty = (u256(1) << 40);
genesis.noteDirty();
mine(f, genesis, 3);
return 0; return 0;
} }
#endif #endif

3
libdevcore/Worker.h

@ -66,6 +66,9 @@ protected:
/// Called when is to be stopped, just prior to thread being joined. /// Called when is to be stopped, just prior to thread being joined.
virtual void doneWorking() {} virtual void doneWorking() {}
/// Blocks caller into worker thread has finished.
void join() const { Guard l(x_work); try { if (m_work) m_work->join(); } catch (...) {} }
private: private:
std::string m_name; std::string m_name;
unsigned m_idleWaitMs = 0; unsigned m_idleWaitMs = 0;

52
libethcore/Ethash.cpp

@ -63,7 +63,7 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi)
{ {
WorkPackage ret; WorkPackage ret;
ret.boundary = _bi.boundary(); ret.boundary = _bi.boundary();
ret.headerHash = _bi.headerHash(WithNonce); ret.headerHash = _bi.headerHash(WithoutNonce);
ret.seedHash = _bi.seedHash(); ret.seedHash = _bi.seedHash();
return ret; return ret;
} }
@ -95,9 +95,8 @@ bool Ethash::verify(BlockInfo const& _header)
return false; return false;
#endif #endif
h256 boundary = u256((bigint(1) << 256) / _header.difficulty);
auto result = EthashAux::eval(_header); auto result = EthashAux::eval(_header);
bool slow = result.value <= boundary && result.mixHash == _header.mixHash; bool slow = result.value <= _header.boundary() && result.mixHash == _header.mixHash;
#if ETH_DEBUG || !ETH_TRUE #if ETH_DEBUG || !ETH_TRUE
if (!pre && slow) if (!pre && slow)
@ -107,7 +106,7 @@ bool Ethash::verify(BlockInfo const& _header)
cwarn << "nonce:" << _header.nonce; cwarn << "nonce:" << _header.nonce;
cwarn << "mixHash:" << _header.mixHash; cwarn << "mixHash:" << _header.mixHash;
cwarn << "difficulty:" << _header.difficulty; cwarn << "difficulty:" << _header.difficulty;
cwarn << "boundary:" << boundary; cwarn << "boundary:" << _header.boundary();
cwarn << "result.value:" << result.value; cwarn << "result.value:" << result.value;
cwarn << "result.mixHash:" << result.mixHash; cwarn << "result.mixHash:" << result.mixHash;
} }
@ -125,16 +124,18 @@ void Ethash::CPUMiner::workLoop()
ethash_return_value ethashReturn; ethash_return_value ethashReturn;
auto p = EthashAux::params(m_work.seedHash); auto p = EthashAux::params(m_work.seedHash);
void const* dagPointer = EthashAux::full(m_work.headerHash).data(); void const* dagPointer = EthashAux::full(m_work.seedHash).data();
uint8_t const* headerHashPointer = m_work.headerHash.data(); uint8_t const* headerHashPointer = m_work.headerHash.data();
h256 boundary = m_work.boundary; h256 boundary = m_work.boundary;
unsigned hashCount = 0; unsigned hashCount = 1;
for (; !shouldStop(); tryNonce++, hashCount++) for (; !shouldStop(); tryNonce++, hashCount++)
{ {
ethash_compute_full(&ethashReturn, dagPointer, &p, headerHashPointer, tryNonce); ethash_compute_full(&ethashReturn, dagPointer, &p, headerHashPointer, tryNonce);
h256 value = h256(ethashReturn.result, h256::ConstructFromPointer); h256 value = h256(ethashReturn.result, h256::ConstructFromPointer);
if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256(ethashReturn.mix_hash, h256::ConstructFromPointer)})) if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256(ethashReturn.mix_hash, h256::ConstructFromPointer)}))
break; break;
if (!(hashCount % 1000))
accumulateHashes(1000);
} }
} }
@ -148,6 +149,7 @@ public:
void abort() void abort()
{ {
Guard l(x_all); Guard l(x_all);
m_owner->m_work.headerHash = h256();
if (m_aborted) if (m_aborted)
return; return;
// cdebug << "Attempting to abort"; // cdebug << "Attempting to abort";
@ -159,8 +161,6 @@ public:
m_aborted = m_abort = false; m_aborted = m_abort = false;
} }
uint64_t fetchTotal() { Guard l(x_all); auto ret = m_total; m_total = 0; return ret; }
protected: protected:
virtual bool found(uint64_t const* _nonces, uint32_t _count) override virtual bool found(uint64_t const* _nonces, uint32_t _count) override
{ {
@ -180,7 +180,7 @@ protected:
{ {
Guard l(x_all); Guard l(x_all);
// cdebug << "Searched" << _count << "from" << _startNonce; // cdebug << "Searched" << _count << "from" << _startNonce;
m_total += _count; m_owner->accumulateHashes(_count);
m_last = _startNonce + _count; m_last = _startNonce + _count;
if (m_abort) if (m_abort)
{ {
@ -192,7 +192,6 @@ protected:
private: private:
Mutex x_all; Mutex x_all;
uint64_t m_total;
uint64_t m_last; uint64_t m_last;
bool m_abort = false; bool m_abort = false;
bool m_aborted = true; bool m_aborted = true;
@ -214,38 +213,43 @@ Ethash::GPUMiner::~GPUMiner()
bool Ethash::GPUMiner::report(uint64_t _nonce) bool Ethash::GPUMiner::report(uint64_t _nonce)
{ {
Nonce n = (Nonce)(u64)_nonce; Nonce n = (Nonce)(u64)_nonce;
Result r = EthashAux::eval(m_lastWork.seedHash, m_lastWork.headerHash, n); Result r = EthashAux::eval(m_work.seedHash, m_work.headerHash, n);
if (r.value < m_lastWork.boundary) if (r.value < m_work.boundary)
return submitProof(Solution{n, r.mixHash}); return submitProof(Solution{n, r.mixHash});
return false; return false;
} }
void Ethash::GPUMiner::kickOff(WorkPackage const& _work) void Ethash::GPUMiner::kickOff(WorkPackage const& _work)
{ {
if (!m_miner || m_minerSeed != _work.seedHash) m_work = _work;
startWorking();
}
void Ethash::GPUMiner::workLoop()
{
// take local copy of work since it may end up being overwritten by kickOff/pause.
WorkPackage w = m_work;
if (!m_miner || m_minerSeed != w.seedHash)
{ {
if (m_miner) m_minerSeed = w.seedHash;
m_hook->abort();
delete m_miner; delete m_miner;
m_miner = new ethash_cl_miner; m_miner = new ethash_cl_miner;
auto p = EthashAux::params(_work.seedHash); auto p = EthashAux::params(m_minerSeed);
auto cb = [&](void* d) { EthashAux::full(_work.seedHash, bytesRef((byte*)d, p.full_size)); }; auto cb = [&](void* d) { EthashAux::full(m_minerSeed, bytesRef((byte*)d, p.full_size)); };
m_miner->init(p, cb, 32); m_miner->init(p, cb, 32);
} }
if (m_lastWork.headerHash != _work.headerHash)
{ uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);
m_hook->abort(); m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook);
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)_work.boundary >> 192);
m_miner->search(_work.headerHash.data(), upper64OfBoundary, *m_hook);
}
m_lastWork = _work;
} }
void Ethash::GPUMiner::pause() void Ethash::GPUMiner::pause()
{ {
m_hook->abort(); m_hook->abort();
stopWorking();
m_work.headerHash = h256();
} }
#endif #endif

22
libethcore/Ethash.h

@ -59,6 +59,11 @@ public:
struct WorkPackage struct WorkPackage
{ {
WorkPackage() = default;
void reset() { headerHash = h256(); }
operator bool() const { return headerHash != h256(); }
h256 boundary; h256 boundary;
h256 headerHash; ///< When h256() means "pause until notified a new work package is available". h256 headerHash; ///< When h256() means "pause until notified a new work package is available".
h256 seedHash; h256 seedHash;
@ -89,17 +94,16 @@ public:
startWorking(); startWorking();
} }
void pause() override { stopWorking(); } void pause() override { stopWorking(); m_work.reset(); }
private: private:
void workLoop() override; void workLoop() override;
WorkPackage m_work; WorkPackage m_work;
MineInfo m_info;
}; };
#if ETH_ETHASHCL || !ETH_TRUE #if ETH_ETHASHCL || !ETH_TRUE
class GPUMiner: public Miner class GPUMiner: public Miner, Worker
{ {
friend class dev::eth::EthashCLHook; friend class dev::eth::EthashCLHook;
@ -114,14 +118,16 @@ public:
void pause() override; void pause() override;
private: private:
void workLoop() override;
bool report(uint64_t _nonce); bool report(uint64_t _nonce);
EthashCLHook* m_hook; using Miner::accumulateHashes;
ethash_cl_miner* m_miner;
EthashCLHook* m_hook = nullptr;
ethash_cl_miner* m_miner = nullptr;
h256 m_minerSeed; h256 m_minerSeed; ///< Last seed in m_miner
WorkPackage m_lastWork; ///< Work loaded into m_miner. WorkPackage m_work; ///< Work to be done by GPU, set with kickOff and picked up in workLoop.
MineInfo m_info;
}; };
#else #else
using GPUMiner = CPUMiner; using GPUMiner = CPUMiner;

35
libethcore/Miner.h

@ -34,30 +34,24 @@ namespace dev
namespace eth namespace eth
{ {
struct MineInfo
{
MineInfo() = default;
MineInfo(bool _completed): completed(_completed) {}
void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; }
double requirement = 0;
double best = 1e99;
unsigned hashes = 0;
bool completed = false;
};
/** /**
* @brief Describes the progress of a mining operation. * @brief Describes the progress of a mining operation.
*/ */
struct MiningProgress struct MiningProgress
{ {
void combine(MiningProgress const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); current = std::max(current, _m.current); hashes += _m.hashes; ms = std::max(ms, _m.ms); } // MiningProgress& operator+=(MiningProgress const& _mp) { hashes += _mp.hashes; ms = std::max(ms, _mp.ms); return *this; }
double requirement = 0; ///< The PoW requirement - as the second logarithm of the minimum acceptable hash.
double best = 1e99; ///< The PoW achievement - as the second logarithm of the minimum found hash.
double current = 0; ///< The most recent PoW achievement - as the second logarithm of the presently found hash.
unsigned hashes = 0; ///< Total number of hashes computed. unsigned hashes = 0; ///< Total number of hashes computed.
unsigned ms = 0; ///< Total number of milliseconds of mining thus far. unsigned ms = 0; ///< Total number of milliseconds of mining thus far.
}; };
struct MineInfo: public MiningProgress {};
inline std::ostream& operator<<(std::ostream& _out, MiningProgress const& _p)
{
_out << (_p.hashes * 1000 / _p.ms) << "H/s = " << _p.hashes << " hashes / " << (double(_p.ms) / 1000) << "s";
return _out;
}
template <class PoW> class GenericMiner; template <class PoW> class GenericMiner;
/** /**
@ -103,13 +97,18 @@ public:
void setWork(WorkPackage const& _work = WorkPackage()) void setWork(WorkPackage const& _work = WorkPackage())
{ {
Guard l(x_work); Guard l(x_work);
if (_work.headerHash == m_work.headerHash)
return;
if (_work.headerHash != h256()) if (_work.headerHash != h256())
kickOff(m_work); kickOff(_work);
else if (m_work.headerHash == h256() && _work.headerHash != h256()) else if (m_work.headerHash == h256() && _work.headerHash != h256())
pause(); pause();
m_work = _work; m_work = _work;
m_hashCount = 0;
} }
unsigned hashCount() { return m_hashCount; }
unsigned index() const { return m_index; } unsigned index() const { return m_index; }
protected: protected:
@ -146,12 +145,16 @@ protected:
WorkPackage const& work() const { return m_work; } WorkPackage const& work() const { return m_work; }
void accumulateHashes(unsigned _n) { m_hashCount += _n; }
private: private:
FarmFace* m_farm = nullptr; FarmFace* m_farm = nullptr;
unsigned m_index; unsigned m_index;
Mutex x_work; Mutex x_work;
WorkPackage m_work; WorkPackage m_work;
unsigned m_hashCount = 0;
}; };
} }

45
libethereum/Farm.h

@ -56,16 +56,16 @@ public:
*/ */
void setWork(BlockInfo const& _bi) void setWork(BlockInfo const& _bi)
{ {
WorkPackage w; WriteGuard l(x_work);
{
WriteGuard l(x_work);
m_header = _bi;
w = m_work = PoW::package(m_header);
}
ReadGuard l2(x_miners); ReadGuard l2(x_miners);
m_header = _bi;
auto p = PoW::package(m_header);
if (p.headerHash == m_work.headerHash)
return;
m_work = p;
for (auto const& m: m_miners) for (auto const& m: m_miners)
m->setWork(m_work); m->setWork(m_work);
resetTimer();
} }
/** /**
@ -99,7 +99,19 @@ public:
* @brief Get information on the progress of mining this work package. * @brief Get information on the progress of mining this work package.
* @return The progress with mining so far. * @return The progress with mining so far.
*/ */
MiningProgress const& miningProgress() const { ReadGuard l(x_progress); return m_progress; } MiningProgress const& miningProgress() const
{
MiningProgress p;
p.ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_lastStart).count();
{
ReadGuard l2(x_miners);
for (auto const& i: m_miners)
p.hashes += i->hashCount();
}
ReadGuard l(x_progress);
m_progress = p;
return m_progress;
}
using SolutionFound = std::function<bool(Solution const&)>; using SolutionFound = std::function<bool(Solution const&)>;
@ -110,6 +122,8 @@ public:
*/ */
void onSolutionFound(SolutionFound const& _handler) { m_onSolutionFound = _handler; } void onSolutionFound(SolutionFound const& _handler) { m_onSolutionFound = _handler; }
WorkPackage work() const { ReadGuard l(x_work); return m_work; }
private: private:
/** /**
* @brief Called from a Miner to note a WorkPackage has a solution. * @brief Called from a Miner to note a WorkPackage has a solution.
@ -140,21 +154,32 @@ private:
template <class MinerType> template <class MinerType>
bool start() bool start()
{ {
WriteGuard l(x_miners); ReadGuard l(x_work);
WriteGuard l2(x_miners);
if (!m_miners.empty() && !!std::dynamic_pointer_cast<MinerType>(m_miners[0])) if (!m_miners.empty() && !!std::dynamic_pointer_cast<MinerType>(m_miners[0]))
return true; return true;
m_miners.clear(); m_miners.clear();
m_miners.reserve(MinerType::instances()); m_miners.reserve(MinerType::instances());
for (unsigned i = 0; i < MinerType::instances(); ++i) for (unsigned i = 0; i < MinerType::instances(); ++i)
{
m_miners.push_back(std::shared_ptr<Miner>(new MinerType(std::make_pair(this, i)))); m_miners.push_back(std::shared_ptr<Miner>(new MinerType(std::make_pair(this, i))));
m_miners.back()->setWork(m_work);
}
resetTimer();
return true; return true;
} }
void resetTimer()
{
m_lastStart = std::chrono::steady_clock::now();
}
mutable SharedMutex x_miners; mutable SharedMutex x_miners;
std::vector<std::shared_ptr<Miner>> m_miners; std::vector<std::shared_ptr<Miner>> m_miners;
mutable SharedMutex x_progress; mutable SharedMutex x_progress;
MiningProgress m_progress; mutable MiningProgress m_progress;
std::chrono::steady_clock::time_point m_lastStart;
mutable SharedMutex x_work; mutable SharedMutex x_work;
WorkPackage m_work; WorkPackage m_work;

23
mix/MixClient.cpp

@ -20,6 +20,7 @@
* Ethereum IDE client. * Ethereum IDE client.
*/ */
#include "MixClient.h"
#include <vector> #include <vector>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
@ -28,10 +29,8 @@
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/BlockChain.h> #include <libethereum/BlockChain.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "Exceptions.h" #include "Exceptions.h"
#include "MixClient.h" using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -250,9 +249,17 @@ void MixClient::mine()
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
m_state.commitToMine(bc()); m_state.commitToMine(bc());
ProofOfWork pow; GenericFarm<ProofOfWork> f;
while (!m_state.mine(&pow).completed) {} bool completed = false;
m_state.completeMine(); f.onSolutionFound([&](ProofOfWork::Solution sol)
{
return completed = m_state.completeMine<ProofOfWork>(sol);
});
f.setWork(m_state.info());
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
bc().import(m_state.blockData(), m_stateDB); bc().import(m_state.blockData(), m_stateDB);
m_state.sync(bc()); m_state.sync(bc());
m_startState = m_state; m_startState = m_state;
@ -392,9 +399,9 @@ uint64_t MixClient::hashrate() const
return 0; return 0;
} }
eth::MineProgress MixClient::miningProgress() const eth::MiningProgress MixClient::miningProgress() const
{ {
return eth::MineProgress(); return eth::MiningProgress();
} }
} }

4
mix/MixClient.h

@ -67,8 +67,8 @@ public:
void stopMining() override; void stopMining() override;
bool isMining() const override; bool isMining() const override;
uint64_t hashrate() const override; uint64_t hashrate() const override;
eth::MineProgress miningProgress() const override; eth::MiningProgress miningProgress() const override;
std::pair<h256, u256> getWork() override { return std::pair<h256, u256>(); } eth::ProofOfWork::WorkPackage getWork() override { return eth::ProofOfWork::WorkPackage(); }
bool submitWork(eth::ProofOfWork::Solution const&) override { return false; } bool submitWork(eth::ProofOfWork::Solution const&) override { return false; }
virtual void flushTransactions() override {} virtual void flushTransactions() override {}

10
neth/main.cpp

@ -40,7 +40,6 @@
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h> #include <jsonrpccpp/server/connectors/httpserver.h>
#endif #endif
#include <libethcore/Ethasher.h>
#include "BuildInfo.h" #include "BuildInfo.h"
#undef KEY_EVENT // from windows.h #undef KEY_EVENT // from windows.h
@ -332,7 +331,6 @@ int main(int argc, char** argv)
unsigned mining = ~(unsigned)0; unsigned mining = ~(unsigned)0;
NodeMode mode = NodeMode::Full; NodeMode mode = NodeMode::Full;
unsigned peers = 5; unsigned peers = 5;
int miners = -1;
#if ETH_JSONRPC #if ETH_JSONRPC
int jsonrpc = 8080; int jsonrpc = 8080;
#endif #endif
@ -502,8 +500,6 @@ int main(int argc, char** argv)
g_logVerbosity = atoi(argv[++i]); g_logVerbosity = atoi(argv[++i]);
else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
peers = atoi(argv[++i]); peers = atoi(argv[++i]);
else if ((arg == "-t" || arg == "--miners") && i + 1 < argc)
miners = atoi(argv[++i]);
else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
@ -553,9 +549,7 @@ int main(int argc, char** argv)
killChain ? WithExisting::Kill : WithExisting::Trust, killChain ? WithExisting::Kill : WithExisting::Trust,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(), mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
netPrefs, netPrefs,
&nodesState, &nodesState);
miners
);
web3.setIdealPeerCount(peers); web3.setIdealPeerCount(peers);
std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
@ -1253,7 +1247,7 @@ int main(int argc, char** argv)
if (c && c->isMining()) if (c && c->isMining())
{ {
mvwprintw(consolewin, qheight - 1, width / 4 - 11, "Mining ON"); mvwprintw(consolewin, qheight - 1, width / 4 - 11, "Mining ON");
dev::eth::MineProgress p = c->miningProgress(); dev::eth::MiningProgress p = c->miningProgress();
auto speed = boost::format("%2% kH/s @ %1%s") % (p.ms / 1000) % (p.ms ? p.hashes / p.ms : 0); auto speed = boost::format("%2% kH/s @ %1%s") % (p.ms / 1000) % (p.ms ? p.hashes / p.ms : 0);
mvwprintw(consolewin, qheight - 2, width / 4 - speed.str().length() - 2, speed.str().c_str()); mvwprintw(consolewin, qheight - 2, width / 4 - speed.str().length() - 2, speed.str().c_str());
} }

31
test/TestHelper.cpp

@ -62,6 +62,37 @@ void connectClients(Client& c1, Client& c2)
c2.connect("127.0.0.1", c1Port); c2.connect("127.0.0.1", c1Port);
#endif #endif
} }
void mine(State& s, BlockChain const& _bc)
{
s.commitToMine(_bc);
GenericFarm<ProofOfWork> f;
bool completed = false;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
return completed = s.completeMine<ProofOfWork>(sol);
});
f.setWork(s.info());
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
}
void mine(BlockInfo& _bi)
{
GenericFarm<ProofOfWork> f;
bool completed = false;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
ProofOfWork::assignResult(sol, _bi);
return completed = true;
});
f.setWork(_bi);
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
}
} }
namespace test namespace test

5
test/TestHelper.h

@ -36,9 +36,12 @@ namespace eth
{ {
class Client; class Client;
class State;
void mine(Client& c, int numBlocks); void mine(Client& c, int numBlocks);
void connectClients(Client& c1, Client& c2); void connectClients(Client& c1, Client& c2);
void mine(State& _s, BlockChain const& _bc);
void mine(BlockInfo& _bi);
} }
@ -225,7 +228,5 @@ public:
}; };
}; };
} }
} }

111
test/blockchain.cpp

@ -190,11 +190,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
{ {
state.sync(bc); state.sync(bc);
state.sync(bc, txs, gp); state.sync(bc, txs, gp);
state.commitToMine(bc); mine(state, bc);
MineInfo info;
ProofOfWork pow;
for (info.completed = false; !info.completed; info = state.mine(&pow)) {}
state.completeMine();
} }
catch (Exception const& _e) catch (Exception const& _e)
{ {
@ -519,76 +515,55 @@ bytes createBlockRLPFromFields(mObject& _tObj)
return rlpStream.out(); return rlpStream.out();
} }
void overwriteBlockHeader(BlockInfo& _currentBlockHeader, mObject& _blObj) void overwriteBlockHeader(BlockInfo& _header, mObject& _blObj)
{ {
if (_blObj["blockHeader"].get_obj().size() != 14) auto ho = _blObj["blockHeader"].get_obj();
if (ho.size() != 14)
{ {
BlockInfo tmp = _header;
BlockInfo tmp = _currentBlockHeader; if (ho.count("parentHash"))
tmp.parentHash = h256(ho["parentHash"].get_str());
if (_blObj["blockHeader"].get_obj().count("parentHash")) if (ho.count("uncleHash"))
tmp.parentHash = h256(_blObj["blockHeader"].get_obj()["parentHash"].get_str()); tmp.sha3Uncles = h256(ho["uncleHash"].get_str());
if (ho.count("coinbase"))
if (_blObj["blockHeader"].get_obj().count("uncleHash")) tmp.coinbaseAddress = Address(ho["coinbase"].get_str());
tmp.sha3Uncles = h256(_blObj["blockHeader"].get_obj()["uncleHash"].get_str()); if (ho.count("stateRoot"))
tmp.stateRoot = h256(ho["stateRoot"].get_str());
if (_blObj["blockHeader"].get_obj().count("coinbase")) if (ho.count("transactionsTrie"))
tmp.coinbaseAddress = Address(_blObj["blockHeader"].get_obj()["coinbase"].get_str()); tmp.transactionsRoot = h256(ho["transactionsTrie"].get_str());
if (ho.count("receiptTrie"))
if (_blObj["blockHeader"].get_obj().count("stateRoot")) tmp.receiptsRoot = h256(ho["receiptTrie"].get_str());
tmp.stateRoot = h256(_blObj["blockHeader"].get_obj()["stateRoot"].get_str()); if (ho.count("bloom"))
tmp.logBloom = LogBloom(ho["bloom"].get_str());
if (_blObj["blockHeader"].get_obj().count("transactionsTrie")) if (ho.count("difficulty"))
tmp.transactionsRoot = h256(_blObj["blockHeader"].get_obj()["transactionsTrie"].get_str()); tmp.difficulty = toInt(ho["difficulty"]);
if (ho.count("number"))
if (_blObj["blockHeader"].get_obj().count("receiptTrie")) tmp.number = toInt(ho["number"]);
tmp.receiptsRoot = h256(_blObj["blockHeader"].get_obj()["receiptTrie"].get_str()); if (ho.count("gasLimit"))
tmp.gasLimit = toInt(ho["gasLimit"]);
if (_blObj["blockHeader"].get_obj().count("bloom")) if (ho.count("gasUsed"))
tmp.logBloom = LogBloom(_blObj["blockHeader"].get_obj()["bloom"].get_str()); tmp.gasUsed = toInt(ho["gasUsed"]);
if (ho.count("timestamp"))
if (_blObj["blockHeader"].get_obj().count("difficulty")) tmp.timestamp = toInt(ho["timestamp"]);
tmp.difficulty = toInt(_blObj["blockHeader"].get_obj()["difficulty"]); if (ho.count("extraData"))
tmp.extraData = importByteArray(ho["extraData"].get_str());
if (_blObj["blockHeader"].get_obj().count("number")) if (ho.count("mixHash"))
tmp.number = toInt(_blObj["blockHeader"].get_obj()["number"]); tmp.mixHash = h256(ho["mixHash"].get_str());
tmp.noteDirty();
if (_blObj["blockHeader"].get_obj().count("gasLimit"))
tmp.gasLimit = toInt(_blObj["blockHeader"].get_obj()["gasLimit"]);
if (_blObj["blockHeader"].get_obj().count("gasUsed"))
tmp.gasUsed = toInt(_blObj["blockHeader"].get_obj()["gasUsed"]);
if (_blObj["blockHeader"].get_obj().count("timestamp"))
tmp.timestamp = toInt(_blObj["blockHeader"].get_obj()["timestamp"]);
if (_blObj["blockHeader"].get_obj().count("extraData"))
tmp.extraData = importByteArray(_blObj["blockHeader"].get_obj()["extraData"].get_str());
if (_blObj["blockHeader"].get_obj().count("mixHash"))
tmp.mixHash = h256(_blObj["blockHeader"].get_obj()["mixHash"].get_str());
// find new valid nonce // find new valid nonce
if (tmp != _header)
if (tmp != _currentBlockHeader)
{ {
_currentBlockHeader = tmp; mine(tmp);
_header = tmp;
ProofOfWork pow;
std::pair<MineInfo, Ethash::Solution> ret;
while (!ProofOfWork::verify(_currentBlockHeader))
{
ret = pow.mine(_currentBlockHeader, 1000, true);
Ethash::assignResult(ret.second, _currentBlockHeader);
}
} }
} }
else else
{ {
// take the blockheader as is // take the blockheader as is
const bytes c_blockRLP = createBlockRLPFromFields(_blObj["blockHeader"].get_obj()); const bytes c_blockRLP = createBlockRLPFromFields(ho);
const RLP c_bRLP(c_blockRLP); const RLP c_bRLP(c_blockRLP);
_currentBlockHeader.populateFromHeader(c_bRLP, IgnoreNonce); _header.populateFromHeader(c_bRLP, IgnoreNonce);
} }
} }
@ -620,13 +595,7 @@ BlockInfo constructBlock(mObject& _o)
void updatePoW(BlockInfo& _bi) void updatePoW(BlockInfo& _bi)
{ {
ProofOfWork pow; mine(_bi);
std::pair<MineInfo, Ethash::Solution> ret;
while (!ProofOfWork::verify(_bi))
{
ret = pow.mine(_bi, 10000, true);
Ethash::assignResult(ret.second, _bi);
}
_bi.noteDirty(); _bi.noteDirty();
} }

12
test/dagger.cpp

@ -25,7 +25,7 @@
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/Ethasher.h> #include <libethcore/EthashAux.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "TestHelper.h" #include "TestHelper.h"
@ -63,18 +63,18 @@ BOOST_AUTO_TEST_CASE(basic_test)
unsigned cacheSize(o["cache_size"].get_int()); unsigned cacheSize(o["cache_size"].get_int());
h256 cacheHash(o["cache_hash"].get_str()); h256 cacheHash(o["cache_hash"].get_str());
BOOST_REQUIRE_EQUAL(Ethasher::get()->params(header).cache_size, cacheSize); BOOST_REQUIRE_EQUAL(EthashAux::get()->params(header).cache_size, cacheSize);
BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)Ethasher::get()->light(header), cacheSize)), cacheHash); BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)EthashAux::get()->light(header), cacheSize)), cacheHash);
#if TEST_FULL #if TEST_FULL
unsigned fullSize(o["full_size"].get_int()); unsigned fullSize(o["full_size"].get_int());
h256 fullHash(o["full_hash"].get_str()); h256 fullHash(o["full_hash"].get_str());
BOOST_REQUIRE_EQUAL(Ethasher::get()->full(header).size(), fullSize); BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header).size(), fullSize);
BOOST_REQUIRE_EQUAL(sha3(Ethasher::get()->full(header)), fullHash); BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header)), fullHash);
#endif #endif
h256 result(o["result"].get_str()); h256 result(o["result"].get_str());
Ethasher::Result r = Ethasher::eval(header); Ethash::Result r = EthashAux::eval(header);
BOOST_REQUIRE_EQUAL(r.value, result); BOOST_REQUIRE_EQUAL(r.value, result);
BOOST_REQUIRE_EQUAL(r.mixHash, header.mixHash); BOOST_REQUIRE_EQUAL(r.mixHash, header.mixHash);
} }

11
test/stateOriginal.cpp

@ -25,7 +25,9 @@
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/Farm.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
#include "TestHelper.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -67,10 +69,8 @@ BOOST_AUTO_TEST_CASE(Complex)
cout << s; cout << s;
// Mine to get some ether! // Mine to get some ether!
s.commitToMine(bc); mine(s, bc);
ProofOfWork pow;
while (!s.mine(&pow).completed) {}
s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);
cout << bc; cout << bc;
@ -89,8 +89,7 @@ BOOST_AUTO_TEST_CASE(Complex)
// Mine to get some ether and set in stone. // Mine to get some ether and set in stone.
s.commitToMine(bc); s.commitToMine(bc);
s.commitToMine(bc); s.commitToMine(bc);
while (!s.mine(&pow).completed) {} mine(s, bc);
s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);
cout << bc; cout << bc;

2
third/MainWin.cpp

@ -465,7 +465,7 @@ void Main::on_urlEdit_returnPressed()
void Main::refreshMining() void Main::refreshMining()
{ {
dev::eth::MineProgress p = ethereum()->miningProgress(); dev::eth::MiningProgress p = ethereum()->miningProgress();
ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining");
} }

Loading…
Cancel
Save