Browse Source

Mining view.

cl-refactor
Gav Wood 11 years ago
parent
commit
57129c2007
  1. 103
      alethzero/GraphParameters.h
  2. 195
      alethzero/Grapher.cpp
  3. 116
      alethzero/Grapher.h
  4. 39
      alethzero/Main.ui
  5. 79
      alethzero/MainWin.cpp
  6. 28
      alethzero/MainWin.h
  7. 107
      alethzero/MiningView.cpp
  8. 56
      alethzero/MiningView.h
  9. 10
      libethcore/Dagger.cpp
  10. 5
      libethcore/Dagger.h
  11. 13
      libethereum/Client.cpp
  12. 14
      libethereum/Client.h
  13. 31
      libethereum/Executive.cpp
  14. 2
      libethereum/Executive.h
  15. 31
      libethsupport/CommonIO.cpp
  16. 3
      libethsupport/CommonIO.h
  17. 11
      libethsupport/FixedHash.h

103
alethzero/GraphParameters.h

@ -0,0 +1,103 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <type_traits>
#include <cmath>
#undef foreach
#define foreach BOOST_FOREACH
namespace lb
{
template <class T>
static T graphParameters(T _min, T _max, unsigned _divisions, T* o_from = 0, T* o_delta = 0, bool _forceMinor = false, T _divisor = 1)
{
T uMin = _min / _divisor;
T uMax = _max / _divisor;
if (uMax == uMin || !_divisions)
{
*o_from = 0;
*o_delta = 1;
return 1;
}
long double l10 = std::log10((uMax - uMin) / T(_divisions) * 5.5f);
long double mt = std::pow(10.f, l10 - std::floor(l10));
long double ep = std::pow(10.f, std::floor(l10));
T inc = _forceMinor
? ((mt > 6.f) ? ep / 2.f : (mt > 3.f) ? ep / 5.f : (mt > 1.2f) ? ep / 10.f : ep / 20.f)
: ((mt > 6.f) ? ep * 2.f : (mt > 3.f) ? ep : (mt > 1.2f) ? ep / 2.f : ep / 5.f);
if (inc == 0)
inc = 1;
if (o_delta && o_from)
{
(*o_from) = std::floor(uMin / inc) * inc * _divisor;
(*o_delta) = (std::ceil(uMax / inc) - std::floor(uMin / inc)) * inc * _divisor;
}
else if (o_from)
{
(*o_from) = std::ceil(uMin / inc) * inc * _divisor;
}
return inc * _divisor;
}
struct GraphParametersForceMinor { GraphParametersForceMinor() {} };
static const GraphParametersForceMinor ForceMinor;
template <class T>
struct GraphParameters
{
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions)
{
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false);
to = from + delta;
}
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, GraphParametersForceMinor)
{
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true);
to = from + delta;
}
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, T _divisor)
{
major = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false, _divisor);
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true, _divisor);
to = from + delta;
}
template <class S, class Enable = void>
struct MajorDeterminor { static bool go(S _s, S _j) { S ip; S fp = std::modf(_s / _j + S(0.5), &ip); return fabs(fabs(fp) - 0.5) < 0.05; } };
template <class S>
struct MajorDeterminor<S, typename std::enable_if<std::is_integral<S>::value>::type> { static S go(S _s, S _j) { return _s % _j == 0; } };
bool isMajor(T _t) const { return MajorDeterminor<T>::go(_t, major); }
T from;
T delta;
T major;
T to;
T incr;
};
}

195
alethzero/Grapher.cpp

@ -0,0 +1,195 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QPainter>
#include "GraphParameters.h"
#include "Grapher.h"
using namespace std;
using namespace lb;
void Grapher::init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float)> _xLabel, std::function<std::string(float)> _yLabel, std::function<std::string(float, float)> _pLabel, int _leftGutter, int _bottomGutter)
{
fontPixelSize = QFontInfo(QFont("Ubuntu", 10)).pixelSize();
if (_leftGutter)
_leftGutter = max<int>(_leftGutter, fontPixelSize * 2);
if (_bottomGutter)
_bottomGutter = max<int>(_bottomGutter, fontPixelSize * 1.25);
QRect a(_leftGutter, 0, _p->viewport().width() - _leftGutter, _p->viewport().height() - _bottomGutter);
init(_p, _xRange, _yRange, _xLabel, _yLabel, _pLabel, a);
}
bool Grapher::drawAxes(bool _x, bool _y) const
{
int w = active.width();
int h = active.height();
int l = active.left();
int r = active.right();
int t = active.top();
int b = active.bottom();
p->setFont(QFont("Ubuntu", 10));
p->fillRect(p->viewport(), qRgb(255, 255, 255));
static const int c_markLength = 2;
static const int c_markSpacing = 2;
static const int c_xSpacing = fontPixelSize * 3;
static const int c_ySpacing = fontPixelSize * 1.25;
if (w < c_xSpacing || h < c_ySpacing || !p->viewport().contains(active))
return false;
if (_y)
{
GraphParameters<float> yParams(yRange, h / c_ySpacing, 1.f);
float dy = fabs(yRange.second - yRange.first);
if (dy > .001)
for (float f = yParams.from; f < yParams.to; f += yParams.incr)
{
int y = b - h * (f - yParams.from) / dy;
if (yParams.isMajor(f))
{
p->setPen(QColor(208, 208, 208));
p->drawLine(l - c_markLength, y, r, y);
if (l > p->viewport().left())
{
p->setPen(QColor(144, 144, 144));
p->drawText(QRect(0, y - c_ySpacing / 2, l - c_markLength - c_markSpacing, c_ySpacing), Qt::AlignRight|Qt::AlignVCenter, QString::fromStdString(yLabel(round(f * 100000) / 100000)));
}
}
else
{
p->setPen(QColor(236, 236, 236));
p->drawLine(l, y, r, y);
}
}
p->setPen(QColor(192,192,192));
p->drawLine(l - c_markSpacing, b, r, b);
}
if (_x)
{
GraphParameters<float> xParams(xRange, w / c_xSpacing, 1.f);
float dx = fabs(xRange.second - xRange.first);
for (float f = xParams.from; f < xParams.to; f += xParams.incr)
{
int x = l + w * (f - xParams.from) / dx;
if (xParams.isMajor(f))
{
p->setPen(QColor(208, 208, 208));
p->drawLine(x, t, x, b + c_markLength);
if (b < p->viewport().bottom())
{
p->setPen(QColor(144, 144, 144));
p->drawText(QRect(x - c_xSpacing / 2, b + c_markLength + c_markSpacing, c_xSpacing, p->viewport().height() - (b + c_markLength + c_markSpacing)), Qt::AlignHCenter|Qt::AlignTop, QString::fromStdString(xLabel(f)));
}
}
else
{
p->setPen(QColor(236, 236, 236));
p->drawLine(x, t, x, b);
}
}
}
p->setClipRect(active);
return true;
}
void Grapher::drawLineGraph(vector<float> const& _data, QColor _color, QBrush const& _fillToZero, float _width) const
{
int s = _data.size();
QPoint l;
for (int i = 0; i < s; ++i)
{
int zy = yP(0.f);
QPoint h(xTP(i), yTP(_data[i]));
if (i)
{
if (_fillToZero != Qt::NoBrush)
{
p->setPen(Qt::NoPen);
p->setBrush(_fillToZero);
p->drawPolygon(QPolygon(QVector<QPoint>() << QPoint(h.x(), zy) << h << l << QPoint(l.x(), zy)));
}
p->setPen(QPen(_color, _width));
p->drawLine(QLine(l, h));
}
l = h;
}
}
void Grapher::ruleY(float _x, QColor _color, float _width) const
{
p->setPen(QPen(_color, _width));
p->drawLine(xTP(_x), active.top(), xTP(_x), active.bottom());
}
void Grapher::drawLineGraph(std::function<float(float)> const& _f, QColor _color, QBrush const& _fillToZero, float _width) const
{
QPoint l;
for (int x = active.left(); x < active.right(); x += 2)
{
int zy = yP(0.f);
QPoint h(x, yTP(_f(xRU(x))));
if (x != active.left())
{
if (_fillToZero != Qt::NoBrush)
{
p->setPen(Qt::NoPen);
p->setBrush(_fillToZero);
p->drawPolygon(QPolygon(QVector<QPoint>() << QPoint(h.x(), zy) << h << l << QPoint(l.x(), zy)));
}
p->setPen(QPen(_color, _width));
p->drawLine(QLine(l, h));
}
l = h;
}
}
void Grapher::labelYOrderedPoints(map<float, float> const& _data, int _maxCount, float _minFactor) const
{
int ly = active.top() + 6;
int pc = 0;
if (_data.empty())
return;
float smallestAllowed = prev(_data.end())->first * _minFactor;
for (auto peaki = _data.rbegin(); peaki != _data.rend(); ++peaki)
if ((peaki->first > smallestAllowed || _minFactor == 0) && pc < _maxCount)
{
auto peak = *peaki;
int x = xTP(peak.second);
int y = yTP(peak.first);
p->setPen(QColor::fromHsvF(float(pc) / _maxCount, 1.f, 0.5f, 0.5f));
p->drawEllipse(QPoint(x, y), 4, 4);
p->drawLine(x, y - 4, x, ly + 6);
QString f = QString::fromStdString(pLabel(xT(peak.second), yT(peak.first)));
int fw = p->fontMetrics().width(f);
p->drawLine(x + 16 + fw + 2, ly + 6, x, ly + 6);
p->setPen(QColor::fromHsvF(0, 0.f, .35f));
p->fillRect(QRect(x+12, ly-6, fw + 8, 12), QBrush(QColor(255, 255, 255, 160)));
p->drawText(QRect(x+16, ly-6, 160, 12), Qt::AlignVCenter, f);
ly += 14;
++pc;
}
}

116
alethzero/Grapher.h

@ -0,0 +1,116 @@
/* BEGIN COPYRIGHT
*
* This file is part of Noted.
*
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
*
* Noted 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 2 of the License, or
* (at your option) any later version.
*
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <functional>
#include <QBrush>
#include <QRect>
class QPainter;
namespace lb
{
class Grapher
{
public:
Grapher(): p(0) {}
void init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float _f)> _xLabel, std::function<std::string(float _f)> _yLabel, std::function<std::string(float, float)> _pLabel, int _leftGutter = 30, int _bottomGutter = 16);
void init(QPainter* _p, std::pair<float, float> _xRange, std::pair<float, float> _yRange, std::function<std::string(float _f)> _xLabel, std::function<std::string(float _f)> _yLabel, std::function<std::string(float, float)> _pLabel, QRect _active)
{
p = _p;
active = _active;
xRange = _xRange;
yRange = _yRange;
dx = xRange.second - xRange.first;
dy = yRange.second - yRange.first;
xLabel = _xLabel;
yLabel = _yLabel;
pLabel = _pLabel;
}
void setDataTransform(float _xM, float _xC, float _yM, float _yC)
{
xM = _xM;
xC = _xC;
yM = _yM;
yC = _yC;
}
void setDataTransform(float _xM, float _xC)
{
xM = _xM;
xC = _xC;
yM = 1.f;
yC = 0.f;
}
void resetDataTransform() { xM = yM = 1.f; xC = yC = 0.f; }
bool drawAxes(bool _x = true, bool _y = true) const;
void drawLineGraph(std::vector<float> const& _data, QColor _color = QColor(128, 128, 128), QBrush const& _fillToZero = Qt::NoBrush, float _width = 0.f) const;
void drawLineGraph(std::function<float(float)> const& _f, QColor _color = QColor(128, 128, 128), QBrush const& _fillToZero = Qt::NoBrush, float _width = 0.f) const;
void ruleX(float _y, QColor _color = QColor(128, 128, 128), float _width = 0.f) const;
void ruleY(float _x, QColor _color = QColor(128, 128, 128), float _width = 0.f) const;
void labelYOrderedPoints(std::map<float, float> const& _translatedData, int _maxCount = 20, float _minFactor = .01f) const;
protected:
QPainter* p;
QRect active;
std::pair<float, float> xRange;
std::pair<float, float> yRange;
float xM;
float xC;
float yM;
float yC;
float dx;
float dy;
std::function<std::string(float _f)> xLabel;
std::function<std::string(float _f)> yLabel;
std::function<std::string(float _x, float _y)> pLabel;
float fontPixelSize;
// Translate from raw indexed data into x/y graph units. Only relevant for indexed data.
float xT(float _dataIndex) const { return _dataIndex * xM + xC; }
float yT(float _dataValue) const { return _dataValue * yM + yC; }
// Translate from x/y graph units to widget pixels.
int xP(float _xUnits) const { return active.left() + (_xUnits - xRange.first) / dx * active.width(); }
int yP(float _yUnits) const { return active.bottom() - (_yUnits - yRange.first) / dy * active.height(); }
QPoint P(float _x, float _y) const { return QPoint(xP(_x), yP(_y)); }
// Translate direcly from raw indexed data to widget pixels.
int xTP(float _dataIndex) const { return active.left() + (xT(_dataIndex) - xRange.first) / dx * active.width(); }
int yTP(float _dataValue) const { return active.bottom() - (yT(_dataValue) - yRange.first) / dy * active.height(); }
// Translate back from pixels into graph units.
float xU(int _xPixels) const { return float(_xPixels - active.left()) / active.width() * dx + xRange.first; }
// Translate back from graph units into raw data index.
float xR(float _xUnits) const { return (_xUnits - xC) / xM; }
// Translate directly from pixels into raw data index. xRU(xTP(X)) == X
float xRU(int _xPixels) const { return xR(xU(_xPixels)); }
};
}

39
alethzero/Main.ui

@ -981,6 +981,39 @@
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_10">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Mining</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_10">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="MiningView" name="miningView" native="true"/>
</item>
</layout>
</widget>
</widget>
<action name="quit">
<property name="text">
<string>&amp;Quit</string>
@ -1110,6 +1143,12 @@
<extends>QWidget</extends>
<header>QtWebKitWidgets/QWebView</header>
</customwidget>
<customwidget>
<class>MiningView</class>
<extends>QWidget</extends>
<header>MiningView.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>destination</tabstop>

79
alethzero/MainWin.cpp

@ -1,3 +1,24 @@
/*
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 MainWin.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include <fstream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
@ -21,6 +42,7 @@
#include <libethereum/ExtVM.h>
#include <libethereum/Client.h>
#include <libethereum/PeerServer.h>
#include "MiningView.h"
#include "BuildInfo.h"
#include "MainWin.h"
#include "ui_Main.h"
@ -76,36 +98,6 @@ static void initUnits(QComboBox* _b)
_b->addItem(QString::fromStdString(units()[n].second), n);
}
string htmlDump(bytes const& _b, unsigned _w = 8)
{
stringstream ret;
ret << "<pre style=\"font-family: Monospace, sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 128)
if ((char)_b[j] == '<')
ret << "&lt;";
else if ((char)_b[j] == '&')
ret << "&amp;";
else
ret << (char)_b[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
ret << "\n";
}
ret << "</pre>";
cdebug << ret.str();
return ret.str();
}
Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250");
using namespace boost::process;
@ -183,6 +175,9 @@ Main::Main(QWidget *parent) :
m_refreshNetwork = new QTimer(this);
connect(m_refreshNetwork, SIGNAL(timeout()), SLOT(refreshNetwork()));
m_refreshNetwork->start(1000);
m_refreshMining = new QTimer(this);
connect(m_refreshMining, SIGNAL(timeout()), SLOT(refreshMining()));
m_refreshMining->start(200);
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
@ -446,6 +441,22 @@ void Main::on_nameReg_textChanged()
m_nameReg = Address();
}
void Main::refreshMining()
{
eth::ClientGuard g(m_client.get());
list<eth::MineInfo> l = m_client->miningHistory();
eth::MineProgress p = m_client->miningProgress();
static uint lh = 0;
if (p.hashes < lh)
ui->miningView->resetStats();
lh = p.hashes;
ui->miningView->appendStats(l, p);
/* if (p.ms)
for (eth::MineInfo const& i: l)
cnote << i.hashes * 10 << "h/sec, need:" << i.requirement << " best:" << i.best << " best-so-far:" << p.best << " avg-speed:" << (p.hashes * 1000 / p.ms) << "h/sec";
*/
}
void Main::refreshNetwork()
{
auto ps = m_client->peers();
@ -605,7 +616,7 @@ void Main::on_transactionQueue_currentItemChanged()
else
{
if (tx.data.size())
s << htmlDump(tx.data, 16);
s << eth::memDump(tx.data, 16, true);
}
s << "<hr/>";
@ -762,7 +773,7 @@ void Main::on_blocks_currentItemChanged()
else
{
if (tx.data.size())
s << htmlDump(tx.data, 16);
s << eth::memDump(tx.data, 16);
}
}
@ -891,7 +902,7 @@ void Main::on_data_textChanged()
else
s = s.mid(1);
}
ui->code->setHtml(QString::fromStdString(htmlDump(m_data)));
ui->code->setHtml(QString::fromStdString(eth::memDump(m_data)));
if (m_client->postState().addressHasCode(fromString(ui->destination->currentText())))
{
ui->gas->setMinimum((qint64)state().callGas(m_data.size(), 1));
@ -1161,7 +1172,7 @@ void Main::updateDebugger()
for (auto i: ws.stack)
ds->insertItem(0, QString::fromStdString(toHex(((h256)i).asArray())));
ui->debugMemory->setHtml(QString::fromStdString(htmlDump(ws.memory, 16)));
ui->debugMemory->setHtml(QString::fromStdString(eth::memDump(ws.memory, 16)));
ui->debugCode->setCurrentRow(m_pcWarp[(unsigned)ws.curPC]);
ostringstream ss;
ss << hex << "PC: 0x" << ws.curPC << " | GAS: 0x" << ws.gas;

28
alethzero/MainWin.h

@ -1,5 +1,25 @@
#ifndef MAIN_H
#define MAIN_H
/*
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 MainWin.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <QtQml/QJSValue>
#include <QtNetwork/QNetworkAccessManager>
@ -84,6 +104,7 @@ private slots:
void refresh(bool _override = false);
void refreshNetwork();
void refreshMining();
signals:
void changed(); // TODO: manifest
@ -117,6 +138,7 @@ private:
QMutex m_guiLock;
QTimer* m_refresh;
QTimer* m_refreshNetwork;
QTimer* m_refreshMining;
QStringList m_servers;
QList<eth::KeyPair> m_myKeys;
bool m_keysChanged = false;
@ -135,5 +157,3 @@ private:
QEthereum* m_ethereum;
};
#endif // MAIN_H

107
alethzero/MiningView.cpp

@ -0,0 +1,107 @@
/*
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 MiningView.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "MiningView.h"
#include <QtWidgets>
#include <QtCore>
#include <libethereum/Client.h>
#include "Grapher.h"
using namespace std;
using namespace eth;
using namespace lb;
string id(float _y) { return toString(_y); }
string ms(float _x){ return toString(round(_x * 1000)) + (!_x ? "ms" : ""); }
string msL(float _x, float _y) { return toString(round(_x * 1000)) + "ms (" + toString(round(_y * 100)) + "%)"; }
MiningView::MiningView(QWidget* _p): QWidget(_p)
{
}
void MiningView::appendStats(list<MineInfo> const& _i, MineProgress const& _p)
{
if (_i.empty())
return;
unsigned o = m_values.size();
for (MineInfo const& i: _i)
{
m_values.push_back(i.best);
m_lastBest = min(m_lastBest, i.best);
m_bests.push_back(m_lastBest);
m_reqs.push_back(i.requirement);
if (i.completed)
{
m_completes.push_back(o);
m_resets.push_back(o);
m_haveReset = false;
m_lastBest = 1e99;
}
++o;
}
if (m_haveReset)
{
m_resets.push_back(o - 1);
m_lastBest = 1e99;
m_haveReset = false;
}
o = max<int>(0, (int)m_values.size() - (int)m_duration);
trimFront(m_values, o);
trimFront(m_bests, o);
trimFront(m_reqs, o);
for (auto& i: m_resets)
i -= o;
remove_if(m_resets.begin(), m_resets.end(), [](int i){return i < 0;});
for (auto& i: m_completes)
i -= o;
remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;});
m_progress = _p;
update();
}
void MiningView::resetStats()
{
m_haveReset = true;
}
void MiningView::paintEvent(QPaintEvent*)
{
Grapher g;
QPainter p(this);
g.init(&p, make_pair(0.f, max<float>(m_duration * 0.1f, m_values.size() * 0.1f)), make_pair(m_progress.requirement, 256.f), ms, id, msL);
g.drawAxes();
g.setDataTransform(0.1, 0);
g.drawLineGraph(m_values, QColor(192, 192, 192));
g.drawLineGraph(m_bests, QColor(128, 128, 128));
g.drawLineGraph(m_reqs, QColor(128, 64, 64));
for (auto r: m_resets)
g.ruleY(r - 1, QColor(128, 128, 128));
for (auto r: m_completes)
g.ruleY(r, QColor(192, 64, 64));
}

56
alethzero/MiningView.h

@ -0,0 +1,56 @@
/*
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 MiningView.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <list>
#include <QtWidgets/QWidget>
#include <libethereum/Client.h>
namespace eth
{
class MineInfo;
}
class MiningView: public QWidget
{
Q_OBJECT
public:
MiningView(QWidget* _p = nullptr);
void appendStats(std::list<eth::MineInfo> const& _l, eth::MineProgress const& _p);
void resetStats();
protected:
virtual void paintEvent(QPaintEvent*);
private:
eth::MineProgress m_progress;
unsigned m_duration = 300;
std::vector<float> m_values;
std::vector<float> m_bests;
std::vector<float> m_reqs;
std::vector<int> m_resets;
std::vector<int> m_completes;
double m_lastBest = 1e31;
bool m_haveReset = false;
};

10
libethcore/Dagger.cpp

@ -36,22 +36,22 @@ namespace eth
MineInfo Dagger::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout, bool const& _continue)
{
MineInfo ret{0, 0, false};
MineInfo ret{0.f, 1e99, 0, false};
static std::mt19937_64 s_eng((time(0)));
u256 s = std::uniform_int_distribution<uint>(0, ~(uint)0)(s_eng);
u256 s = h256::random(s_eng);
bigint d = (bigint(1) << 256) / _difficulty;
ret.requirement = toLog2((u256)d);
ret.requirement = log2((double)d);
// 2^ 0 32 64 128 256
// [--------*-------------------------]
//
// evaluate until we run out of time
for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; s++)
for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; s++, ret.hashes++)
{
o_solution = (h256)s;
auto e = (bigint)(u256)eval(_root, o_solution);
ret.best = max(ret.best, toLog2((u256)e));
ret.best = min<double>(ret.best, log2((double)e));
if (e <= d)
{
ret.completed = true;

5
libethcore/Dagger.h

@ -37,8 +37,9 @@ inline uint toLog2(u256 _d)
struct MineInfo
{
uint requirement;
uint best;
double requirement;
double best;
uint hashes;
bool completed;
};

13
libethereum/Client.cpp

@ -226,6 +226,9 @@ void Client::work()
{
if (m_restartMining)
{
m_mineProgress.best = (uint)-1;
m_mineProgress.hashes = 0;
m_mineProgress.ms = 0;
lock_guard<recursive_mutex> l(m_lock);
if (m_paranoia)
{
@ -251,16 +254,22 @@ void Client::work()
// Mine for a while.
MineInfo mineInfo = m_postMine.mine(100);
m_mineProgress.best = max(m_mineProgress.best, mineInfo.best);
m_mineProgress.best = min(m_mineProgress.best, mineInfo.best);
m_mineProgress.current = mineInfo.best;
m_mineProgress.requirement = mineInfo.requirement;
m_mineProgress.ms += 100;
m_mineProgress.hashes += mineInfo.hashes;
{
lock_guard<recursive_mutex> l(m_lock);
m_mineHistory.push_back(mineInfo);
}
if (mineInfo.completed)
{
// Import block.
lock_guard<recursive_mutex> l(m_lock);
m_bc.attemptImport(m_postMine.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_changed = true;
}
}

14
libethereum/Client.h

@ -23,6 +23,7 @@
#include <thread>
#include <mutex>
#include <list>
#include <atomic>
#include <libethsupport/Common.h>
#include <libethcore/Dagger.h>
@ -36,9 +37,11 @@ namespace eth
struct MineProgress
{
uint requirement;
uint best;
uint current;
double requirement;
double best;
double current;
uint hashes;
uint ms;
};
class Client;
@ -165,8 +168,12 @@ public:
void stopMining();
/// Are we mining now?
bool isMining() { return m_doMine; }
/// Register a callback for information concerning mining.
/// This callback will be in an arbitrary thread, blocking progress. JUST COPY THE DATA AND GET OUT.
/// Check the progress of the mining.
MineProgress miningProgress() const { return m_mineProgress; }
/// Get and clear the mining history.
std::list<MineInfo> miningHistory() { auto ret = m_mineHistory; m_mineHistory.clear(); return ret; }
private:
void work();
@ -187,6 +194,7 @@ private:
bool m_paranoia = false;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;
std::list<MineInfo> m_mineHistory;
mutable bool m_restartMining = false;
mutable bool m_changed;

31
libethereum/Executive.cpp

@ -26,37 +26,6 @@
using namespace std;
using namespace eth;
string eth::memDump(bytes const& _b, unsigned _w, bool _html)
{
stringstream ret;
if (_html)
ret << "<pre style=\"font-family: Monospace, sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 128)
if ((char)_b[j] == '<' && _html)
ret << "&lt;";
else if ((char)_b[j] == '&' && _html)
ret << "&amp;";
else
ret << (char)_b[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
ret << "\n";
}
if (_html)
ret << "</pre>";
return ret.str();
}
Executive::~Executive()
{
// TODO: Make safe.

2
libethereum/Executive.h

@ -34,8 +34,6 @@ class State;
struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; };
std::string memDump(bytes const& _b, unsigned _w = 8, bool _html = false);
class Executive
{
public:

31
libethsupport/CommonIO.cpp

@ -26,6 +26,37 @@
using namespace std;
using namespace eth;
string eth::memDump(bytes const& _b, unsigned _w, bool _html)
{
stringstream ret;
if (_html)
ret << "<pre style=\"font-family: Monospace, sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 128)
if ((char)_b[j] == '<' && _html)
ret << "&lt;";
else if ((char)_b[j] == '&' && _html)
ret << "&amp;";
else
ret << (char)_b[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
ret << "\n";
}
if (_html)
ret << "</pre>";
return ret.str();
}
bytes eth::contents(std::string const& _file)
{
std::ifstream is(_file, std::ifstream::binary);

3
libethsupport/CommonIO.h

@ -46,6 +46,9 @@ bytes contents(std::string const& _file);
/// Write the given binary data into the given file, replacing the file if it pre-exists.
void writeFile(std::string const& _file, bytes const& _data);
/// Nicely renders the given bytes to a string, optionally as HTML.
std::string memDump(bytes const& _b, unsigned _w = 8, bool _html = false);
/// Converts arbitrary value to string representation using std::stringstream.
template <class _T>
std::string toString(_T const& _t)

11
libethsupport/FixedHash.h

@ -24,6 +24,7 @@
#pragma once
#include <array>
#include <random>
#include <algorithm>
#include "CommonData.h"
@ -113,6 +114,16 @@ public:
/// @returns a constant reference to the object's data as an STL array.
std::array<byte, N> const& asArray() const { return m_data; }
/// @returns a randomly-valued hash
template <class Engine>
static FixedHash random(Engine& _eng)
{
FixedHash ret;
for (auto& i: ret.m_data)
i = std::uniform_int_distribution<byte>(0, 255)(_eng);
return ret;
}
/// A generic std::hash compatible function object.
struct hash
{

Loading…
Cancel
Save