diff --git a/CMakeLists.txt b/CMakeLists.txt index d69e1e958..9ed54656f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,7 +369,7 @@ if (NOT LANGUAGES) add_subdirectory(third) if(QTQML) #add_subdirectory(iethxi) - add_subdirectory(walleth) + #add_subdirectory(walleth) // resurect once we want to submit ourselves to QML. endif() endif() endif() diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 3eac0a0b6..c5d1aa0be 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -52,7 +52,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore) if (APPLE) # First have qt5 install plugins and frameworks diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp new file mode 100644 index 000000000..657727a6a --- /dev/null +++ b/alethzero/DownloadView.cpp @@ -0,0 +1,83 @@ +/* + 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 . +*/ +/** @file DownloadView.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "DownloadView.h" + +#include +#include +#include +#include "Grapher.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; + +DownloadView::DownloadView(QWidget* _p): QWidget(_p) +{ +} + +void DownloadView::paintEvent(QPaintEvent*) +{ + QPainter p(this); + + p.fillRect(rect(), Qt::white); + if (!m_man || m_man->chain().empty() || !m_man->subCount()) + return; + + double ratio = (double)rect().width() / rect().height(); + if (ratio < 1) + ratio = 1 / ratio; + double n = min(rect().width(), rect().height()) / ceil(sqrt(m_man->chain().size() / ratio)); + +// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); + QSizeF area(n, n); + QPointF pos(0, 0); + + auto const& bg = m_man->blocksGot(); + + for (unsigned i = bg.all().first, ei = bg.all().second; i < ei; ++i) + { + int s = -2; + if (bg.contains(i)) + s = -1; + else + { + unsigned h = 0; + m_man->foreachSub([&](DownloadSub const& sub) + { + if (sub.asked().contains(i)) + s = h; + h++; + }); + } + unsigned dh = 360 / m_man->subCount(); + if (s == -2) + p.fillRect(QRectF(QPointF(pos) + QPointF(3 * area.width() / 8, 3 * area.height() / 8), area / 4), Qt::black); + else if (s == -1) + p.fillRect(QRectF(QPointF(pos) + QPointF(1 * area.width() / 8, 1 * area.height() / 8), area * 3 / 4), Qt::black); + else + p.fillRect(QRectF(QPointF(pos) + QPointF(1 * area.width() / 8, 1 * area.height() / 8), area * 3 / 4), QColor::fromHsv(s * dh, 64, 128)); + + pos.setX(pos.x() + n); + if (pos.x() >= rect().width() - n) + pos = QPoint(0, pos.y() + n); + } +} diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h new file mode 100644 index 000000000..22a11651c --- /dev/null +++ b/alethzero/DownloadView.h @@ -0,0 +1,53 @@ +/* + 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 . +*/ +/** @file DownloadView.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#ifdef Q_MOC_RUN +#define BOOST_MPL_IF_HPP_INCLUDED +#endif + +#include +#include +#ifndef Q_MOC_RUN +#include +#endif + +namespace dev { namespace eth { +struct MineInfo; +class DownloadMan; +}} + +class DownloadView: public QWidget +{ + Q_OBJECT + +public: + DownloadView(QWidget* _p = nullptr); + + void setDownloadMan(dev::eth::DownloadMan const* _man) { m_man = _man; } + +protected: + virtual void paintEvent(QPaintEvent*); + +private: + dev::eth::DownloadMan const* m_man = nullptr; +}; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index aa8a43f1c..dbc4bb144 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -132,6 +132,7 @@ + @@ -1432,6 +1433,39 @@ font-size: 14pt + + + QDockWidget::DockWidgetFeatureMask + + + Blockchain Download + + + 2 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + &Quit @@ -1698,6 +1732,14 @@ font-size: 14pt Reserved Debug 1 + + + true + + + Enable Local Addresses + + @@ -1712,6 +1754,12 @@ font-size: 14pt
MiningView.h
1 + + DownloadView + QWidget +
DownloadView.h
+ 1 +
destination diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e9cdf90bc..b4bbb8ca7 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,50 +39,16 @@ #include #include #include +#include +#include "DownloadView.h" #include "MiningView.h" #include "BuildInfo.h" #include "MainWin.h" #include "ui_Main.h" using namespace std; - -// types -using dev::bytes; -using dev::bytesConstRef; -using dev::h160; -using dev::h256; -using dev::u160; -using dev::u256; -using dev::Address; -using dev::eth::BlockInfo; -using dev::eth::Client; -using dev::eth::Instruction; -using dev::KeyPair; -using dev::eth::NodeMode; -using dev::eth::BlockChain; -using dev::p2p::PeerInfo; -using dev::RLP; -using dev::Secret; -using dev::eth::Transaction; -using dev::eth::Executive; - -// functions -using dev::toHex; -using dev::fromHex; -using dev::left160; -using dev::right160; -using dev::simpleDebugOut; -using dev::toLog2; -using dev::toString; -using dev::operator<<; -using dev::eth::units; -using dev::eth::sha3; -using dev::eth::compileLLL; -using dev::eth::disassemble; -using dev::eth::formatBalance; - -// vars -using dev::g_logPost; -using dev::g_logVerbosity; +using namespace dev; +using namespace dev::p2p; +using namespace dev::eth; static void initUnits(QComboBox* _b) { @@ -114,7 +81,6 @@ static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr) return QString(); } - Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); Main::Main(QWidget *parent) : @@ -133,26 +99,10 @@ Main::Main(QWidget *parent) : // ui->log->addItem(QString::fromStdString(s)); }; -#if 0&Ð_DEBUG - m_servers.append("192.168.0.10:30301"); -#else - int pocnumber = QString(dev::Version).section('.', 1, 1).toInt(); - if (pocnumber == 5) - m_servers.push_back("54.72.69.180:30303"); - else if (pocnumber == 6) - m_servers.push_back("54.76.56.74:30303"); - else - { - connect(&m_webCtrl, &QNetworkAccessManager::finished, [&](QNetworkReply* _r) - { - m_servers = QString::fromUtf8(_r->readAll()).split("\n", QString::SkipEmptyParts); - }); - QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc" + QString::number(pocnumber) + ".txt")); - r.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1712.0 Safari/537.36"); - m_webCtrl.get(r); - srand(time(0)); - } +#if ETH_DEBUG + m_servers.append("localhost:30300"); #endif + m_servers.append(QString::fromStdString(Host::pocHost() + ":30303")); cerr << "State root: " << BlockChain::genesis().stateRoot << endl; cerr << "Block Hash: " << sha3(BlockChain::createGenesisBlock()) << endl; @@ -177,12 +127,12 @@ Main::Main(QWidget *parent) : connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); - m_client.reset(new Client("AlethZero")); + m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); connect(ui->webView, &QWebView::loadStarted, [this]() { // NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it. - m_ethereum = new QEthereum(this, client(), owned()); + m_ethereum = new QEthereum(this, ethereum(), owned()); QWebFrame* f = ui->webView->page()->mainFrame(); f->disconnect(SIGNAL(javaScriptWindowObjectCleared())); @@ -226,6 +176,11 @@ Main::~Main() writeSettings(); } +dev::p2p::NetworkPreferences Main::netPrefs() const +{ + return NetworkPreferences(ui->port->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), ui->localNetworking->isChecked()); +} + void Main::onKeysChanged() { installBalancesWatch(); @@ -233,14 +188,14 @@ void Main::onKeysChanged() unsigned Main::installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f) { - auto ret = client()->installWatch(_tf); + auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; return ret; } unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) { - auto ret = client()->installWatch(_tf); + auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; return ret; } @@ -255,14 +210,14 @@ void Main::installWatches() void Main::installNameRegWatch() { - client()->uninstallWatch(m_nameRegFilter); - m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)client()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); + ethereum()->uninstallWatch(m_nameRegFilter); + m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { - client()->uninstallWatch(m_currenciesFilter); - m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)client()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); + ethereum()->uninstallWatch(m_currenciesFilter); + m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } void Main::installBalancesWatch() @@ -270,9 +225,9 @@ void Main::installBalancesWatch() dev::eth::MessageFilter tf; vector
altCoins; - Address coinsAddr = right160(client()->stateAt(c_config, 1)); - for (unsigned i = 0; i < client()->stateAt(coinsAddr, 0); ++i) - altCoins.push_back(right160(client()->stateAt(coinsAddr, i + 1))); + Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); + for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) + altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); for (auto i: m_myKeys) { tf.altered(i.address()); @@ -280,7 +235,7 @@ void Main::installBalancesWatch() tf.altered(c, (u160)i.address()); } - client()->uninstallWatch(m_balancesFilter); + ethereum()->uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); }); } @@ -328,7 +283,7 @@ void Main::onNewPending() void Main::on_forceMining_triggered() { - client()->setForceMining(ui->forceMining->isChecked()); + ethereum()->setForceMining(ui->forceMining->isChecked()); } void Main::on_enableOptimizer_triggered() @@ -422,11 +377,11 @@ QString Main::pretty(dev::Address _a) const { h256 n; - if (h160 nameReg = (u160)client()->stateAt(c_config, 0)) - n = client()->stateAt(nameReg, (u160)(_a)); + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) + n = ethereum()->stateAt(nameReg, (u160)(_a)); if (!n) - n = client()->stateAt(m_nameReg, (u160)(_a)); + n = ethereum()->stateAt(m_nameReg, (u160)(_a)); return fromRaw(n); } @@ -452,11 +407,11 @@ Address Main::fromString(QString const& _a) const memset(n.data() + sn.size(), 0, 32 - sn.size()); if (_a.size()) { - if (h160 nameReg = (u160)client()->stateAt(c_config, 0)) - if (h256 a = client()->stateAt(nameReg, n)) + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) + if (h256 a = ethereum()->stateAt(nameReg, n)) return right160(a); - if (h256 a = client()->stateAt(m_nameReg, n)) + if (h256 a = ethereum()->stateAt(m_nameReg, n)) return right160(a); } if (_a.size() == 40) @@ -484,11 +439,11 @@ QString Main::lookup(QString const& _a) const */ h256 ret; - if (h160 dnsReg = (u160)client()->stateAt(c_config, 4, 0)) - ret = client()->stateAt(dnsReg, n); + if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, 0)) + ret = ethereum()->stateAt(dnsReg, n); /* if (!ret) - if (h160 nameReg = (u160)m_client->stateAt(c_config, 0, 0)) - ret = m_client->stateAt(nameReg, n2); + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, 0)) + ret = ethereum()->stateAt(nameReg, n2); */ if (ret && !((u256)ret >> 32)) return QString("%1.%2.%3.%4").arg((int)ret[28]).arg((int)ret[29]).arg((int)ret[30]).arg((int)ret[31]); @@ -506,7 +461,7 @@ void Main::on_about_triggered() void Main::on_paranoia_triggered() { - client()->setParanoia(ui->paranoia->isChecked()); + ethereum()->setParanoia(ui->paranoia->isChecked()); } void Main::writeSettings() @@ -525,6 +480,7 @@ void Main::writeSettings() s.setValue("upnp", ui->upnp->isChecked()); s.setValue("forceAddress", ui->forceAddress->text()); s.setValue("usePast", ui->usePast->isChecked()); + s.setValue("localNetworking", ui->localNetworking->isChecked()); s.setValue("forceMining", ui->forceMining->isChecked()); s.setValue("paranoia", ui->paranoia->isChecked()); s.setValue("showAll", ui->showAll->isChecked()); @@ -537,7 +493,7 @@ void Main::writeSettings() s.setValue("privateChain", m_privateChain); s.setValue("verbosity", ui->verbosity->value()); - bytes d = client()->savePeers(); + bytes d = m_webThree->savePeers(); if (d.size()) m_peers = QByteArray((char*)d.data(), (int)d.size()); s.setValue("peers", m_peers); @@ -569,11 +525,12 @@ void Main::readSettings(bool _skipGeometry) m_myKeys.append(KeyPair(k)); } } - client()->setAddress(m_myKeys.back().address()); + ethereum()->setAddress(m_myKeys.back().address()); m_peers = s.value("peers").toByteArray(); ui->upnp->setChecked(s.value("upnp", true).toBool()); ui->forceAddress->setText(s.value("forceAddress", "").toString()); ui->usePast->setChecked(s.value("usePast", true).toBool()); + ui->localNetworking->setChecked(s.value("localNetworking", true).toBool()); ui->forceMining->setChecked(s.value("forceMining", false).toBool()); on_forceMining_triggered(); ui->paranoia->setChecked(s.value("paranoia", false).toBool()); @@ -665,17 +622,17 @@ void Main::on_nameReg_textChanged() void Main::on_preview_triggered() { - client()->setDefault(ui->preview->isChecked() ? 0 : -1); + ethereum()->setDefault(ui->preview->isChecked() ? 0 : -1); refreshAll(); } void Main::refreshMining() { - dev::eth::MineProgress p = client()->miningProgress(); - ui->mineStatus->setText(client()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); + dev::eth::MineProgress 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"); if (!ui->miningView->isVisible()) return; - list l = client()->miningHistory(); + list l = ethereum()->miningHistory(); static unsigned lh = 0; if (p.hashes < lh) ui->miningView->resetStats(); @@ -694,12 +651,12 @@ void Main::refreshBalances() ui->ourAccounts->clear(); u256 totalBalance = 0; map> altCoins; - Address coinsAddr = right160(client()->stateAt(c_config, 1)); - for (unsigned i = 0; i < client()->stateAt(coinsAddr, 0); ++i) + Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); + for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) { - auto n = client()->stateAt(coinsAddr, i + 1); - auto addr = right160(client()->stateAt(coinsAddr, n)); - auto denom = client()->stateAt(coinsAddr, sha3(h256(n).asBytes())); + auto n = ethereum()->stateAt(coinsAddr, i + 1); + auto addr = right160(ethereum()->stateAt(coinsAddr, n)); + auto denom = ethereum()->stateAt(coinsAddr, sha3(h256(n).asBytes())); if (denom == 0) denom = 1; // cdebug << n << addr << denom << sha3(h256(n).asBytes()); @@ -707,13 +664,13 @@ void Main::refreshBalances() } for (auto i: m_myKeys) { - u256 b = client()->balanceAt(i.address()); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)client()->countAt(i.address())), ui->ourAccounts)) + u256 b = ethereum()->balanceAt(i.address()); + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); totalBalance += b; for (auto& c: altCoins) - get<1>(c.second) += (u256)client()->stateAt(c.first, (u160)i.address()); + get<1>(c.second) += (u256)ethereum()->stateAt(c.first, (u160)i.address()); } QString b; @@ -729,12 +686,12 @@ void Main::refreshBalances() void Main::refreshNetwork() { - auto ps = client()->peers(); + auto ps = web3()->peers(); ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)"); ui->peers->clear(); for (PeerInfo const& i: ps) - ui->peers->addItem(QString("%3 ms - %1:%2 - %4").arg(i.host.c_str()).arg(i.port).arg(chrono::duration_cast(i.lastPing).count()).arg(i.clientVersion.c_str())); + ui->peers->addItem(QString("%3 ms - %1:%2 - %4 %5").arg(i.host.c_str()).arg(i.port).arg(chrono::duration_cast(i.lastPing).count()).arg(i.clientVersion.c_str()).arg(QString::fromStdString(toString(i.caps)))); } void Main::refreshAll() @@ -751,7 +708,7 @@ void Main::refreshPending() { cwatch << "refreshPending()"; ui->transactionQueue->clear(); - for (Transaction const& t: client()->pending()) + for (Transaction const& t: ethereum()->pending()) { QString s = t.receiveAddress ? QString("%2 %5> %3: %1 [%4]") @@ -759,7 +716,7 @@ void Main::refreshPending() .arg(render(t.safeSender())) .arg(render(t.receiveAddress)) .arg((unsigned)t.nonce) - .arg(client()->codeAt(t.receiveAddress).size() ? '*' : '-') : + .arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') : QString("%2 +> %3: %1 [%4]") .arg(formatBalance(t.value).c_str()) .arg(render(t.safeSender())) @@ -775,16 +732,16 @@ void Main::refreshAccounts() ui->accounts->clear(); ui->contracts->clear(); for (auto n = 0; n < 2; ++n) - for (auto i: client()->addresses()) + for (auto i: ethereum()->addresses()) { auto r = render(i); if (r.contains('(') == !n) { if (n == 0 || ui->showAllAccounts->isChecked()) - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(client()->balanceAt(i)).c_str()).arg(r).arg((unsigned)client()->countAt(i)), ui->accounts)) + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->accounts)) ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); - if (client()->codeAt(i).size()) - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(client()->balanceAt(i)).c_str()).arg(r).arg((unsigned)client()->countAt(i)), ui->contracts)) + if (ethereum()->codeAt(i).size()) + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->contracts)) ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); } } @@ -794,7 +751,7 @@ void Main::refreshDestination() { cwatch << "refreshDestination()"; QString s; - for (auto i: client()->addresses()) + for (auto i: ethereum()->addresses()) if ((s = pretty(i)).size()) // A namereg address if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) @@ -807,8 +764,8 @@ void Main::refreshDestination() void Main::refreshBlockCount() { cwatch << "refreshBlockCount()"; - auto d = client()->blockChain().details(); - auto diff = BlockInfo(client()->blockChain().block()).difficulty; + auto d = ethereum()->blockChain().details(); + auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty; ui->blockCount->setText(QString("%6 #%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); } @@ -839,7 +796,7 @@ static bool transactionMatch(string const& _f, Transaction const& _t) void Main::on_turboMining_triggered() { - client()->setTurboMining(ui->turboMining->isChecked()); + ethereum()->setTurboMining(ui->turboMining->isChecked()); } void Main::refreshBlockChain() @@ -850,7 +807,7 @@ void Main::refreshBlockChain() ui->blocks->clear(); string filter = ui->blockChainFilter->text().toLower().toStdString(); - auto const& bc = client()->blockChain(); + auto const& bc = ethereum()->blockChain(); unsigned i = (ui->showAll->isChecked() || !filter.empty()) ? (unsigned)-1 : 10; for (auto h = bc.currentHash(); h != bc.genesisHash() && bc.details(h) && i; h = bc.details(h).parent, --i) { @@ -877,7 +834,7 @@ void Main::refreshBlockChain() .arg(render(t.safeSender())) .arg(render(t.receiveAddress)) .arg((unsigned)t.nonce) - .arg(client()->codeAt(t.receiveAddress).size() ? '*' : '-') : + .arg(ethereum()->codeAt(t.receiveAddress).size() ? '*' : '-') : QString(" %2 +> %3: %1 [%4]") .arg(formatBalance(t.value).c_str()) .arg(render(t.safeSender())) @@ -926,6 +883,9 @@ void Main::timerEvent(QTimerEvent*) if (interval / 100 % 2 == 0) refreshMining(); + if (interval / 100 % 2 == 0 && m_webThree->ethereum()->isSyncing()) + ui->downloadView->update(); + if (m_logChanged) { m_logLock.lock(); @@ -948,7 +908,7 @@ void Main::timerEvent(QTimerEvent*) m_ethereum->poll(); for (auto const& i: m_handlers) - if (client()->checkWatch(i.first)) + if (ethereum()->checkWatch(i.first)) i.second(); } @@ -1019,9 +979,9 @@ void Main::on_transactionQueue_currentItemChanged() stringstream s; int i = ui->transactionQueue->currentRow(); - if (i >= 0 && i < (int)client()->pending().size()) + if (i >= 0 && i < (int)ethereum()->pending().size()) { - Transaction tx(client()->pending()[i]); + Transaction tx(ethereum()->pending()[i]); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce)); s << "

" << th << "

"; @@ -1049,7 +1009,7 @@ void Main::on_transactionQueue_currentItemChanged() // s << "Pre: " << fs.rootHash() << "
"; // s << "Post: " << ts.rootHash() << ""; - s << renderDiff(client()->diff(i, 0)); + s << renderDiff(ethereum()->diff(i, 0)); } ui->pendingInfo->setHtml(QString::fromStdString(s.str())); @@ -1076,7 +1036,7 @@ void Main::on_inject_triggered() { QString s = QInputDialog::getText(this, "Inject Transaction", "Enter transaction dump in hex"); bytes b = fromHex(s.toStdString()); - client()->inject(&b); + ethereum()->inject(&b); } void Main::on_blocks_currentItemChanged() @@ -1090,8 +1050,8 @@ void Main::on_blocks_currentItemChanged() auto hba = item->data(Qt::UserRole).toByteArray(); assert(hba.size() == 32); auto h = h256((byte const*)hba.data(), h256::ConstructFromPointer); - auto details = client()->blockChain().details(h); - auto blockData = client()->blockChain().block(h); + auto details = ethereum()->blockChain().details(h); + auto blockData = ethereum()->blockChain().block(h); auto block = RLP(blockData); BlockInfo info(blockData); @@ -1115,7 +1075,7 @@ void Main::on_blocks_currentItemChanged() s << "
Bloom: " << details.bloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; - s << "
Pre: " << BlockInfo(client()->blockChain().block(info.parentHash)).stateRoot << ""; + s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << ""; for (auto const& i: block[1]) s << "
" << sha3(i[0].data()).abridged() << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]"; s << "
Post: " << info.stateRoot << ""; @@ -1151,7 +1111,7 @@ void Main::on_blocks_currentItemChanged() if (tx.data.size()) s << dev::memDump(tx.data, 16, true); } - s << renderDiff(client()->diff(txi, h)); + s << renderDiff(ethereum()->diff(txi, h)); ui->debugCurrent->setEnabled(true); ui->debugDumpState->setEnabled(true); ui->debugDumpStatePre->setEnabled(true); @@ -1173,7 +1133,7 @@ void Main::on_debugCurrent_triggered() if (!item->data(Qt::UserRole + 1).isNull()) { unsigned txi = item->data(Qt::UserRole + 1).toInt(); - m_executiveState = client()->state(txi + 1, h); + m_executiveState = ethereum()->state(txi + 1, h); m_currentExecution = unique_ptr(new Executive(m_executiveState)); Transaction t = m_executiveState.pending()[txi]; m_executiveState = m_executiveState.fromPending(txi); @@ -1199,7 +1159,7 @@ void Main::on_debugDumpState_triggered(int _add) if (f.is_open()) { unsigned txi = item->data(Qt::UserRole + 1).toInt(); - f << client()->state(txi + _add, h) << endl; + f << ethereum()->state(txi + _add, h) << endl; } } } @@ -1265,10 +1225,10 @@ void Main::on_contracts_currentItemChanged() stringstream s; try { - auto storage = client()->storageAt(address); + auto storage = ethereum()->storageAt(address); for (auto const& i: storage) s << "@" << showbase << hex << prettyU256(i.first).toStdString() << "    " << showbase << hex << prettyU256(i.second).toStdString() << "
"; - s << "

Body Code

" << disassemble(client()->codeAt(address)); + s << "

Body Code

" << disassemble(ethereum()->codeAt(address)); ui->contractInfo->appendHtml(QString::fromStdString(s.str())); } catch (dev::eth::InvalidTrie) @@ -1281,7 +1241,7 @@ void Main::on_contracts_currentItemChanged() void Main::on_idealPeers_valueChanged() { - client()->setIdealPeerCount(ui->idealPeers->value()); + m_webThree->setIdealPeerCount(ui->idealPeers->value()); } void Main::on_ourAccounts_doubleClicked() @@ -1427,7 +1387,7 @@ void Main::on_data_textChanged() s = s.mid(1); } ui->code->setHtml(QString::fromStdString(dev::memDump(m_data, 8, true))); - if (client()->codeAt(fromString(ui->destination->currentText()), 0).size()) + if (ethereum()->codeAt(fromString(ui->destination->currentText()), 0).size()) { ui->gas->setMinimum((qint64)Client::txGas(m_data.size(), 1)); if (!ui->gas->isEnabled()) @@ -1450,9 +1410,9 @@ void Main::on_killBlockchain_triggered() writeSettings(); ui->mine->setChecked(false); ui->net->setChecked(false); - m_client.reset(); - m_client.reset(new Client("AlethZero", Address(), string(), true)); - m_ethereum->setClient(client()); + web3()->stopNetwork(); + ethereum()->killChain(); + m_ethereum->setClient(ethereum()); readSettings(true); installWatches(); refreshAll(); @@ -1495,7 +1455,7 @@ void Main::updateFee() bool ok = false; for (auto i: m_myKeys) - if (client()->balanceAt(i.address()) >= totalReq) + if (ethereum()->balanceAt(i.address()) >= totalReq) { ok = true; break; @@ -1514,15 +1474,24 @@ void Main::on_net_triggered() if (ui->clientName->text().size()) n += "/" + ui->clientName->text().toStdString(); n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); - client()->setClientVersion(n); + web3()->setClientVersion(n); if (ui->net->isChecked()) { - client()->startNetwork(ui->port->value(), string(), 0, NodeMode::Full, ui->idealPeers->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0); + // TODO: alter network stuff? + //ui->port->value(), string(), 0, NodeMode::Full, ui->idealPeers->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0 + web3()->setIdealPeerCount(ui->idealPeers->value()); + web3()->setNetworkPreferences(netPrefs()); + ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0); + web3()->startNetwork(); + ui->downloadView->setDownloadMan(ethereum()->downloadMan()); if (m_peers.size() && ui->usePast->isChecked()) - client()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); + web3()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); } else - client()->stopNetwork(); + { + ui->downloadView->setDownloadMan(nullptr); + web3()->stopNetwork(); + } } void Main::on_connect_triggered() @@ -1538,7 +1507,7 @@ void Main::on_connect_triggered() { string host = s.section(":", 0, 0).toStdString(); unsigned short port = s.section(":", 1).toInt(); - client()->connect(host, port); + web3()->connect(host, port); } } @@ -1552,25 +1521,25 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { - client()->setAddress(m_myKeys.last().address()); - client()->startMining(); + ethereum()->setAddress(m_myKeys.last().address()); + ethereum()->startMining(); } else - client()->stopMining(); + ethereum()->stopMining(); } void Main::on_send_clicked() { u256 totalReq = value() + fee(); for (auto i: m_myKeys) - if (client()->balanceAt(i.address(), 0) >= totalReq) + if (ethereum()->balanceAt(i.address(), 0) >= totalReq) { debugFinished(); Secret s = i.secret(); if (isCreation()) - client()->transact(s, value(), m_data, ui->gas->value(), gasPrice()); + ethereum()->transact(s, value(), m_data, ui->gas->value(), gasPrice()); else - client()->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); + ethereum()->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); return; } statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount."); @@ -1583,10 +1552,10 @@ void Main::on_debug_clicked() { u256 totalReq = value() + fee(); for (auto i: m_myKeys) - if (client()->balanceAt(i.address()) >= totalReq) + if (ethereum()->balanceAt(i.address()) >= totalReq) { Secret s = i.secret(); - m_executiveState = client()->postState(); + m_executiveState = ethereum()->postState(); m_currentExecution = unique_ptr(new Executive(m_executiveState)); Transaction t; t.nonce = m_executiveState.transactionsFrom(dev::toAddress(s)); @@ -1937,4 +1906,7 @@ void Main::updateDebugger() #include\ "moc_MiningView.cpp" +#include\ +"moc_DownloadView.cpp" + #endif diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index a3bfa718d..ce1a9b670 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace Ui { class Main; @@ -69,7 +70,9 @@ public: explicit Main(QWidget *parent = 0); ~Main(); - dev::eth::Client* client() const { return m_client.get(); } + dev::WebThreeDirect* web3() const { return m_webThree.get(); } + dev::eth::Client* ethereum() const { return m_webThree->ethereum(); } + dev::shh::WhisperHost* whisper() const { return m_webThree->whisper(); } QList const& owned() const { return m_myKeys; } @@ -146,6 +149,8 @@ signals: void poll(); private: + dev::p2p::NetworkPreferences netPrefs() const; + QString pretty(dev::Address _a) const; QString prettyU256(dev::u256 _n) const; @@ -200,7 +205,7 @@ private: std::unique_ptr ui; - std::unique_ptr m_client; + std::unique_ptr m_webThree; std::map> m_handlers; unsigned m_nameRegFilter = (unsigned)-1; diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 93946aa8f..eee1d258b 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -4,13 +4,13 @@ aux_source_directory(. SRC_LIST) include_directories(..) link_directories(../libethcore) -link_directories(../libethereum) +link_directories(../libwebthree) set(EXECUTABLE eth) add_executable(${EXECUTABLE} ${SRC_LIST}) -target_link_libraries(${EXECUTABLE} ethereum) +target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) if(MINIUPNPC_LS) diff --git a/eth/EthStubServer.cpp b/eth/EthStubServer.cpp index 86bb1ba58..ad6a87781 100644 --- a/eth/EthStubServer.cpp +++ b/eth/EthStubServer.cpp @@ -25,14 +25,15 @@ #include #include #include +#include #include "CommonJS.h" using namespace std; using namespace dev; using namespace dev::eth; -EthStubServer::EthStubServer(jsonrpc::AbstractServerConnector* _conn, Client& _client): +EthStubServer::EthStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3): AbstractEthStubServer(_conn), - m_client(_client) + m_web3(_web3) { } @@ -59,20 +60,25 @@ Json::Value EthStubServer::procedures() return ret; } +dev::eth::Client& EthStubServer::ethereum() const +{ + return *m_web3.ethereum(); +} + std::string EthStubServer::coinbase() { - return toJS(m_client.address()); + return toJS(ethereum().address()); } std::string EthStubServer::balanceAt(std::string const& _a) { - return toJS(m_client.balanceAt(jsToAddress(_a), 0)); + return toJS(ethereum().balanceAt(jsToAddress(_a), 0)); } Json::Value EthStubServer::check(Json::Value const& _as) { // TODO -// if (m_client.changed()) +// if (ethereum().changed()) return _as; /* else { @@ -84,7 +90,7 @@ Json::Value EthStubServer::check(Json::Value const& _as) std::string EthStubServer::create(const std::string& _bCode, const std::string& _sec, const std::string& _xEndowment, const std::string& _xGas, const std::string& _xGasPrice) { - Address ret = m_client.transact(jsToSecret(_sec), jsToU256(_xEndowment), jsToBytes(_bCode), jsToU256(_xGas), jsToU256(_xGasPrice)); + Address ret = ethereum().transact(jsToSecret(_sec), jsToU256(_xEndowment), jsToBytes(_bCode), jsToU256(_xGas), jsToU256(_xGasPrice)); return toJS(ret); } @@ -100,17 +106,17 @@ std::string EthStubServer::gasPrice() bool EthStubServer::isContractAt(const std::string& _a) { - return m_client.codeAt(jsToAddress(_a), 0).size(); + return ethereum().codeAt(jsToAddress(_a), 0).size(); } bool EthStubServer::isListening() { - return m_client.haveNetwork(); + return m_web3.haveNetwork(); } bool EthStubServer::isMining() { - return m_client.isMining(); + return ethereum().isMining(); } std::string EthStubServer::key() @@ -130,23 +136,28 @@ Json::Value EthStubServer::keys() int EthStubServer::peerCount() { - return m_client.peerCount(); + return m_web3.peerCount(); } std::string EthStubServer::storageAt(const std::string& _a, const std::string& x) { - return toJS(m_client.stateAt(jsToAddress(_a), jsToU256(x), 0)); + return toJS(ethereum().stateAt(jsToAddress(_a), jsToU256(x), 0)); +} + +std::string EthStubServer::stateAt(const std::string& _a, const std::string& x, const std::string& s) +{ + return toJS(ethereum().stateAt(jsToAddress(_a), jsToU256(x), std::atol(s.c_str()))); } Json::Value EthStubServer::transact(const std::string& _aDest, const std::string& _bData, const std::string& _sec, const std::string& _xGas, const std::string& _xGasPrice, const std::string& _xValue) { - m_client.transact(jsToSecret(_sec), jsToU256(_xValue), jsToAddress(_aDest), jsToBytes(_bData), jsToU256(_xGas), jsToU256(_xGasPrice)); + ethereum().transact(jsToSecret(_sec), jsToU256(_xValue), jsToAddress(_aDest), jsToBytes(_bData), jsToU256(_xGas), jsToU256(_xGasPrice)); return Json::Value(); } std::string EthStubServer::txCountAt(const std::string& _a) { - return toJS(m_client.countAt(jsToAddress(_a), 0)); + return toJS(ethereum().countAt(jsToAddress(_a), 0)); } std::string EthStubServer::secretToAddress(const std::string& _a) @@ -167,7 +178,7 @@ Json::Value EthStubServer::block(const std::string& _hash) Json::Value EthStubServer::blockJson(const std::string& _hash) { Json::Value res; - auto const& bc = m_client.blockChain(); + auto const& bc = ethereum().blockChain(); auto b = _hash.length() ? bc.block(h256(_hash)) : bc.block(); diff --git a/eth/EthStubServer.h b/eth/EthStubServer.h index 28af916a2..469abed07 100644 --- a/eth/EthStubServer.h +++ b/eth/EthStubServer.h @@ -29,12 +29,12 @@ #include "abstractethstubserver.h" #pragma GCC diagnostic pop -namespace dev { namespace eth { class Client; } class KeyPair; } +namespace dev { class WebThreeDirect; namespace eth { class Client; } class KeyPair; } class EthStubServer: public AbstractEthStubServer { public: - EthStubServer(jsonrpc::AbstractServerConnector* _conn, dev::eth::Client& _client); + EthStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3); virtual Json::Value procedures(); virtual std::string balanceAt(std::string const& _a); @@ -49,6 +49,7 @@ public: virtual Json::Value keys(); virtual int peerCount(); virtual std::string storageAt(const std::string& a, const std::string& x); + virtual std::string stateAt(const std::string& a, const std::string& x, const std::string& s); virtual Json::Value transact(const std::string& aDest, const std::string& bData, const std::string& sec, const std::string& xGas, const std::string& xGasPrice, const std::string& xValue); virtual std::string txCountAt(const std::string& a); virtual std::string secretToAddress(const std::string& a); @@ -57,7 +58,8 @@ public: virtual Json::Value block(const std::string&); void setKeys(std::vector _keys) { m_keys = _keys; } private: - dev::eth::Client& m_client; + dev::eth::Client& ethereum() const; + dev::WebThreeDirect& m_web3; std::vector m_keys; Json::Value jsontypeToValue(int); Json::Value blockJson(const std::string&); diff --git a/eth/abstractethstubserver.h b/eth/abstractethstubserver.h index 940e4c809..7f110513d 100644 --- a/eth/abstractethstubserver.h +++ b/eth/abstractethstubserver.h @@ -30,6 +30,7 @@ class AbstractEthStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("procedures", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::proceduresI); this->bindAndAddMethod(new jsonrpc::Procedure("secretToAddress", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::secretToAddressI); this->bindAndAddMethod(new jsonrpc::Procedure("storageAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING,"x",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::storageAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("stateAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING,"x",jsonrpc::JSON_STRING,"s",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::stateAtI); this->bindAndAddMethod(new jsonrpc::Procedure("transact", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "aDest",jsonrpc::JSON_STRING,"bData",jsonrpc::JSON_STRING,"sec",jsonrpc::JSON_STRING,"xGas",jsonrpc::JSON_STRING,"xGasPrice",jsonrpc::JSON_STRING,"xValue",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::transactI); this->bindAndAddMethod(new jsonrpc::Procedure("txCountAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::txCountAtI); @@ -120,6 +121,11 @@ class AbstractEthStubServer : public jsonrpc::AbstractServerstorageAt(request["a"].asString(), request["x"].asString()); } + inline virtual void stateAtI(const Json::Value& request, Json::Value& response) + { + response = this->stateAt(request["a"].asString(), request["x"].asString(), request["s"].asString()); + } + inline virtual void transactI(const Json::Value& request, Json::Value& response) { response = this->transact(request["aDest"].asString(), request["bData"].asString(), request["sec"].asString(), request["xGas"].asString(), request["xGasPrice"].asString(), request["xValue"].asString()); @@ -148,6 +154,7 @@ class AbstractEthStubServer : public jsonrpc::AbstractServer #include #include +#include #if ETH_READLINE #include #include @@ -43,6 +44,7 @@ #include "BuildInfo.h" using namespace std; using namespace dev; +using namespace dev::p2p; using namespace dev::eth; using namespace boost::algorithm; using dev::eth::Instruction; @@ -97,6 +99,7 @@ void help() << "Usage eth [OPTIONS] " << endl << "Options:" << endl << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl + << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl << " -c,--client-name Add a name to your client's version string (default: blank)." << endl << " -d,--db-path Load database from path (default: ~/.ethereum " << endl << " /Etherum or Library/Application Support/Ethereum)." << endl @@ -110,7 +113,8 @@ void help() << " -l,--listen Listen on the given port for incoming connected (default: 30303)." << endl << " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl << " -n,--upnp Use upnp for NAT (default: on)." << endl - << " -o,--mode Start a full node or a peer node (Default: full)." << endl + << " -L,--local-networking Use peers whose addresses are local." << endl + << " -o,--mode Start a full node or a peer node (Default: full)." << endl << " -p,--port Connect to remote port (default: 30303)." << endl << " -r,--remote Connect to remote host (default: none)." << endl << " -s,--secret Set the secret key for use with send command (default: auto)." << endl @@ -131,17 +135,8 @@ string credits(bool _interactive = false) if (_interactive) { - string vs = toString(dev::Version); - vs = vs.substr(vs.find_first_of('.') + 1)[0]; - int pocnumber = stoi(vs); - string m_servers; - if (pocnumber == 4) - m_servers = "54.72.31.55"; - else - m_servers = "54.72.69.180"; - cout << "Type 'netstart 30303' to start networking" << endl; - cout << "Type 'connect " << m_servers << " 30303' to connect" << endl; + cout << "Type 'connect " << Host::pocHost() << " 30303' to connect" << endl; cout << "Type 'exit' to quit" << endl << endl; } return cout.str(); @@ -182,10 +177,12 @@ int main(int argc, char** argv) unsigned peers = 5; bool interactive = false; #if ETH_JSONRPC - int jsonrpc = 8080; + int jsonrpc = -1; #endif string publicIP; + bool bootstrap = false; bool upnp = true; + bool useLocal = false; bool forceMining = false; string clientName; @@ -231,10 +228,12 @@ int main(int argc, char** argv) upnp = false; else { - cerr << "Invalid UPnP option: " << m << endl; + cerr << "Invalid -n/--upnp option: " << m << endl; return -1; } } + else if (arg == "-L" || arg == "--local-networking") + useLocal = true; else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) clientName = argv[++i]; else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) @@ -254,17 +253,19 @@ int main(int argc, char** argv) mining = i; else { - cerr << "Unknown mining option: " << m << endl; + cerr << "Unknown -m/--mining option: " << m << endl; return -1; } } + else if (arg == "-b" || arg == "--bootstrap") + bootstrap = true; else if (arg == "-f" || arg == "--force-mining") forceMining = true; else if (arg == "-i" || arg == "--interactive") interactive = true; #if ETH_JSONRPC else if ((arg == "-j" || arg == "--json-rpc")) - jsonrpc = jsonrpc ? jsonrpc : 8080; + jsonrpc = jsonrpc == -1 ? 8080 : jsonrpc; else if (arg == "--json-rpc-port" && i + 1 < argc) jsonrpc = atoi(argv[++i]); #endif @@ -296,22 +297,32 @@ int main(int argc, char** argv) if (!clientName.empty()) clientName += "/"; - Client c("Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), coinbase, dbPath); - - c.setForceMining(true); - cout << credits(); - c.setForceMining(forceMining); + NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); + dev::WebThreeDirect web3("Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath, false, mode == NodeMode::Full ? set{"eth", "shh"} : set{}, netPrefs); + web3.setIdealPeerCount(peers); + eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; + + if (c) + { + c->setForceMining(forceMining); + c->setAddress(coinbase); + } cout << "Address: " << endl << toHex(us.address().asArray()) << endl; - c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp); + web3.startNetwork(); + + if (bootstrap) + web3.connect(Host::pocHost()); + if (remoteHost.size()) + web3.connect(remoteHost, remotePort); #if ETH_JSONRPC auto_ptr jsonrpcServer; if (jsonrpc > -1) { - jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c)); + jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3)); jsonrpcServer->setKeys({us}); jsonrpcServer->StartListening(); } @@ -349,34 +360,34 @@ int main(int argc, char** argv) iss >> cmd; if (cmd == "netstart") { - unsigned port; - iss >> port; - c.startNetwork((short)port); + iss >> netPrefs.listenPort; + web3.setNetworkPreferences(netPrefs); + web3.startNetwork(); } else if (cmd == "connect") { string addr; unsigned port; iss >> addr >> port; - c.connect(addr, (short)port); + web3.connect(addr, (short)port); } else if (cmd == "netstop") { - c.stopNetwork(); + web3.stopNetwork(); } - else if (cmd == "minestart") + else if (c && cmd == "minestart") { - c.startMining(); + c->startMining(); } - else if (cmd == "minestop") + else if (c && cmd == "minestop") { - c.stopMining(); + c->stopMining(); } - else if (cmd == "mineforce") + else if (c && cmd == "mineforce") { string enable; iss >> enable; - c.setForceMining(isTrue(enable)); + c->setForceMining(isTrue(enable)); } else if (cmd == "verbosity") { @@ -395,7 +406,7 @@ int main(int argc, char** argv) { if (jsonrpc < 0) jsonrpc = 8080; - jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c)); + jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3)); jsonrpcServer->setKeys({us}); jsonrpcServer->StartListening(); } @@ -416,24 +427,24 @@ int main(int argc, char** argv) { cout << "Secret Key: " << toHex(us.secret().asArray()) << endl; } - else if (cmd == "block") + else if (c && cmd == "block") { - cout << "Current block: " << c.blockChain().details().number << endl; + cout << "Current block: " <blockChain().details().number << endl; } else if (cmd == "peers") { - for (auto it: c.peers()) + for (auto it: web3.peers()) cout << it.host << ":" << it.port << ", " << it.clientVersion << ", " << std::chrono::duration_cast(it.lastPing).count() << "ms" << endl; } - else if (cmd == "balance") + else if (c && cmd == "balance") { - cout << "Current balance: " << formatBalance(c.balanceAt(us.address())) << " = " << c.balanceAt(us.address()) << " wei" << endl; + cout << "Current balance: " << formatBalance( c->balanceAt(us.address())) << " = " <balanceAt(us.address()) << " wei" << endl; } - else if (cmd == "transact") + else if (c && cmd == "transact") { - auto const& bc = c.blockChain(); + auto const& bc =c->blockChain(); auto h = bc.currentHash(); auto blockData = bc.block(h); BlockInfo info(blockData); @@ -478,35 +489,35 @@ int main(int argc, char** argv) { Secret secret = h256(fromHex(sechex)); Address dest = h160(fromHex(hexAddr)); - c.transact(secret, amount, dest, data, gas, gasPrice); + c->transact(secret, amount, dest, data, gas, gasPrice); } } else cwarn << "Require parameters: transact ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; } - else if (cmd == "listContracts") + else if (c && cmd == "listContracts") { - auto acs = c.addresses(); + auto acs =c->addresses(); string ss; for (auto const& i: acs) - if (c.codeAt(i, 0).size()) + if ( c->codeAt(i, 0).size()) { - ss = toString(i) + " : " + toString(c.balanceAt(i)) + " [" + toString((unsigned)c.countAt(i)) + "]"; + ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; cout << ss << endl; } } - else if (cmd == "listAccounts") + else if (c && cmd == "listAccounts") { - auto acs = c.addresses(); + auto acs =c->addresses(); string ss; for (auto const& i: acs) - if (c.codeAt(i, 0).empty()) + if ( c->codeAt(i, 0).empty()) { - ss = toString(i) + " : " + toString(c.balanceAt(i)) + " [" + toString((unsigned)c.countAt(i)) + "]"; + ss = toString(i) + " : " + toString( c->balanceAt(i)) + " [" + toString((unsigned) c->countAt(i)) + "]"; cout << ss << endl; } } - else if (cmd == "send") + else if (c && cmd == "send") { if (iss.peek() != -1) { @@ -522,21 +533,21 @@ int main(int argc, char** argv) } else { - auto const& bc = c.blockChain(); + auto const& bc =c->blockChain(); auto h = bc.currentHash(); auto blockData = bc.block(h); BlockInfo info(blockData); u256 minGas = (u256)Client::txGas(0, 0); Address dest = h160(fromHex(hexAddr)); - c.transact(us.secret(), amount, dest, bytes(), minGas, info.minGasPrice); + c->transact(us.secret(), amount, dest, bytes(), minGas, info.minGasPrice); } } else cwarn << "Require parameters: send ADDRESS AMOUNT"; } - else if (cmd == "contract") + else if (c && cmd == "contract") { - auto const& bc = c.blockChain(); + auto const& bc =c->blockChain(); auto h = bc.currentHash(); auto blockData = bc.block(h); BlockInfo info(blockData); @@ -573,12 +584,12 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - c.transact(us.secret(), endowment, init, gas, gasPrice); + c->transact(us.secret(), endowment, init, gas, gasPrice); } else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; } - else if (cmd == "dumptrace") + else if (c && cmd == "dumptrace") { unsigned block; unsigned index; @@ -588,7 +599,7 @@ int main(int argc, char** argv) ofstream f; f.open(filename); - dev::eth::State state = c.state(index + 1, c.blockChain().numberHash(block)); + dev::eth::State state =c->state(index + 1,c->blockChain().numberHash(block)); if (index < state.pending().size()) { Executive e(state); @@ -633,7 +644,7 @@ int main(int argc, char** argv) e.finalize(oof); } } - else if (cmd == "inspect") + else if (c && cmd == "inspect") { string rechex; iss >> rechex; @@ -647,10 +658,10 @@ int main(int argc, char** argv) try { - auto storage = c.storageAt(h, 0); + auto storage =c->storageAt(h, 0); for (auto const& i: storage) s << "@" << showbase << hex << i.first << " " << showbase << hex << i.second << endl; - s << endl << disassemble(c.codeAt(h, 0)) << endl; + s << endl << disassemble( c->codeAt(h, 0)) << endl; string outFile = getDataDir() + "/" + rechex + ".evm"; ofstream ofs; @@ -735,19 +746,21 @@ int main(int argc, char** argv) jsonrpcServer->StopListening(); #endif } - else + else if (c) { - unsigned n = c.blockChain().details().number; + unsigned n =c->blockChain().details().number; if (mining) - c.startMining(); + c->startMining(); while (true) { - if (c.blockChain().details().number - n == mining) - c.stopMining(); + if ( c->isMining() &&c->blockChain().details().number - n == mining) + c->stopMining(); this_thread::sleep_for(chrono::milliseconds(100)); } } - + else + while (true) + this_thread::sleep_for(chrono::milliseconds(1000)); return 0; } diff --git a/exp/main.cpp b/exp/main.cpp index c49b13e44..1f29ab207 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -19,290 +19,59 @@ * @date 2014 * Ethereum client. */ -#if 0 -#define BOOST_RESULT_OF_USE_DECLTYPE -#define BOOST_SPIRIT_USE_PHOENIX_V3 -#include -#include -#include -#endif +#include #include #include #include #include #include +#include +#include #include -#if 0 -#include -#include "BuildInfo.h" -#endif using namespace std; using namespace dev; using namespace dev::eth; using namespace dev::p2p; using namespace dev::shh; -#if 0 -#if 0 -namespace qi = boost::spirit::qi; -namespace px = boost::phoenix; -namespace sp = boost::spirit; - -class ASTSymbol: public string -{ -public: - ASTSymbol() {} -}; - -enum class ASTType -{ - Symbol, - IntegerLiteral, - StringLiteral, - Call, - Return, - Operator, - Compound -}; - -class ASTNode: public vector -{ -public: - ASTNode() {} - ASTNode(ASTSymbol const& _s): m_type(ASTType::Symbol), m_s(_s) {} - ASTNode(string const& _s): m_type(ASTType::StringLiteral), m_s(_s) {} - ASTNode(bigint const& _i): m_type(ASTType::IntegerLiteral), m_i(_i) {} - ASTNode(ASTType _t): m_type(_t) {} - - ASTNode& operator=(ASTSymbol const& _s) { m_type = ASTType::Symbol; m_s = _s; return *this; } - ASTNode& operator=(string const& _s) { m_type = ASTType::StringLiteral; m_s = _s; return *this; } - ASTNode& operator=(bigint const& _i) { m_type = ASTType::IntegerLiteral; m_i = _i; return *this; } - ASTNode& operator=(ASTType const& _s) { m_type = _s; return *this; } - - void debugOut(ostream& _out) const; - -private: - ASTType m_type; - string m_s; - bigint m_i; -}; - -void parseTree(string const& _s, ASTNode& o_out) -{ - using qi::standard::space; - using qi::standard::space_type; - typedef string::const_iterator it; - -/* static const u256 ether = u256(1000000000) * 1000000000; - static const u256 finney = u256(1000000000) * 1000000; - static const u256 szabo = u256(1000000000) * 1000;*/ - - qi::rule element; - qi::rule call; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; -/* qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule seq = '{' > *element > '}'; - qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element; - qi::rule list = '(' > *element > ')'; - - qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()];*/ - qi::rule value = call[qi::_val = ASTType::Call] | str[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule compound = '{' > *element > '}'; - call = '(' > *value > ')'; //symbol > '(' > !(value > *(',' > value)) > ')'; - element = compound[qi::_val = ASTType::Compound] | value[qi::_val = qi::_1]; - - auto ret = _s.cbegin(); - qi::phrase_parse(ret, _s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); - for (auto i = ret; i != _s.cend(); ++i) - if (!isspace(*i)) - throw std::exception(); -} - -void ASTNode::debugOut(ostream& _out) const -{ - switch (m_type) - { - case ASTType::StringLiteral: - _out << "\"" << m_s << "\""; - break; - case ASTType::Symbol: - _out << m_s; - break; - case ASTType::Compound: - { - unsigned n = 0; - _out << "{"; - for (auto const& i: *this) - { - i.debugOut(_out); - _out << ";"; - ++n; - } - _out << "}"; - break; - } - case ASTType::Call: - { - unsigned n = 0; - for (auto const& i: *this) - { - i.debugOut(_out); - if (n == 0) - _out << "("; - else if (n < size() - 1) - _out << ","; - if (n == size() - 1) - _out << ")"; - ++n; - } - break; - } - default: - _out << "nil"; - } -} - -int main(int, char**) +int main() { - ASTNode out; - parseTree("{x}", out); - out.debugOut(cout); - cout << endl; + DownloadMan man; + DownloadSub s0(man); + DownloadSub s1(man); + DownloadSub s2(man); + man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)})); + cnote << s0.nextFetch(2); + cnote << s1.nextFetch(2); + cnote << s2.nextFetch(2); + s0.noteBlock(u256(0)); + s0.doneFetch(); + cnote << s0.nextFetch(2); + s1.noteBlock(u256(2)); + s1.noteBlock(u256(3)); + s1.doneFetch(); + cnote << s1.nextFetch(2); + s0.doneFetch(); + cnote << s0.nextFetch(2); + +/* RangeMask m(0, 100); + cnote << m; + m += UnsignedRange(3, 10); + cnote << m; + m += UnsignedRange(11, 16); + cnote << m; + m += UnsignedRange(10, 11); + cnote << m; + cnote << ~m; + cnote << (~m).lowest(10); + for (auto i: (~m).lowest(10)) + cnote << i;*/ return 0; } -#endif -void killBigints(sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; - case sp::utree_type::any_type: delete _this.get(); break; - default:; - } -} - -void debugOutAST(ostream& _out, sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: - switch (_this.tag()) - { - case 0: { int n = 0; for (auto const& i: _this) { debugOutAST(_out, i); if (n++) _out << ", "; } break; } - case 1: _out << "@ "; debugOutAST(_out, _this.front()); break; - case 2: _out << "@@ "; debugOutAST(_out, _this.front()); break; - case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; - case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; - case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; - case 6: _out << "$ "; debugOutAST(_out, _this.front()); break; - default: - { _out << _this.tag() << ": "; int n = 0; for (auto const& i: _this) { debugOutAST(_out, i); if (n++) _out << ", "; } break; } - } - - break; - case sp::utree_type::int_type: _out << _this.get(); break; - case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; - case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; - case sp::utree_type::any_type: _out << *_this.get(); break; - default: _out << "nil"; - } -} - -namespace dev { -namespace eth { -namespace parseTreeLLL_ { - -template -struct tagNode -{ - void operator()(sp::utree& n, qi::rule::context_type& c) const - { - (boost::fusion::at_c<0>(c.attributes) = n).tag(N); - } -}; - -}}} - -void parseTree(string const& _s, sp::utree& o_out) -{ - using qi::standard::space; - using qi::standard::space_type; - using dev::eth::parseTreeLLL_::tagNode; - typedef sp::basic_string symbol_type; - typedef string::const_iterator it; - - static const u256 ether = u256(1000000000) * 1000000000; - static const u256 finney = u256(1000000000) * 1000000; - static const u256 szabo = u256(1000000000) * 1000; -#if 0 - qi::rule element; - qi::rule statement; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule compound = '{' > *statement > '}'; -/* qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element;*/ -// qi::rule args = '(' > (element % ',') > ')'; - - qi::rule expression; - qi::rule group = '(' >> expression[qi::_val = qi::_1] >> ')'; - qi::rule factor = atom | group; - qi::rule mul = '*' >> factor; - qi::rule div = '/' >> factor; - qi::rule op = mul[tagNode<10>()] | div[tagNode<11>()]; - qi::rule term = factor >> !op; - expression = term >> !(('+' >> term) | ('-' >> term)); - - // qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | calldataload[tagNode<6>()]; - statement = compound[tagNode<5>()] | (element > ';')[qi::_val = qi::_1]; - element %= expression;// | extra; -#endif - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule intnode = integer[qi::_val = px::construct(px::new_(qi::_1))]; - qi::rule funcname = symbol; - qi::rule statement; - qi::rule call = funcname > '(' > funcname > ')'; - statement = call | intnode | symbol; - - auto ret = _s.cbegin(); - qi::phrase_parse(ret, _s.cend(), statement, space, qi::skip_flag::dont_postskip, o_out); - for (auto i = ret; i != _s.cend(); ++i) - if (!isspace(*i)) - throw std::exception(); -} -#endif +/* int main(int argc, char** argv) { -#if 0 - sp::utree out; - parseTree("x(2)", out); - debugOutAST(cout, out); - killBigints(out); - cout << endl; -#endif - g_logVerbosity = 20; short listenPort = 30303; @@ -322,24 +91,25 @@ int main(int argc, char** argv) remoteHost = argv[i]; } - Host ph("Test", listenPort, "", false, true); + Host ph("Test", NetworkPreferences(listenPort, "", false, true)); ph.registerCapability(new WhisperHost()); auto wh = ph.cap(); + ph.start(); + if (!remoteHost.empty()) ph.connect(remoteHost, remotePort); /// Only interested in the packet if the lowest bit is 1 auto w = wh->installWatch(MessageFilter(std::vector >({{fromHex("0000000000000000000000000000000000000000000000000000000000000001"), fromHex("0000000000000000000000000000000000000000000000000000000000000001")}}))); + for (int i = 0; ; ++i) { - this_thread::sleep_for(chrono::milliseconds(1000)); - ph.process(); wh->sendRaw(h256(u256(i * i)).asBytes(), h256(u256(i)).asBytes(), 1000); for (auto i: wh->checkWatch(w)) cnote << "New message:" << (u256)h256(wh->message(i).payload); } - return 0; } +*/ diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 325ba274e..8312960c1 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.6.8b"; +char const* Version = "0.6.9"; } diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 96269bbc1..6e889a6b0 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -102,3 +102,181 @@ bytes dev::asNibbles(std::string const& _s) } return ret; } + +#if 0 + +/* Following code is copyright 2012-2014 Luke Dashjr + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the standard MIT license. See COPYING for more details. + */ + +#include +#include +#include +#include + +static const int8_t b58digits_map[] = { + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, + -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, + 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, + -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, + 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, +}; + +bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) +{ + size_t binsz = *binszp; + const unsigned char *b58u = (void*)b58; + unsigned char *binu = bin; + size_t outisz = (binsz + 3) / 4; + uint32_t outi[outisz]; + uint64_t t; + uint32_t c; + size_t i, j; + uint8_t bytesleft = binsz % 4; + uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; + unsigned zerocount = 0; + + if (!b58sz) + b58sz = strlen(b58); + + memset(outi, 0, outisz * sizeof(*outi)); + + // Leading zeros, just count + for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) + ++zerocount; + + for ( ; i < b58sz; ++i) + { + if (b58u[i] & 0x80) + // High-bit set on invalid digit + return false; + if (b58digits_map[b58u[i]] == -1) + // Invalid base58 digit + return false; + c = (unsigned)b58digits_map[b58u[i]]; + for (j = outisz; j--; ) + { + t = ((uint64_t)outi[j]) * 58 + c; + c = (t & 0x3f00000000) >> 32; + outi[j] = t & 0xffffffff; + } + if (c) + // Output number too big (carry to the next int32) + return false; + if (outi[0] & zeromask) + // Output number too big (last int32 filled too far) + return false; + } + + j = 0; + switch (bytesleft) { + case 3: + *(binu++) = (outi[0] & 0xff0000) >> 16; + case 2: + *(binu++) = (outi[0] & 0xff00) >> 8; + case 1: + *(binu++) = (outi[0] & 0xff); + ++j; + default: + break; + } + + for (; j < outisz; ++j) + { + *(binu++) = (outi[j] >> 0x18) & 0xff; + *(binu++) = (outi[j] >> 0x10) & 0xff; + *(binu++) = (outi[j] >> 8) & 0xff; + *(binu++) = (outi[j] >> 0) & 0xff; + } + + // Count canonical base58 byte count + binu = bin; + for (i = 0; i < binsz; ++i) + { + if (binu[i]) + break; + --*binszp; + } + *binszp += zerocount; + + return true; +} + +static +bool my_dblsha256(void *hash, const void *data, size_t datasz) +{ + uint8_t buf[0x20]; + return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); +} + +int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) +{ + unsigned char buf[32]; + const uint8_t *binc = bin; + unsigned i; + if (binsz < 4) + return -4; + if (!my_dblsha256(buf, bin, binsz - 4)) + return -2; + if (memcmp(&binc[binsz - 4], buf, 4)) + return -1; + + // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) + for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) + {} // Just finding the end of zeros, nothing to do in loop + if (binc[i] == '\0' || base58str[i] == '1') + return -3; + + return binc[0]; +} + +static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) +{ + const uint8_t *bin = data; + int carry; + size_t i, j, high, zcount = 0; + size_t size; + + while (zcount < binsz && !bin[zcount]) + ++zcount; + + size = (binsz - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memset(buf, 0, size); + + for (i = zcount, high = size - 1; i < binsz; ++i, high = j) + { + for (carry = bin[i], j = size - 1; (j > high) || carry; --j) + { + carry += 256 * buf[j]; + buf[j] = carry % 58; + carry /= 58; + } + } + + for (j = 0; j < size && !buf[j]; ++j); + + if (*b58sz <= zcount + size - j) + { + *b58sz = zcount + size - j + 1; + return false; + } + + if (zcount) + memset(b58, '1', zcount); + for (i = zcount; j < size; ++i, ++j) + b58[i] = b58digits_ordered[buf[j]]; + b58[i] = '\0'; + *b58sz = i + 1; + + return true; +} + +#endif diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 1181e07e8..11850fa69 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -55,6 +55,11 @@ int fromHex(char _i); /// @example fromHex("41626261") == asBytes("Abba") bytes fromHex(std::string const& _s); +#if 0 +std::string toBase58(bytesConstRef _data); +bytes fromBase58(std::string const& _s); +#endif + /// Converts byte array to a string containing the same (binary) data. Unless /// the byte array happens to contain ASCII data, this won't be printable. inline std::string asString(bytes const& _b) diff --git a/libdevcore/CommonIO.h b/libdevcore/CommonIO.h index 068c5c777..98c5a96c7 100644 --- a/libdevcore/CommonIO.h +++ b/libdevcore/CommonIO.h @@ -49,15 +49,6 @@ 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 -std::string toString(_T const& _t) -{ - std::ostringstream o; - o << _t; - return o.str(); -} - // Stream I/O functions. // Provides templated stream I/O for all STL collections so they can be shifted on to any iostream-like interface. @@ -223,4 +214,15 @@ template inline std::ostream& operator<<(std::ostream& _out, template _S& operator<<(_S& _out, std::shared_ptr<_T> const& _p) { if (_p) _out << "@" << (*_p); else _out << "nullptr"; return _out; } +// Functions that use streaming stuff. + +/// Converts arbitrary value to string representation using std::stringstream. +template +std::string toString(_T const& _t) +{ + std::ostringstream o; + o << _t; + return o.str(); +} + } diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index ed311a082..35e1d1dcf 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -160,7 +160,6 @@ public: explicit operator std::string() const { return toString(); } explicit operator RLPs() const { return toList(); } explicit operator byte() const { return toInt(); } - explicit operator unsigned() const { return toInt(); } explicit operator u256() const { return toInt(); } explicit operator bigint() const { return toInt(); } template explicit operator FixedHash<_N>() const { return toHash>(); } @@ -213,8 +212,8 @@ public: std::pair ret; if (isList()) { - ret.first = (*this)[0].operator T(); - ret.second = (*this)[1].operator U(); + ret.first = (T)(*this)[0]; + ret.second = (U)(*this)[1]; } return ret; } diff --git a/libdevcore/RangeMask.cpp b/libdevcore/RangeMask.cpp new file mode 100644 index 000000000..5317e00e8 --- /dev/null +++ b/libdevcore/RangeMask.cpp @@ -0,0 +1,22 @@ +/* + 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 . +*/ +/** @file RangeMask.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "RangeMask.h" diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h new file mode 100644 index 000000000..f1b0043ff --- /dev/null +++ b/libdevcore/RangeMask.h @@ -0,0 +1,212 @@ +/* + 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 . +*/ +/** @file EthereumHost.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include + +namespace dev +{ + +class RLPStream; + +using UnsignedRange = std::pair; +using UnsignedRanges = std::vector; + +template +class RangeMask +{ + template friend std::ostream& operator<<(std::ostream& _out, RangeMask const& _r); + +public: + using Range = std::pair; + using Ranges = std::vector; + + RangeMask() {} + RangeMask(T _begin, T _end): m_all(_begin, _end) {} + RangeMask(Range const& _c): m_all(_c) {} + + RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; } + + RangeMask lowest(T _items) const + { + RangeMask ret(m_all); + for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i) + _items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)) - i->first; + return ret; + } + + RangeMask operator~() const + { + RangeMask ret(m_all); + T last = m_all.first; + for (auto i: m_ranges) + { + if (i.first != last) + ret.m_ranges[last] = i.first; + last = i.second; + } + if (last != m_all.second) + ret.m_ranges[last] = m_all.second; + return ret; + } + + RangeMask& operator+=(RangeMask const& _m) + { + for (auto const& i: _m.m_ranges) + operator+=(i); + return *this; + } + RangeMask& operator+=(UnsignedRange const& _m) + { + for (auto i = _m.first; i < _m.second;) + { + // for each number, we find the element equal or next lower. this, if any, must contain the value. + auto uit = m_ranges.upper_bound(i); + auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); + if (it == m_ranges.end() || it->second < i) + // lower range is too low to merge. + // if the next higher range is too high. + if (uit == m_ranges.end() || uit->first > _m.second) + { + // just create a new range + m_ranges[i] = _m.second; + break; + } + else + { + if (uit->first == i) + // move i to end of range + i = uit->second; + else + { + // merge with the next higher range + // move i to end of range + i = m_ranges[i] = uit->second; + i = uit->second; + m_ranges.erase(uit); + } + } + else if (it->second == i) + { + // if the next higher range is too high. + if (uit == m_ranges.end() || uit->first > _m.second) + { + // merge with the next lower range + m_ranges[it->first] = _m.second; + break; + } + else + { + // merge with both next lower & next higher. + i = m_ranges[it->first] = uit->second; + m_ranges.erase(uit); + } + } + else + i = it->second; + } + return *this; + } + + RangeMask& operator+=(T _i) + { + return operator+=(Range(_i, _i + 1)); + } + + bool contains(T _i) const + { + auto it = m_ranges.upper_bound(_i); + if (it == m_ranges.begin()) + return false; + return (--it)->second > _i; + } + + bool empty() const + { + return m_ranges.empty(); + } + + bool full() const + { + return m_ranges.size() == 1 && m_ranges.begin()->first == m_all.first && m_ranges.begin()->second == m_all.second; + } + + void clear() + { + m_ranges.clear(); + } + + std::pair const& all() const { return m_all; } + + class const_iterator + { + friend class RangeMask; + + public: + const_iterator() {} + + T operator*() const { return m_value; } + const_iterator& operator++() { if (m_owner) m_value = m_owner->next(m_value); return *this; } + const_iterator operator++(int) { auto ret = *this; if (m_owner) m_value = m_owner->next(m_value); return ret; } + + bool operator==(const_iterator const& _i) const { return m_owner == _i.m_owner && m_value == _i.m_value; } + bool operator!=(const_iterator const& _i) const { return !operator==(_i); } + bool operator<(const_iterator const& _i) const { return m_value < _i.m_value; } + + private: + const_iterator(RangeMask const& _m, bool _end): m_owner(&_m), m_value(_m.m_ranges.empty() || _end ? _m.m_all.second : _m.m_ranges.begin()->first) {} + + RangeMask const* m_owner = nullptr; + T m_value = 0; + }; + + const_iterator begin() const { return const_iterator(*this, false); } + const_iterator end() const { return const_iterator(*this, true); } + T next(T _t) const + { + _t++; + // find next item in range at least _t + auto uit = m_ranges.upper_bound(_t); // > _t + auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); + if (it != m_ranges.end() && it->first <= _t && it->second > _t) + return _t; + return uit == m_ranges.end() ? m_all.second : uit->first; + } + +private: + UnsignedRange m_all; + std::map m_ranges; +}; + +template inline std::ostream& operator<<(std::ostream& _out, RangeMask const& _r) +{ + _out << _r.m_all.first << "{ "; + for (auto const& i: _r.m_ranges) + _out << "[" << i.first << ", " << i.second << ") "; + _out << "}" << _r.m_all.second; + return _out; +} + +} diff --git a/libdevcore/Worker.cpp b/libdevcore/Worker.cpp new file mode 100644 index 000000000..29ff766d7 --- /dev/null +++ b/libdevcore/Worker.cpp @@ -0,0 +1,63 @@ +/* + 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 . +*/ +/** @file Worker.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "Worker.h" + +#include +#include +#include "Log.h" +using namespace std; +using namespace dev; + +void Worker::startWorking() +{ + cdebug << "startWorking for thread" << m_name; + Guard l(x_work); + if (m_work) + return; + cdebug << "Spawning" << m_name; + m_stop = false; + m_work.reset(new thread([&]() + { + setThreadName(m_name.c_str()); + while (!m_stop) + { + this_thread::sleep_for(chrono::milliseconds(30)); + doWork(); + } + cdebug << "Finishing up worker thread"; + doneWorking(); + })); +} + +void Worker::stopWorking() +{ + cdebug << "stopWorking for thread" << m_name; + Guard l(x_work); + if (!m_work) + return; + cdebug << "Stopping" << m_name; + m_stop = true; + m_work->join(); + m_work.reset(); + cdebug << "Stopped" << m_name; +} + diff --git a/libdevcore/Worker.h b/libdevcore/Worker.h new file mode 100644 index 000000000..8f0baaf60 --- /dev/null +++ b/libdevcore/Worker.h @@ -0,0 +1,59 @@ +/* + 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 . +*/ +/** @file Worker.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include "Guards.h" + +namespace dev +{ + +class Worker +{ +protected: + Worker(std::string const& _name = "anon"): m_name(_name) {} + + /// Move-constructor. + Worker(Worker&& _m) { std::swap(m_name, _m.m_name); } + + /// Move-assignment. + Worker& operator=(Worker&& _m) { std::swap(m_name, _m.m_name); return *this; } + + virtual ~Worker() { stopWorking(); } + + void setName(std::string _n) { if (!isWorking()) m_name = _n; } + + void startWorking(); + void stopWorking(); + bool isWorking() const { Guard l(x_work); return !!m_work; } + virtual void doWork() = 0; + virtual void doneWorking() {} + +private: + mutable Mutex x_work; ///< Lock for the network existance. + std::unique_ptr m_work; ///< The network thread. + bool m_stop = false; + std::string m_name; +}; + +} diff --git a/libdevcrypto/FileSystem.cpp b/libdevcrypto/FileSystem.cpp index 1fb38b57f..e161c3234 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcrypto/FileSystem.cpp @@ -31,9 +31,8 @@ #include using namespace std; using namespace dev; -using namespace dev::eth; -std::string dev::eth::getDataDir() +std::string dev::getDataDir() { #ifdef _WIN32 char path[1024] = ""; diff --git a/libdevcrypto/FileSystem.h b/libdevcrypto/FileSystem.h index 9c597c421..605545b0d 100644 --- a/libdevcrypto/FileSystem.h +++ b/libdevcrypto/FileSystem.h @@ -27,11 +27,8 @@ namespace dev { -namespace eth -{ /// @returns the path for user data. std::string getDataDir(); } -} diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index 8186acaee..283f11b88 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -56,7 +56,7 @@ extern u256 c_genesisDifficulty; struct BlockInfo { public: - h256 hash; ///< SHA3 hash of the entire block! Not serialised (the only member not contained in a block header). + h256 hash; ///< SHA3 hash of the block header! Not serialised (the only member not contained in a block header). h256 parentHash; h256 sha3Uncles; Address coinbaseAddress; diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index f96fb5480..eed8b4bb9 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -34,7 +34,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 32; +const unsigned c_protocolVersion = 33; const unsigned c_databaseVersion = 1; static const vector> g_units = diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 716add2ae..79cccd4ef 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -108,6 +108,20 @@ bytes BlockChain::createGenesisBlock() } BlockChain::BlockChain(std::string _path, bool _killExisting) +{ + // Initialise with the genesis as the last block on the longest chain. + m_genesisHash = BlockChain::genesis().hash; + m_genesisBlock = BlockChain::createGenesisBlock(); + + open(_path, _killExisting); +} + +BlockChain::~BlockChain() +{ + close(); +} + +void BlockChain::open(std::string _path, bool _killExisting) { if (_path.empty()) _path = Defaults::get()->m_dbPath; @@ -127,10 +141,6 @@ BlockChain::BlockChain(std::string _path, bool _killExisting) if (!m_extrasDB) throw DatabaseAlreadyOpen(); - // Initialise with the genesis as the last block on the longest chain. - m_genesisHash = BlockChain::genesis().hash; - m_genesisBlock = BlockChain::createGenesisBlock(); - if (!details(m_genesisHash)) { // Insert details of genesis block. @@ -150,11 +160,16 @@ BlockChain::BlockChain(std::string _path, bool _killExisting) cnote << "Opened blockchain DB. Latest: " << currentHash(); } -BlockChain::~BlockChain() +void BlockChain::close() { cnote << "Closing blockchain DB"; delete m_extrasDB; delete m_db; + m_lastBlockHash = m_genesisHash; + m_details.clear(); + m_blooms.clear(); + m_traces.clear(); + m_cache.clear(); } template @@ -245,21 +260,24 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) auto newHash = BlockInfo::headerHash(_block); // Check block doesn't already exist first! - if (details(newHash)) + if (isKnown(newHash)) { clog(BlockChainNote) << newHash << ": Not new."; throw AlreadyHaveBlock(); } // Work out its number as the parent's number + 1 - auto pd = details(bi.parentHash); - if (!pd) + if (!isKnown(bi.parentHash)) { clog(BlockChainNote) << newHash << ": Unknown parent " << bi.parentHash; // We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on. throw UnknownParent(); } + auto pd = details(bi.parentHash); + if (!pd) + cwarn << "Odd: details is returning false despite block known:" << RLP(pd.rlp()); + // Check it's not crazy if (bi.timestamp > (u256)time(0)) { @@ -432,6 +450,20 @@ h256Set BlockChain::allUnclesFrom(h256 _parent) const return ret; } +bool BlockChain::isKnown(h256 _hash) const +{ + if (_hash == m_genesisHash) + return true; + { + ReadGuard l(x_cache); + if (m_cache.count(_hash)) + return true; + } + string d; + m_db->Get(m_readOptions, ldb::Slice((char const*)&_hash, 32), &d); + return !!d.size(); +} + bytes BlockChain::block(h256 _hash) const { if (_hash == m_genesisHash) diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index c0b3988a9..cf33a5104 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -70,6 +70,8 @@ public: BlockChain(std::string _path, bool _killExisting = false); ~BlockChain(); + void reopen(std::string _path, bool _killExisting = false) { close(); open(_path, _killExisting); } + /// (Potentially) renders invalid existing bytesConstRef returned by lastBlock. /// To be called from main loop every 100ms or so. void process(); @@ -85,6 +87,9 @@ public: /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. h256s import(bytes const& _block, OverlayDB const& _stateDB); + /// Returns true if the given block is known (though not necessarily a part of the canon chain). + bool isKnown(h256 _hash) const; + /// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. BlockDetails details(h256 _hash) const { return queryExtras(_hash, m_details, x_details, NullBlockDetails); } BlockDetails details() const { return details(currentHash()); } @@ -143,6 +148,9 @@ public: h256s treeRoute(h256 _from, h256 _to, h256* o_common = nullptr, bool _pre = true, bool _post = true) const; private: + void open(std::string _path, bool _killExisting = false); + void close(); + template T queryExtras(h256 _h, std::map& _m, boost::shared_mutex& _x, T const& _n) const { { diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 21aeb5a72..a845965d5 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -74,21 +74,24 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc) // Check it's not in the future if (bi.timestamp > (u256)time(0)) + { m_future.insert(make_pair((unsigned)bi.timestamp, _block.toBytes())); + cblockq << "OK - queued for future."; + } else { // We now know it. - if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.details(bi.parentHash)) + if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash)) { // We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on. -// cnote << "OK - queued for future."; + cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged(); m_unknown.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes()))); m_unknownSet.insert(h); } else { // If valid, append to blocks. -// cnote << "OK - ready for chain insertion."; + cblockq << "OK - ready for chain insertion."; m_ready.push_back(_block.toBytes()); m_readySet.insert(h); diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 5a4a86ad6..20bc4ce59 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -34,7 +34,7 @@ namespace eth class BlockChain; -struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 7; }; +struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 4; }; #define cblockq dev::LogOutputStream() /** @@ -64,6 +64,9 @@ public: /// Get information on the items queued. std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_ready.size(), m_unknown.size()); } + /// Clear everything. + void clear() { WriteGuard l(m_lock); m_readySet.clear(); m_drainingSet.clear(); m_ready.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); } + private: void noteReadyWithoutWriteGuard(h256 _b); void notePresentWithoutWriteGuard(bytesConstRef _block); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 3bc159f17..de0077f89 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -53,94 +53,107 @@ void VersionChecker::setOk() } } -Client::Client(std::string const& _clientVersion, Address _us, std::string const& _dbPath, bool _forceClean): - m_clientVersion(_clientVersion), - m_vc(_dbPath), - m_bc(_dbPath, !m_vc.ok() || _forceClean), - m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), - m_preMine(_us, m_stateDB), - m_postMine(_us, m_stateDB) -{ - setMiningThreads(); - if (_dbPath.size()) - Defaults::setDBPath(_dbPath); - m_vc.setOk(); - work(); -} - Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId): + Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), m_preMine(Address(), m_stateDB), m_postMine(Address(), m_stateDB) { - m_extHost = _extNet->registerCapability(new EthereumHost(m_bc, _networkId)); + m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); -// setMiningThreads(); + setMiningThreads(); if (_dbPath.size()) Defaults::setDBPath(_dbPath); m_vc.setOk(); - work(); + doWork(); + + startWorking(); } Client::~Client() { - if (m_work) - { - if (m_workState.load(std::memory_order_acquire) == Active) - m_workState.store(Deleting, std::memory_order_release); - while (m_workState.load(std::memory_order_acquire) != Deleted) - this_thread::sleep_for(chrono::milliseconds(10)); - m_work->join(); - m_work.reset(nullptr); - } - stopNetwork(); + stopWorking(); } -void Client::ensureWorking() +void Client::setNetworkId(u256 _n) { - static const char* c_threadName = "eth"; + if (auto h = m_host.lock()) + h->setNetworkId(_n); +} - if (!m_work) - m_work.reset(new thread([&]() - { - setThreadName(c_threadName); - m_workState.store(Active, std::memory_order_release); - while (m_workState.load(std::memory_order_acquire) != Deleting) - work(); - m_workState.store(Deleted, std::memory_order_release); - - // Synchronise the state according to the head of the block chain. - // TODO: currently it contains keys for *all* blocks. Make it remove old ones. - WriteGuard l(x_stateDB); - m_preMine.sync(m_bc); - m_postMine = m_preMine; - })); +DownloadMan const* Client::downloadMan() const { if (auto h = m_host.lock()) return &(h->downloadMan()); return nullptr; } +bool Client::isSyncing() const { if (auto h = m_host.lock()) return h->isSyncing(); return false; } + +void Client::doneWorking() +{ + // Synchronise the state according to the head of the block chain. + // TODO: currently it contains keys for *all* blocks. Make it remove old ones. + WriteGuard l(x_stateDB); + m_preMine.sync(m_bc); + m_postMine = m_preMine; } void Client::flushTransactions() { - work(); + doWork(); +} + +void Client::killChain() +{ + bool wasMining = isMining(); + if (wasMining) + stopMining(); + stopWorking(); + + m_tq.clear(); + m_bq.clear(); + m_miners.clear(); + m_preMine = State(); + m_postMine = State(); + + { + WriteGuard l(x_stateDB); + m_stateDB = OverlayDB(); + m_stateDB = State::openDB(Defaults::dbPath(), true); + } + m_bc.reopen(Defaults::dbPath(), true); + + m_preMine = State(Address(), m_stateDB); + m_postMine = State(Address(), m_stateDB); + + if (auto h = m_host.lock()) + h->reset(); + + doWork(); + + setMiningThreads(0); + + startWorking(); + if (wasMining) + startMining(); } void Client::clearPending() { - WriteGuard l(x_stateDB); - if (!m_postMine.pending().size()) - return; h256Set changeds; - for (unsigned i = 0; i < m_postMine.pending().size(); ++i) - appendFromNewPending(m_postMine.bloom(i), changeds); - changeds.insert(PendingChangedFilter); - m_postMine = m_preMine; + { + WriteGuard l(x_stateDB); + if (!m_postMine.pending().size()) + return; + for (unsigned i = 0; i < m_postMine.pending().size(); ++i) + appendFromNewPending(m_postMine.bloom(i), changeds); + changeds.insert(PendingChangedFilter); + m_postMine = m_preMine; + } - if (!m_extHost.lock()) { ReadGuard l(x_miners); for (auto& m: m_miners) m.noteStateChange(); } + noteChanged(changeds); } @@ -211,111 +224,10 @@ void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const o_changed.insert(i.first); } -void Client::startNetwork(unsigned short _listenPort, std::string const& _seedHost, unsigned short _port, NodeMode _mode, unsigned _peers, string const& _publicIP, bool _upnp, u256 _networkId) -{ - static const char* c_threadName = "net"; - - { - UpgradableGuard l(x_net); - if (m_net.get()) - return; - { - UpgradeGuard ul(l); - - if (!m_workNet) - m_workNet.reset(new thread([&]() - { - setThreadName(c_threadName); - m_workNetState.store(Active, std::memory_order_release); - while (m_workNetState.load(std::memory_order_acquire) != Deleting) - workNet(); - m_workNetState.store(Deleted, std::memory_order_release); - })); - - if (!m_extHost.lock()) - { - try - { - m_net.reset(new Host(m_clientVersion, _listenPort, _publicIP, _upnp)); - } - catch (std::exception const&) - { - // Probably already have the port open. - cwarn << "Could not initialize with specified/default port. Trying system-assigned port"; - m_net.reset(new Host(m_clientVersion, 0, _publicIP, _upnp)); - } - if (_mode == NodeMode::Full) - m_net->registerCapability(new EthereumHost(m_bc, _networkId)); - } - } - m_net->setIdealPeerCount(_peers); - } - - if (!m_extHost.lock()) - if (_seedHost.size()) - connect(_seedHost, _port); - - ensureWorking(); -} - -void Client::stopNetwork() -{ - UpgradableGuard l(x_net); - - if (m_workNet) - { - if (m_workNetState.load(std::memory_order_acquire) == Active) - m_workNetState.store(Deleting, std::memory_order_release); - while (m_workNetState.load(std::memory_order_acquire) != Deleted) - this_thread::sleep_for(chrono::milliseconds(10)); - m_workNet->join(); - } - if (m_net) - { - UpgradeGuard ul(l); - m_net.reset(nullptr); - m_workNet.reset(nullptr); - } -} - -std::vector Client::peers() -{ - ReadGuard l(x_net); - return m_net ? m_net->peers() : std::vector(); -} - -size_t Client::peerCount() const -{ - ReadGuard l(x_net); - return m_net ? m_net->peerCount() : 0; -} - -void Client::setIdealPeerCount(size_t _n) const -{ - ReadGuard l(x_net); - if (m_net) - return m_net->setIdealPeerCount(_n); -} - -bytes Client::savePeers() -{ - ReadGuard l(x_net); - if (m_net) - return m_net->savePeers(); - return bytes(); -} - -void Client::restorePeers(bytesConstRef _saved) -{ - ReadGuard l(x_net); - if (m_net) - return m_net->restorePeers(_saved); -} - void Client::setForceMining(bool _enable) { m_forceMining = _enable; - if (!m_extHost.lock()) + if (!m_host.lock()) { ReadGuard l(x_miners); for (auto& m: m_miners) @@ -323,19 +235,8 @@ void Client::setForceMining(bool _enable) } } -void Client::connect(std::string const& _seedHost, unsigned short _port) -{ - ReadGuard l(x_net); - if (!m_net.get()) - return; - m_net->connect(_seedHost, _port); -} - void Client::setMiningThreads(unsigned _threads) { - if (m_extHost.lock()) - return; - stopMining(); auto t = _threads ? _threads : thread::hardware_concurrency(); @@ -350,8 +251,6 @@ void Client::setMiningThreads(unsigned _threads) MineProgress Client::miningProgress() const { MineProgress ret; - if (m_extHost.lock()) - return ret; ReadGuard l(x_miners); for (auto& m: m_miners) ret.combine(m.miningProgress()); @@ -361,8 +260,6 @@ MineProgress Client::miningProgress() const std::list Client::miningHistory() { std::list ret; - if (m_extHost.lock()) - return ret; ReadGuard l(x_miners); if (m_miners.empty()) @@ -404,7 +301,7 @@ void Client::setupState(State& _s) void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { - ensureWorking(); + startWorking(); Transaction t; // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); @@ -446,7 +343,7 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) { - ensureWorking(); + startWorking(); Transaction t; { @@ -466,47 +363,18 @@ Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u2 void Client::inject(bytesConstRef _rlp) { - ensureWorking(); + startWorking(); m_tq.attemptImport(_rlp); } -void Client::workNet() -{ - // Process network events. - // Synchronise block chain with network. - // Will broadcast any of our (new) transactions and blocks, and collect & add any of their (new) transactions and blocks. - { - ReadGuard l(x_net); - if (m_net) - { - cwork << "NETWORK"; - m_net->process(); // must be in guard for now since it uses the blockchain. - - // returns h256Set as block hashes, once for each block that has come in/gone out. - if (m_net->cap()) - { - cwork << "NET <==> TQ ; CHAIN ==> NET ==> BQ"; - m_net->cap()->sync(m_tq, m_bq); - cwork << "TQ:" << m_tq.items() << "; BQ:" << m_bq.items(); - } - } - } - - if (auto h = m_extHost.lock()) - h->sync(m_tq, m_bq); - - this_thread::sleep_for(chrono::milliseconds(1)); -} - -void Client::work() +void Client::doWork() { // TODO: Use condition variable rather than polling. cworkin << "WORK"; h256Set changeds; - if (!m_extHost.lock()) { ReadGuard l(x_miners); for (auto& m: m_miners) @@ -557,7 +425,8 @@ void Client::work() cwork << "preSTATE <== CHAIN"; if (m_preMine.sync(m_bc) || m_postMine.address() != m_preMine.address()) { - cnote << "New block on chain: Restarting mining operation."; + if (isMining()) + cnote << "New block on chain: Restarting mining operation."; m_postMine = m_preMine; rsm = true; changeds.insert(PendingChangedFilter); @@ -573,11 +442,12 @@ void Client::work() appendFromNewPending(i, changeds); changeds.insert(PendingChangedFilter); - cnote << "Additional transaction ready: Restarting mining operation."; + if (isMining()) + cnote << "Additional transaction ready: Restarting mining operation."; rsm = true; } } - if (!m_extHost.lock() && rsm) + if (rsm) { ReadGuard l(x_miners); for (auto& m: m_miners) diff --git a/libethereum/Client.h b/libethereum/Client.h index 8bdb48051..d00bf53ba 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ namespace eth { class Client; +class DownloadMan; enum ClientWorkState { @@ -108,14 +110,11 @@ struct WorkChannel: public LogChannel { static const char* name() { return "-W-" /** * @brief Main API hub for interfacing with Ethereum. */ -class Client: public MinerHost, public Interface +class Client: public MinerHost, public Interface, Worker { friend class Miner; public: - /// Original Constructor. - explicit Client(std::string const& _clientVersion, Address _us = Address(), std::string const& _dbPath = std::string(), bool _forceClean = false); - /// New-style Constructor. explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0); @@ -165,6 +164,9 @@ public: // [EXTRA API]: + /// @returns the length of the chain. + virtual unsigned number() const { return m_bc.number(); } + /// Get a map containing each of the pending transactions. /// @TODO: Remove in favour of transactions(). Transactions pending() const { return m_postMine.pending(); } @@ -192,32 +194,6 @@ public: /// Get the object representing the current canonical blockchain. BlockChain const& blockChain() const { return m_bc; } - // Misc stuff: - - void setClientVersion(std::string const& _name) { m_clientVersion = _name; } - - // Network stuff: - - /// Get information on the current peer set. - std::vector peers(); - /// Same as peers().size(), but more efficient. - size_t peerCount() const; - /// Same as peers().size(), but more efficient. - void setIdealPeerCount(size_t _n) const; - - /// Start the network subsystem. - void startNetwork(unsigned short _listenPort = 30303, std::string const& _remoteHost = std::string(), unsigned short _remotePort = 30303, NodeMode _mode = NodeMode::Full, unsigned _peers = 5, std::string const& _publicIP = std::string(), bool _upnp = true, u256 _networkId = 0); - /// Connect to a particular peer. - void connect(std::string const& _seedHost, unsigned short _port = 30303); - /// Stop the network subsystem. - void stopNetwork(); - /// Is the network subsystem up? - bool haveNetwork() { ReadGuard l(x_net); return !!m_net; } - /// Save peers - bytes savePeers(); - /// Restore peers - void restorePeers(bytesConstRef _saved); - // Mining stuff: /// Check block validity prior to mining. @@ -243,7 +219,7 @@ public: unsigned miningThreads() const { ReadGuard l(x_miners); return m_miners.size(); } /// Start mining. /// NOT thread-safe - call it & stopMining only from a single thread - void startMining() { ensureWorking(); ReadGuard l(x_miners); for (auto& m: m_miners) m.start(); } + void startMining() { startWorking(); ReadGuard l(x_miners); for (auto& m: m_miners) m.start(); } /// Stop mining. /// NOT thread-safe void stopMining() { ReadGuard l(x_miners); for (auto& m: m_miners) m.stop(); } @@ -254,19 +230,22 @@ public: /// Get and clear the mining history. std::list miningHistory(); + // Debug stuff: + + DownloadMan const* downloadMan() const; + bool isSyncing() const; + /// Sets the network id. + void setNetworkId(u256 _n); /// Clears pending transactions. Just for debug use. void clearPending(); + /// Kills the blockchain. Just for debug use. + void killChain(); private: - /// Ensure the worker thread is running. Needed for blockchain maintenance & mining. - void ensureWorking(); - /// Do some work. Handles blockchain maintenance and mining. - /// @param _justQueue If true will only processing the transaction queues. - void work(); + virtual void doWork(); - /// Do some work on the network. - void workNet(); + virtual void doneWorking(); /// Overrides for being a mining host. virtual void setupState(State& _s); @@ -291,26 +270,17 @@ private: State asOf(int _h) const; State asOf(unsigned _h) const; - std::string m_clientVersion; ///< Our end-application client's name/version. VersionChecker m_vc; ///< Dummy object to check & update the protocol version. BlockChain m_bc; ///< Maintains block database. TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). - // TODO: remove in favour of copying m_stateDB as required and thread-safing/copying State. Have a good think about what state objects there should be. Probably want 4 (pre, post, mining, user-visible). + mutable boost::shared_mutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine. OverlayDB m_stateDB; ///< Acts as the central point for the state database, so multiple States can share it. State m_preMine; ///< The present state of the client. State m_postMine; ///< The state of the client which we're mining (i.e. it'll have all the rewards added). - std::unique_ptr m_workNet; ///< The network thread. - std::atomic m_workNetState; - mutable boost::shared_mutex x_net; ///< Lock for the network existance. - std::unique_ptr m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required. - - std::weak_ptr m_extHost; ///< Our Ethereum Host. Don't do anything if we can't lock. - - std::unique_ptr m_work; ///< The work thread. - std::atomic m_workState; + std::weak_ptr m_host; ///< Our Ethereum Host. Don't do anything if we can't lock. std::vector m_miners; mutable boost::shared_mutex x_miners; diff --git a/libethereum/CommonNet.h b/libethereum/CommonNet.h index 3bb45b55d..c53b644e4 100644 --- a/libethereum/CommonNet.h +++ b/libethereum/CommonNet.h @@ -33,11 +33,17 @@ namespace dev namespace eth { +#if ETH_DEBUG +static const unsigned c_maxHashes = 64; ///< Maximum number of hashes BlockHashes will ever send. +static const unsigned c_maxHashesAsk = 64; ///< Maximum number of hashes GetBlockHashes will ever ask for. +static const unsigned c_maxBlocks = 32; ///< Maximum number of blocks Blocks will ever send. +static const unsigned c_maxBlocksAsk = 32; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain). +#else static const unsigned c_maxHashes = 256; ///< Maximum number of hashes BlockHashes will ever send. static const unsigned c_maxHashesAsk = 256; ///< Maximum number of hashes GetBlockHashes will ever ask for. static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send. static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain). - +#endif class OverlayDB; class BlockChain; class TransactionQueue; @@ -55,5 +61,14 @@ enum EthereumPacket BlocksPacket, }; +enum class Grabbing +{ + State, + Hashes, + Chain, + ChainHelper, + Nothing +}; + } } diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp new file mode 100644 index 000000000..09a3bcc00 --- /dev/null +++ b/libethereum/DownloadMan.cpp @@ -0,0 +1,75 @@ +/* + 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 . +*/ +/** @file DownloadMan.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "DownloadMan.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man) +{ + WriteGuard l(m_man->x_subs); + m_man->m_subs.insert(this); +} + +DownloadSub::~DownloadSub() +{ + if (m_man) + { + WriteGuard l(m_man->x_subs); + m_man->m_subs.erase(this); + } +} + +h256Set DownloadSub::nextFetch(unsigned _n) +{ + Guard l(m_fetch); + + if (m_remaining.size()) + return m_remaining; + + m_asked.clear(); + m_indices.clear(); + m_remaining.clear(); + + if (!m_man) + return h256Set(); + + m_asked = (~(m_man->taken() + m_attempted)).lowest(_n); + if (m_asked.empty()) + m_asked = (~(m_man->taken(true) + m_attempted)).lowest(_n); + m_attempted += m_asked; + for (auto i: m_asked) + { + auto x = m_man->m_chain[i]; + m_remaining.insert(x); + m_indices[x] = i; + } + return m_remaining; +} + +void DownloadSub::noteBlock(h256 _hash) +{ + Guard l(m_fetch); + if (m_man && m_indices.count(_hash)) + m_man->m_blocksGot += m_indices[_hash]; + m_remaining.erase(_hash); +} diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h new file mode 100644 index 000000000..e67076d5a --- /dev/null +++ b/libethereum/DownloadMan.h @@ -0,0 +1,136 @@ +/* + 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 . +*/ +/** @file DownloadMan.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace dev +{ + +namespace eth +{ + +class DownloadMan; + +class DownloadSub +{ + friend class DownloadMan; + +public: + DownloadSub(DownloadMan& _man); + ~DownloadSub(); + + /// Finished last fetch - grab the next bunch of block hashes to download. + h256Set nextFetch(unsigned _n); + + /// Note that we've received a particular block. + void noteBlock(h256 _hash); + + /// Nothing doing here. + void doneFetch() { resetFetch(); } + + RangeMask const& asked() const { return m_asked; } + RangeMask const& attemped() const { return m_attempted; } + +private: + void resetFetch() // Called by DownloadMan when we need to reset the download. + { + Guard l(m_fetch); + m_remaining.clear(); + m_indices.clear(); + m_asked.clear(); + m_attempted.clear(); + } + + DownloadMan* m_man = nullptr; + + Mutex m_fetch; + h256Set m_remaining; + std::map m_indices; + RangeMask m_asked; + RangeMask m_attempted; +}; + +class DownloadMan +{ + friend class DownloadSub; + +public: + ~DownloadMan() + { + for (auto i: m_subs) + i->m_man = nullptr; + } + + void resetToChain(h256s const& _chain) + { + { + ReadGuard l(x_subs); + for (auto i: m_subs) + i->resetFetch(); + } + m_chain.clear(); + m_chain.reserve(_chain.size()); + for (auto i = _chain.rbegin(); i != _chain.rend(); ++i) + m_chain.push_back(*i); + m_blocksGot = RangeMask(0, m_chain.size()); + } + + RangeMask taken(bool _desperate = false) const + { + auto ret = m_blocksGot; + if (!_desperate) + { + ReadGuard l(x_subs); + for (auto i: m_subs) + ret += i->m_asked; + } + return ret; + } + + bool isComplete() const + { + return m_blocksGot.full(); + } + + h256s chain() const { return m_chain; } + void foreachSub(std::function const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); } + unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); } + RangeMask blocksGot() const { return m_blocksGot; } + +private: + h256s m_chain; + RangeMask m_blocksGot; + + mutable SharedMutex x_subs; + std::set m_subs; +}; + +} + +} diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 7d3bd9a92..f9fe45eb0 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -15,9 +15,7 @@ along with cpp-ethereum. If not, see . */ /** @file EthereumHost.cpp - * @authors: - * Gav Wood - * Eric Lombrozo + * @author Gav Wood * @date 2014 */ @@ -34,16 +32,21 @@ #include "TransactionQueue.h" #include "BlockQueue.h" #include "EthereumPeer.h" +#include "DownloadMan.h" using namespace std; using namespace dev; using namespace dev::eth; using namespace p2p; -EthereumHost::EthereumHost(BlockChain const& _ch, u256 _networkId): +EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): HostCapability(), - m_chain (&_ch), + Worker ("ethsync"), + m_chain (_ch), + m_tq (_tq), + m_bq (_bq), m_networkId (_networkId) { + m_latestBlockSent = _ch.currentHash(); } EthereumHost::~EthereumHost() @@ -52,36 +55,12 @@ EthereumHost::~EthereumHost() i->cap()->giveUpOnFetch(); } -h256Set EthereumHost::neededBlocks(h256Set const& _exclude) -{ - Guard l(x_blocksNeeded); - h256Set ret; - if (m_blocksNeeded.size()) - { - int s = m_blocksNeeded.size() - 1; - for (; ret.size() < c_maxBlocksAsk && s < (int)m_blocksNeeded.size() && s >= 0; --s) - if (!_exclude.count(m_blocksNeeded[s])) - { - auto it = m_blocksNeeded.begin() + s; - ret.insert(*it); - m_blocksOnWay.insert(*it); - m_blocksNeeded.erase(it); - } - } - if (!ret.size()) - for (auto i = m_blocksOnWay.begin(); ret.size() < c_maxBlocksAsk && i != m_blocksOnWay.end() && !_exclude.count(*i); ++i) - ret.insert(*i); - - clog(NetMessageSummary) << "Asking for" << ret.size() << "blocks that we don't yet have." << m_blocksNeeded.size() << "blocks still needed," << m_blocksOnWay.size() << "blocks on way."; - return ret; -} - bool EthereumHost::ensureInitialised(TransactionQueue& _tq) { - if (m_latestBlockSent == h256()) + if (!m_latestBlockSent) { // First time - just initialise. - m_latestBlockSent = m_chain->currentHash(); + m_latestBlockSent = m_chain.currentHash(); clog(NetNote) << "Initialising: latest=" << m_latestBlockSent.abridged(); for (auto const& i: _tq.transactions()) @@ -91,25 +70,98 @@ bool EthereumHost::ensureInitialised(TransactionQueue& _tq) return false; } -void EthereumHost::noteDoneBlocks() +void EthereumHost::noteHavePeerState(EthereumPeer* _who) +{ + clog(NetAllDetail) << "Have peer state."; + + // if already downloading hash-chain, ignore. + if (m_grabbing != Grabbing::Nothing) + { + clog(NetAllDetail) << "Already downloading chain. Just set to help out."; + _who->ensureGettingChain(); + return; + } + + // otherwise check to see if we should be downloading... + _who->tryGrabbingHashChain(); +} + +void EthereumHost::updateGrabbing(Grabbing _g) +{ + m_grabbing = _g; + if (_g == Grabbing::Nothing) + readyForSync(); + else if (_g == Grabbing::Chain) + for (auto j: peers()) + j->cap()->ensureGettingChain(); +} + +void EthereumHost::noteHaveChain(EthereumPeer* _from) +{ + auto td = _from->m_totalDifficulty; + + if (_from->m_neededBlocks.empty()) + { + _from->m_grabbing = Grabbing::Nothing; + updateGrabbing(Grabbing::Nothing); + return; + } + + clog(NetNote) << "Hash-chain COMPLETE:" << _from->m_totalDifficulty << "vs" << m_chain.details().totalDifficulty << ";" << _from->m_neededBlocks.size() << " blocks, ends" << _from->m_neededBlocks.back().abridged(); + + if (td < m_chain.details().totalDifficulty || (td == m_chain.details().totalDifficulty && m_chain.currentHash() == _from->m_latestHash)) + { + clog(NetNote) << "Difficulty of hashchain not HIGHER. Ignoring."; + _from->m_grabbing = Grabbing::Nothing; + updateGrabbing(Grabbing::Nothing); + return; + } + + clog(NetNote) << "Difficulty of hashchain HIGHER. Replacing fetch queue [latest now" << _from->m_latestHash.abridged() << ", was" << m_latestBlockSent.abridged() << "]"; + + // Looks like it's the best yet for total difficulty. Set to download. + m_man.resetToChain(_from->m_neededBlocks); + m_latestBlockSent = _from->m_latestHash; + + _from->m_grabbing = Grabbing::Chain; + updateGrabbing(Grabbing::Chain); +} + +void EthereumHost::readyForSync() +{ + // start grabbing next hash chain if there is one. + for (auto j: peers()) + { + j->cap()->tryGrabbingHashChain(); + if (j->cap()->m_grabbing == Grabbing::Hashes) + { + m_grabbing = Grabbing::Hashes; + return; + } + } + clog(NetNote) << "No more peers to sync with."; +} + +void EthereumHost::noteDoneBlocks(EthereumPeer* _who) { - clog(NetNote) << "Peer given up on blocks fetch."; - if (m_blocksOnWay.empty()) + if (m_man.isComplete()) + { + // Done our chain-get. + clog(NetNote) << "Chain download complete."; + updateGrabbing(Grabbing::Nothing); + } + if (_who->m_grabbing == Grabbing::Chain) { // Done our chain-get. - if (m_blocksNeeded.size()) - clog(NetNote) << "No more blocks coming. Missing" << m_blocksNeeded.size() << "blocks."; - else - clog(NetNote) << "No more blocks to get."; - m_latestBlockSent = m_chain->currentHash(); + clog(NetNote) << "Chain download failed. Peer with blocks didn't have them all. This peer is bad and should be punished."; + // TODO: note that peer is BADBADBAD! + updateGrabbing(Grabbing::Nothing); } } bool EthereumHost::noteBlock(h256 _hash, bytesConstRef _data) { - Guard l(x_blocksNeeded); - m_blocksOnWay.erase(_hash); - if (!m_chain->details(_hash)) + if (!m_chain.details(_hash)) { lock_guard l(m_incomingLock); m_incomingBlocks.push_back(_data.toBytes()); @@ -118,81 +170,96 @@ bool EthereumHost::noteBlock(h256 _hash, bytesConstRef _data) return false; } -bool EthereumHost::sync(TransactionQueue& _tq, BlockQueue& _bq) +void EthereumHost::doWork() { - bool netChange = ensureInitialised(_tq); - auto h = m_chain->currentHash(); - maintainTransactions(_tq, h); - maintainBlocks(_bq, h); - return netChange; + bool netChange = ensureInitialised(m_tq); + auto h = m_chain.currentHash(); + maintainTransactions(m_tq, h); + maintainBlocks(m_bq, h); +// return netChange; + // TODO: Figure out what to do with netChange. + (void)netChange; } void EthereumHost::maintainTransactions(TransactionQueue& _tq, h256 _currentHash) { - bool resendAll = (_currentHash != m_latestBlockSent); - - for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it) - if (_tq.import(&*it)) - {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce... - else - m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on. - m_incomingTransactions.clear(); + bool resendAll = (m_grabbing == Grabbing::Nothing && m_chain.isKnown(m_latestBlockSent) && _currentHash != m_latestBlockSent); + { + lock_guard l(m_incomingLock); + for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it) + if (_tq.import(&*it)) + {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce... + else + m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on. + m_incomingTransactions.clear(); + } // Send any new transactions. for (auto const& p: peers()) { auto ep = p->cap(); - bytes b; - unsigned n = 0; - for (auto const& i: _tq.transactions()) - if ((!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first)) || ep->m_requireTransactions || resendAll) + if (ep) + { + bytes b; + unsigned n = 0; + for (auto const& i: _tq.transactions()) + if ((!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first)) || ep->m_requireTransactions || resendAll) + { + b += i.second; + ++n; + m_transactionsSent.insert(i.first); + } + ep->clearKnownTransactions(); + + if (n) { - b += i.second; - ++n; - m_transactionsSent.insert(i.first); + RLPStream ts; + EthereumPeer::prep(ts); + ts.appendList(n + 1) << TransactionsPacket; + ts.appendRaw(b, n).swapOut(b); + seal(b); + ep->send(&b); } - if (n) - { - RLPStream ts; - EthereumPeer::prep(ts); - ts.appendList(n + 1) << TransactionsPacket; - ts.appendRaw(b, n).swapOut(b); - seal(b); - ep->send(&b); + ep->m_requireTransactions = false; } - ep->m_knownTransactions.clear(); - ep->m_requireTransactions = false; } } +void EthereumHost::reset() +{ + m_grabbing = Grabbing::Nothing; + + m_man.resetToChain(h256s()); + + m_incomingTransactions.clear(); + m_incomingBlocks.clear(); + + m_latestBlockSent = h256(); + m_transactionsSent.clear(); +} + void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash) { // Import new blocks { lock_guard l(m_incomingLock); for (auto it = m_incomingBlocks.rbegin(); it != m_incomingBlocks.rend(); ++it) - if (_bq.import(&*it, *m_chain)) + if (_bq.import(&*it, m_chain)) {} else{} // TODO: don't forward it. m_incomingBlocks.clear(); } - // If we've finished our initial sync... - { - Guard l(x_blocksNeeded); - if (m_blocksOnWay.size()) - return; - } - // ...send any new blocks. - if (m_latestBlockSent != _currentHash) + // If we've finished our initial sync send any new blocks. + if (m_grabbing == Grabbing::Nothing && m_chain.isKnown(m_latestBlockSent) && m_chain.details(m_latestBlockSent).totalDifficulty < m_chain.details(_currentHash).totalDifficulty) { RLPStream ts; EthereumPeer::prep(ts); bytes bs; unsigned c = 0; - for (auto h: m_chain->treeRoute(m_latestBlockSent, _currentHash, nullptr, false, true)) + for (auto h: m_chain.treeRoute(m_latestBlockSent, _currentHash, nullptr, false, true)) { - bs += m_chain->block(h); + bs += m_chain.block(h); ++c; } clog(NetMessageSummary) << "Sending" << c << "new blocks (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; @@ -204,6 +271,7 @@ void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash) for (auto j: peers()) { auto p = j->cap(); + Guard l(p->x_knownBlocks); if (!p->m_knownBlocks.count(_currentHash)) p->send(&b); p->m_knownBlocks.clear(); @@ -211,32 +279,3 @@ void EthereumHost::maintainBlocks(BlockQueue& _bq, h256 _currentHash) m_latestBlockSent = _currentHash; } } - -void EthereumHost::noteHaveChain(EthereumPeer* _from) -{ - auto td = _from->m_totalDifficulty; - - if (_from->m_neededBlocks.empty()) - return; - - clog(NetNote) << "Hash-chain COMPLETE:" << _from->m_totalDifficulty << "vs" << m_chain->details().totalDifficulty << "," << m_totalDifficultyOfNeeded << ";" << _from->m_neededBlocks.size() << " blocks, ends" << _from->m_neededBlocks.back().abridged(); - - if ((m_totalDifficultyOfNeeded && td < m_totalDifficultyOfNeeded) || td < m_chain->details().totalDifficulty) - { - clog(NetNote) << "Difficulty of hashchain LOWER. Ignoring."; - return; - } - - clog(NetNote) << "Difficulty of hashchain HIGHER. Replacing fetch queue."; - - // Looks like it's the best yet for total difficulty. Set to download. - { - Guard l(x_blocksNeeded); - m_blocksNeeded = _from->m_neededBlocks; - m_blocksOnWay.clear(); - m_totalDifficultyOfNeeded = td; - } - - for (auto j: peers()) - j->cap()->restartGettingChain(); -} diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index bd0a5d0bc..07ef92513 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -29,10 +29,13 @@ #include #include #include +#include +#include #include #include #include "CommonNet.h" #include "EthereumPeer.h" +#include "DownloadMan.h" namespace dev { @@ -49,31 +52,41 @@ class BlockQueue; * @brief The EthereumHost class * @warning None of this is thread-safe. You have been warned. */ -class EthereumHost: public p2p::HostCapability +class EthereumHost: public p2p::HostCapability, Worker { friend class EthereumPeer; public: /// Start server, but don't listen. - EthereumHost(BlockChain const& _ch, u256 _networkId); + EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId); /// Will block on network process events. virtual ~EthereumHost(); unsigned protocolVersion() const { return c_protocolVersion; } u256 networkId() const { return m_networkId; } + void setNetworkId(u256 _n) { m_networkId = _n; } - /// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network. - bool sync(TransactionQueue&, BlockQueue& _bc); + void reset(); + + DownloadMan const& downloadMan() const { return m_man; } + bool isSyncing() const { return m_grabbing == Grabbing::Chain; } private: + void noteHavePeerState(EthereumPeer* _who); /// Session wants to pass us a block that we might not have. /// @returns true if we didn't have it. bool noteBlock(h256 _hash, bytesConstRef _data); /// Session has finished getting the chain of hashes. void noteHaveChain(EthereumPeer* _who); /// Called when the peer can no longer provide us with any needed blocks. - void noteDoneBlocks(); + void noteDoneBlocks(EthereumPeer* _who); + + /// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network. + void doWork(); + + /// Called by peer to add incoming transactions. + void addIncomingTransaction(bytes const& _bytes) { std::lock_guard l(m_incomingLock); m_incomingTransactions.push_back(_bytes); } void maintainTransactions(TransactionQueue& _tq, h256 _currentBlock); void maintainBlocks(BlockQueue& _bq, h256 _currentBlock); @@ -84,26 +97,33 @@ private: h256Set neededBlocks(h256Set const& _exclude); /// Check to see if the network peer-state initialisation has happened. - virtual bool isInitialised() const { return m_latestBlockSent; } + bool isInitialised() const { return m_latestBlockSent; } /// Initialises the network peer-state, doing the stuff that needs to be once-only. @returns true if it really was first. bool ensureInitialised(TransactionQueue& _tq); - BlockChain const* m_chain = nullptr; + virtual void onStarting() { startWorking(); } + virtual void onStopping() { stopWorking(); } + + void readyForSync(); + void updateGrabbing(Grabbing _g); + + BlockChain const& m_chain; + TransactionQueue& m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. + BlockQueue& m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). u256 m_networkId; + Grabbing m_grabbing = Grabbing::Nothing; // TODO: needs to be thread-safe & switch to just having a peer id. + mutable std::recursive_mutex m_incomingLock; std::vector m_incomingTransactions; std::vector m_incomingBlocks; - mutable std::mutex x_blocksNeeded; - u256 m_totalDifficultyOfNeeded; - h256s m_blocksNeeded; - h256Set m_blocksOnWay; + DownloadMan m_man; h256 m_latestBlockSent; - std::set m_transactionsSent; + h256Set m_transactionsSent; }; } diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 9e72f8429..7608afc2a 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -35,7 +35,8 @@ using namespace p2p; #define clogS(X) dev::LogOutputStream(false) << "| " << std::setw(2) << session()->socketId() << "] " EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h): - Capability(_s, _h) + Capability(_s, _h), + m_sub(host()->m_man) { sendStatus(); } @@ -57,15 +58,15 @@ void EthereumPeer::sendStatus() s.appendList(6) << StatusPacket << host()->protocolVersion() << host()->networkId() - << host()->m_chain->details().totalDifficulty - << host()->m_chain->currentHash() - << host()->m_chain->genesisHash(); + << host()->m_chain.details().totalDifficulty + << host()->m_chain.currentHash() + << host()->m_chain.genesisHash(); sealAndSend(s); } void EthereumPeer::startInitialSync() { - // Grab trsansactions off them. + // Grab transactions off them. { RLPStream s; prep(s).appendList(1); @@ -73,16 +74,36 @@ void EthereumPeer::startInitialSync() sealAndSend(s); } - h256 c = host()->m_chain->currentHash(); - unsigned n = host()->m_chain->number(); - u256 td = max(host()->m_chain->details().totalDifficulty, host()->m_totalDifficultyOfNeeded); + host()->noteHavePeerState(this); +} - clogS(NetAllDetail) << "Initial sync. Latest:" << c.abridged() << ", number:" << n << ", TD: max(" << host()->m_chain->details().totalDifficulty << "," << host()->m_totalDifficultyOfNeeded << ") versus " << m_totalDifficulty; - if (td > m_totalDifficulty) +void EthereumPeer::tryGrabbingHashChain() +{ + // if already done this, then ignore. + if (m_grabbing != Grabbing::State) + { + clogS(NetAllDetail) << "Already synced with this peer."; + return; + } + + h256 c = host()->m_chain.currentHash(); + unsigned n = host()->m_chain.number(); + u256 td = host()->m_chain.details().totalDifficulty; + + clogS(NetAllDetail) << "Attempt chain-grab? Latest:" << c.abridged() << ", number:" << n << ", TD:" << td << " versus " << m_totalDifficulty; + if (td >= m_totalDifficulty) + { + clogS(NetAllDetail) << "No. Our chain is better."; + m_grabbing = Grabbing::Nothing; return; // All good - we have the better chain. + } // Our chain isn't better - grab theirs. { + clogS(NetAllDetail) << "Yes. Their chain is better."; + + host()->updateGrabbing(Grabbing::Hashes); + m_grabbing = Grabbing::Hashes; RLPStream s; prep(s).appendList(3); s << GetBlockHashesPacket << m_latestHash << c_maxHashesAsk; @@ -93,19 +114,17 @@ void EthereumPeer::startInitialSync() void EthereumPeer::giveUpOnFetch() { - clogS(NetNote) << "GIVE UP FETCH; can't get" << toString(m_askedBlocks); - if (m_askedBlocks.size()) + clogS(NetNote) << "GIVE UP FETCH"; + + // a bit overkill given that the other nodes may yet have the needed blocks, but better to be safe than sorry. + if (m_grabbing == Grabbing::Chain || m_grabbing == Grabbing::ChainHelper) { - Guard l (host()->x_blocksNeeded); - host()->m_blocksNeeded.reserve(host()->m_blocksNeeded.size() + m_askedBlocks.size()); - for (auto i: m_askedBlocks) - { - m_failedBlocks.insert(i); - host()->m_blocksOnWay.erase(i); - host()->m_blocksNeeded.push_back(i); - } - m_askedBlocks.clear(); + host()->noteDoneBlocks(this); + m_grabbing = Grabbing::Nothing; } + + m_sub.doneFetch(); + // NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary. } bool EthereumPeer::interpret(RLP const& _r) @@ -122,7 +141,7 @@ bool EthereumPeer::interpret(RLP const& _r) clogS(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << genesisHash.abridged() << ", TD:" << m_totalDifficulty << "=" << m_latestHash.abridged(); - if (genesisHash != host()->m_chain->genesisHash()) + if (genesisHash != host()->m_chain.genesisHash()) disable("Invalid genesis hash"); if (m_protocolVersion != host()->protocolVersion()) disable("Invalid protocol version."); @@ -138,33 +157,44 @@ bool EthereumPeer::interpret(RLP const& _r) break; } case TransactionsPacket: + { clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << "entries)"; addRating(_r.itemCount() - 1); + lock_guard l(host()->m_incomingLock); for (unsigned i = 1; i < _r.itemCount(); ++i) { - host()->m_incomingTransactions.push_back(_r[i].data().toBytes()); + host()->addIncomingTransaction(_r[i].data().toBytes()); + + lock_guard l(x_knownTransactions); m_knownTransactions.insert(sha3(_r[i].data())); } break; + } case GetBlockHashesPacket: { h256 later = _r[1].toHash(); unsigned limit = _r[2].toInt(); clogS(NetMessageSummary) << "GetBlockHashes (" << limit << "entries," << later.abridged() << ")"; - unsigned c = min(host()->m_chain->number(later), limit); + unsigned c = min(max(1, host()->m_chain.number(later)) - 1, limit); RLPStream s; prep(s).appendList(1 + c).append(BlockHashesPacket); - h256 p = host()->m_chain->details(later).parent; - for (unsigned i = 0; i < c; ++i, p = host()->m_chain->details(p).parent) + h256 p = host()->m_chain.details(later).parent; + for (unsigned i = 0; i < c; ++i, p = host()->m_chain.details(p).parent) s << p; sealAndSend(s); break; } case BlockHashesPacket: { - clogS(NetMessageSummary) << "BlockHashes (" << dec << (_r.itemCount() - 1) << "entries)"; + clogS(NetMessageSummary) << "BlockHashes (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreHashes"); + + if (m_grabbing != Grabbing::Hashes) + { + cwarn << "Peer giving us hashes when we didn't ask for them."; + break; + } if (_r.itemCount() == 1) { host()->noteHaveChain(this); @@ -173,7 +203,7 @@ bool EthereumPeer::interpret(RLP const& _r) for (unsigned i = 1; i < _r.itemCount(); ++i) { auto h = _r[i].toHash(); - if (host()->m_chain->details(h)) + if (host()->m_chain.details(h)) { host()->noteHaveChain(this); return true; @@ -191,12 +221,12 @@ bool EthereumPeer::interpret(RLP const& _r) case GetBlocksPacket: { clogS(NetMessageSummary) << "GetBlocks (" << dec << (_r.itemCount() - 1) << "entries)"; - // TODO: return the requested blocks. + // return the requested blocks. bytes rlp; unsigned n = 0; for (unsigned i = 1; i < _r.itemCount() && i <= c_maxBlocks; ++i) { - auto b = host()->m_chain->block(_r[i].toHash()); + auto b = host()->m_chain.block(_r[i].toHash()); if (b.size()) { rlp += b; @@ -209,22 +239,23 @@ bool EthereumPeer::interpret(RLP const& _r) } case BlocksPacket: { - clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << "entries)"; + clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreBlocks"); - if (_r.itemCount() == 1 && !m_askedBlocksChanged) + if (_r.itemCount() == 1) { // Couldn't get any from last batch - probably got to this peer's latest block - just give up. + m_sub.doneFetch(); giveUpOnFetch(); } - m_askedBlocksChanged = false; unsigned used = 0; for (unsigned i = 1; i < _r.itemCount(); ++i) { auto h = BlockInfo::headerHash(_r[i].data()); + m_sub.noteBlock(h); if (host()->noteBlock(h, _r[i].data())) used++; - m_askedBlocks.erase(h); + Guard l(x_knownBlocks); m_knownBlocks.insert(h); } addRating(used); @@ -236,15 +267,16 @@ bool EthereumPeer::interpret(RLP const& _r) { auto h = BlockInfo::headerHash(_r[i].data()); BlockInfo bi(_r[i].data()); - if (!host()->m_chain->details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash)) + Guard l(x_knownBlocks); + if (!host()->m_chain.details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash)) { unknownParents++; - clogS(NetAllDetail) << "Unknown parent" << bi.parentHash << "of block" << h; + clogS(NetAllDetail) << "Unknown parent" << bi.parentHash.abridged() << "of block" << h.abridged(); } else { knownParents++; - clogS(NetAllDetail) << "Known parent" << bi.parentHash << "of block" << h; + clogS(NetAllDetail) << "Known parent" << bi.parentHash.abridged() << "of block" << h.abridged(); } } } @@ -258,21 +290,9 @@ bool EthereumPeer::interpret(RLP const& _r) return true; } -void EthereumPeer::restartGettingChain() -{ - if (m_askedBlocks.size()) - { - m_askedBlocksChanged = true; // So that we continue even if the Ask's reply is empty. - m_askedBlocks.clear(); // So that we restart once we get the Ask's reply. - m_failedBlocks.clear(); - } - else - ensureGettingChain(); -} - void EthereumPeer::ensureGettingChain() { - if (m_askedBlocks.size()) + if (m_grabbing == Grabbing::ChainHelper) return; // Already asked & waiting for some. continueGettingChain(); @@ -280,21 +300,20 @@ void EthereumPeer::ensureGettingChain() void EthereumPeer::continueGettingChain() { - if (!m_askedBlocks.size()) - m_askedBlocks = host()->neededBlocks(m_failedBlocks); + if (m_grabbing != Grabbing::Chain) + m_grabbing = Grabbing::ChainHelper; - if (m_askedBlocks.size()) + auto blocks = m_sub.nextFetch(c_maxBlocksAsk); + + if (blocks.size()) { RLPStream s; prep(s); - s.appendList(m_askedBlocks.size() + 1) << GetBlocksPacket; - for (auto i: m_askedBlocks) + s.appendList(blocks.size() + 1) << GetBlocksPacket; + for (auto const& i: blocks) s << i; sealAndSend(s); } else - { - clogS(NetMessageSummary) << "No blocks left to get. Peer doesn't seem to have" << m_failedBlocks.size() << "of our needed blocks."; - host()->noteDoneBlocks(); - } + giveUpOnFetch(); } diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 2e166b1d0..f88a757d8 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -27,9 +27,12 @@ #include #include #include +#include +#include #include #include #include "CommonNet.h" +#include "DownloadMan.h" namespace dev { @@ -58,30 +61,34 @@ private: void sendStatus(); void startInitialSync(); + void tryGrabbingHashChain(); + /// Ensure that we are waiting for a bunch of blocks from our peer. void ensureGettingChain(); /// Ensure that we are waiting for a bunch of blocks from our peer. void continueGettingChain(); - /// Now getting a different chain so we need to make sure we restart. - void restartGettingChain(); void giveUpOnFetch(); + void clearKnownTransactions() { std::lock_guard l(x_knownTransactions); m_knownTransactions.clear(); } + unsigned m_protocolVersion; u256 m_networkId; + Grabbing m_grabbing = Grabbing::State; + h256 m_latestHash; ///< Peer's latest block's hash. u256 m_totalDifficulty; ///< Peer's latest block's total difficulty. h256s m_neededBlocks; ///< The blocks that we should download from this peer. - h256Set m_failedBlocks; ///< Blocks that the peer doesn't seem to have. - - h256Set m_askedBlocks; ///< The blocks for which we sent the last GetBlocks for but haven't received a corresponding Blocks. - bool m_askedBlocksChanged = true; bool m_requireTransactions; + Mutex x_knownBlocks; std::set m_knownBlocks; std::set m_knownTransactions; + std::mutex x_knownTransactions; + + DownloadSub m_sub; }; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index e8c1fd1cb..a6b57a05c 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -187,6 +187,7 @@ bool Executive::go(OnOpFunc const& _onOp) catch (VMException const& _e) { clog(StateChat) << "VM Exception: " << _e.description(); + m_endGas = m_vm->gas(); } catch (Exception const& _e) { diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 3fa93a286..a5df3e5b1 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -95,8 +95,13 @@ public: virtual bool peekWatch(unsigned _watchId) const = 0; virtual bool checkWatch(unsigned _watchId) = 0; + // TODO: Block query API. + // [EXTRA API]: + /// @returns The height of the chain. + virtual unsigned number() const = 0; + /// Get a map containing each of the pending transactions. /// @TODO: Remove in favour of transactions(). virtual Transactions pending() const = 0; diff --git a/libethereum/Miner.cpp b/libethereum/Miner.cpp index c602cedc1..9b651e2c5 100644 --- a/libethereum/Miner.cpp +++ b/libethereum/Miner.cpp @@ -27,42 +27,12 @@ using namespace dev; using namespace dev::eth; Miner::Miner(MinerHost* _host, unsigned _id): - m_host(_host), - m_id(_id) + Worker("miner-" + toString(_id)), + m_host(_host) { } -void Miner::start() -{ - if (!m_host) - return; - - Guard l(x_work); - if (!m_work) - { - m_stop = false; - m_work.reset(new thread([&]() - { - setThreadName(("miner-" + toString(m_id)).c_str()); - m_miningStatus = Preparing; - while (!m_stop) - work(); - })); - } -} - -void Miner::stop() -{ - Guard l(x_work); - if (m_work) - { - m_stop = true; - m_work->join(); - m_work.reset(nullptr); - } -} - -void Miner::work() +void Miner::doWork() { // Do some mining. if (m_miningStatus != Waiting && m_miningStatus != Mined) diff --git a/libethereum/Miner.h b/libethereum/Miner.h index 8912b0e2a..763249b7d 100644 --- a/libethereum/Miner.h +++ b/libethereum/Miner.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "State.h" @@ -74,38 +75,38 @@ public: * @threadsafe * @todo Signal Miner to restart once with condition variables. */ -class Miner +class Miner: Worker { public: /// Null constructor. - Miner(): m_host(nullptr), m_id(0) {} + Miner(): m_host(nullptr) {} /// Constructor. Miner(MinerHost* _host, unsigned _id = 0); /// Move-constructor. - Miner(Miner&& _m) { std::swap(m_host, _m.m_host); std::swap(m_id, _m.m_id); } + Miner(Miner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); } /// Move-assignment. - Miner& operator=(Miner&& _m) { std::swap(m_host, _m.m_host); std::swap(m_id, _m.m_id); return *this; } + Miner& operator=(Miner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); return *this; } /// Destructor. Stops miner. ~Miner() { stop(); } /// Setup its basics. - void setup(MinerHost* _host, unsigned _id = 0) { m_host = _host; m_id = _id; } + void setup(MinerHost* _host, unsigned _id = 0) { m_host = _host; setName("miner-" + toString(_id)); } /// Start mining. - void start(); + void start() { startWorking(); } /// Stop mining. - void stop(); + void stop() { stopWorking(); } /// Call to notify Miner of a state change. void noteStateChange() { m_miningStatus = Preparing; } /// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force(). - bool isRunning() { return !!m_work; } + bool isRunning() { return isWorking(); } /// @returns true if mining is complete. bool isComplete() const { return m_miningStatus == Mined; } @@ -121,14 +122,9 @@ public: private: /// Do some work on the mining. - void work(); + virtual void doWork(); MinerHost* m_host = nullptr; ///< Our host. - unsigned m_id = 0; ///< Our identity. - - std::mutex x_work; ///< Mutex protecting the creation of the work thread. - std::unique_ptr m_work; ///< The work thread. - bool m_stop = false; ///< Stop working? enum MiningStatus { Waiting, Preparing, Mining, Mined, Stopping, Stopped }; MiningStatus m_miningStatus = Waiting; ///< TODO: consider mutex/atomic variable. diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 093db299f..a74b6ba18 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -152,10 +152,15 @@ State& State::operator=(State const& _s) m_currentBlock = _s.m_currentBlock; m_ourAddress = _s.m_ourAddress; m_blockReward = _s.m_blockReward; + m_lastTx = _s.m_lastTx; paranoia("after state cloning (assignment op)", true); return *this; } +State::~State() +{ +} + struct CachedAddressState { CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} diff --git a/libethereum/State.h b/libethereum/State.h index 335f27168..fea8e06c7 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -90,6 +90,8 @@ public: /// Copy state object. State& operator=(State const& _s); + ~State(); + /// Set the coinbase address for any transactions we do. /// This causes a complete reset of current block. void setAddress(Address _coinbaseAddress) { m_ourAddress = _coinbaseAddress; resetCurrent(); } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 154eed9d2..22a420602 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -52,6 +52,8 @@ public: void setFuture(std::pair const& _t); void noteGood(std::pair const& _t); + void clear() { WriteGuard l(m_lock); m_known.clear(); m_current.clear(); m_unknown.clear(); } + private: mutable boost::shared_mutex m_lock; ///< General lock. std::set m_known; ///< Hashes of transactions in both sets. diff --git a/libevm/VM.h b/libevm/VM.h index e7d218ec6..cbecc3ee7 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -41,7 +41,6 @@ class BreakPointHit: public VMException {}; class BadInstruction: public VMException {}; class OutOfGas: public VMException {}; class StackTooSmall: public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; }; -class OperandOutOfRange: public VMException { public: OperandOutOfRange(u256 _min, u256 _max, u256 _got): mn(_min), mx(_max), got(_got) {} u256 mn; u256 mx; u256 got; }; // Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash. // Currently we just pull out the right (low-order in BE) 160-bits. @@ -157,7 +156,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con require(3); newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]); break; - + case Instruction::EXTCODECOPY: + require(4); + newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); + break; + case Instruction::BALANCE: runGas = c_balanceGas; break; diff --git a/libevmface/Instruction.h b/libevmface/Instruction.h index 8d4ca989a..6c87b7a76 100644 --- a/libevmface/Instruction.h +++ b/libevmface/Instruction.h @@ -32,143 +32,140 @@ namespace dev namespace eth { -// TODO: Update comments. - /// Virtual machine bytecode instruction. enum class Instruction: uint8_t { STOP = 0x00, ///< halts execution - ADD, - MUL, - SUB, - DIV, - SDIV, - MOD, - SMOD, - EXP, - NEG, - LT, - GT, - SLT, - SGT, - EQ, - NOT, - - AND = 0x10, - OR, - XOR, - BYTE, - ADDMOD, - MULMOD, - - SHA3 = 0x20, - - ADDRESS = 0x30, - BALANCE, - ORIGIN, - CALLER, - CALLVALUE, - CALLDATALOAD, - CALLDATASIZE, - CALLDATACOPY, - CODESIZE, - CODECOPY, - GASPRICE, - EXTCODESIZE, - EXTCODECOPY, - - PREVHASH = 0x40, - COINBASE, - TIMESTAMP, - NUMBER, - DIFFICULTY, - GASLIMIT, - - POP = 0x50, - MLOAD = 0x53, - MSTORE, - MSTORE8, - SLOAD, - SSTORE, - JUMP, - JUMPI, - PC, - MSIZE, - GAS, - - PUSH1 = 0x60, - PUSH2, - PUSH3, - PUSH4, - PUSH5, - PUSH6, - PUSH7, - PUSH8, - PUSH9, - PUSH10, - PUSH11, - PUSH12, - PUSH13, - PUSH14, - PUSH15, - PUSH16, - PUSH17, - PUSH18, - PUSH19, - PUSH20, - PUSH21, - PUSH22, - PUSH23, - PUSH24, - PUSH25, - PUSH26, - PUSH27, - PUSH28, - PUSH29, - PUSH30, - PUSH31, - PUSH32, - - DUP1 = 0x80, - DUP2, - DUP3, - DUP4, - DUP5, - DUP6, - DUP7, - DUP8, - DUP9, - DUP10, - DUP11, - DUP12, - DUP13, - DUP14, - DUP15, - DUP16, - - SWAP1 = 0x90, - SWAP2, - SWAP3, - SWAP4, - SWAP5, - SWAP6, - SWAP7, - SWAP8, - SWAP9, - SWAP10, - SWAP11, - SWAP12, - SWAP13, - SWAP14, - SWAP15, - SWAP16, - - CREATE = 0xf0, - CALL, - RETURN, - POST, + ADD, ///< addition operation + MUL, ///< mulitplication operation + SUB, ///< subtraction operation + DIV, ///< integer division operation + SDIV, ///< signed integer division operation + MOD, ///< modulo remainder operation + SMOD, ///< signed modulo remainder operation + EXP, ///< exponential operation + NEG, ///< negation operation + LT, ///< less-than comparision + GT, ///< greater-than comparision + SLT, ///< signed less-than comparision + SGT, ///< signed greater-than comparision + EQ, ///< equality comparision + NOT, ///< simple not operator + + AND = 0x10, ///< bitwise AND operation + OR, ///< bitwise OR operation + XOR, ///< bitwise XOR operation + BYTE, ///< retrieve single byte from word + ADDMOD, ///< unsigned modular addition + MULMOD, ///< unsigned modular multiplication + SHA3 = 0x20, ///< compute SHA3-256 hash + + ADDRESS = 0x30, ///< get address of currently executing account + BALANCE, ///< get balance of the given account + ORIGIN, ///< get execution origination address + CALLER, ///< get caller address + CALLVALUE, ///< get deposited value by the instruction/transaction responsible for this execution + CALLDATALOAD, ///< get input data of current environment + CALLDATASIZE, ///< get size of input data in current environment + CALLDATACOPY, ///< copy input data in current environment to memory + CODESIZE, ///< get size of code running in current environment + CODECOPY, ///< copy code running in current environment to memory + GASPRICE, ///< get price of gas in current environment + EXTCODESIZE, ///< get external code size (from another contract) + EXTCODECOPY, ///< copy external code (from another contract) + + PREVHASH = 0x40, ///< get hash of most recent complete block + COINBASE, ///< get the block's coinbase address + TIMESTAMP, ///< get the block's timestamp + NUMBER, ///< get the block's number + DIFFICULTY, ///< get the block's difficulty + GASLIMIT, ///< get the block's gas limit + + POP = 0x50, ///< remove item from stack + MLOAD = 0x53, ///< load word from memory + MSTORE, ///< save word to memory + MSTORE8, ///< save byte to memory + SLOAD, ///< load word from storage + SSTORE, ///< save word to storage + JUMP, ///< alter the program counter + JUMPI, ///< conditionally alter the program counter + PC, ///< get the program counter + MSIZE, ///< get the size of active memory + GAS, ///< get the amount of available gas + + PUSH1 = 0x60, ///< place 1 byte item on stack + PUSH2, ///< place 2 byte item on stack + PUSH3, ///< place 3 byte item on stack + PUSH4, ///< place 4 byte item on stack + PUSH5, ///< place 5 byte item on stack + PUSH6, ///< place 6 byte item on stack + PUSH7, ///< place 7 byte item on stack + PUSH8, ///< place 8 byte item on stack + PUSH9, ///< place 9 byte item on stack + PUSH10, ///< place 10 byte item on stack + PUSH11, ///< place 11 byte item on stack + PUSH12, ///< place 12 byte item on stack + PUSH13, ///< place 13 byte item on stack + PUSH14, ///< place 14 byte item on stack + PUSH15, ///< place 15 byte item on stack + PUSH16, ///< place 16 byte item on stack + PUSH17, ///< place 17 byte item on stack + PUSH18, ///< place 18 byte item on stack + PUSH19, ///< place 19 byte item on stack + PUSH20, ///< place 20 byte item on stack + PUSH21, ///< place 21 byte item on stack + PUSH22, ///< place 22 byte item on stack + PUSH23, ///< place 23 byte item on stack + PUSH24, ///< place 24 byte item on stack + PUSH25, ///< place 25 byte item on stack + PUSH26, ///< place 26 byte item on stack + PUSH27, ///< place 27 byte item on stack + PUSH28, ///< place 28 byte item on stack + PUSH29, ///< place 29 byte item on stack + PUSH30, ///< place 30 byte item on stack + PUSH31, ///< place 31 byte item on stack + PUSH32, ///< place 32 byte item on stack + + DUP1 = 0x80, ///< copies the highest item in the stack to the top of the stack + DUP2, ///< copies the second highest item in the stack to the top of the stack + DUP3, ///< copies the third highest item in the stack to the top of the stack + DUP4, ///< copies the 4th highest item in the stack to the top of the stack + DUP5, ///< copies the 5th highest item in the stack to the top of the stack + DUP6, ///< copies the 6th highest item in the stack to the top of the stack + DUP7, ///< copies the 7th highest item in the stack to the top of the stack + DUP8, ///< copies the 8th highest item in the stack to the top of the stack + DUP9, ///< copies the 9th highest item in the stack to the top of the stack + DUP10, ///< copies the 10th highest item in the stack to the top of the stack + DUP11, ///< copies the 11th highest item in the stack to the top of the stack + DUP12, ///< copies the 12th highest item in the stack to the top of the stack + DUP13, ///< copies the 13th highest item in the stack to the top of the stack + DUP14, ///< copies the 14th highest item in the stack to the top of the stack + DUP15, ///< copies the 15th highest item in the stack to the top of the stack + DUP16, ///< copies the 16th highest item in the stack to the top of the stack + + SWAP1 = 0x90, ///< swaps the highest and second highest value on the stack + SWAP2, ///< swaps the highest and third highest value on the stack + SWAP3, ///< swaps the highest and 4th highest value on the stack + SWAP4, ///< swaps the highest and 5th highest value on the stack + SWAP5, ///< swaps the highest and 6th highest value on the stack + SWAP6, ///< swaps the highest and 7th highest value on the stack + SWAP7, ///< swaps the highest and 8th highest value on the stack + SWAP8, ///< swaps the highest and 9th highest value on the stack + SWAP9, ///< swaps the highest and 10th highest value on the stack + SWAP10, ///< swaps the highest and 11th highest value on the stack + SWAP11, ///< swaps the highest and 12th highest value on the stack + SWAP12, ///< swaps the highest and 13th highest value on the stack + SWAP13, ///< swaps the highest and 14th highest value on the stack + SWAP14, ///< swaps the highest and 15th highest value on the stack + SWAP15, ///< swaps the highest and 16th highest value on the stack + SWAP16, ///< swaps the highest and 17th highest value on the stack + + CREATE = 0xf0, ///< create a new account with associated code + CALL, ///< message-call into an account + RETURN, ///< halt execution returning output data + POST, ///< asynchronous call without output (adds a message to the post queue) CALLSTATELESS, - SUICIDE = 0xff + SUICIDE = 0xff ///< halt execution and register account for later deletion }; /// Information structure for a particular instruction. diff --git a/libp2p/Common.h b/libp2p/Common.h index 8035f462f..a83ac03de 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -94,6 +94,7 @@ struct PeerInfo std::string host; unsigned short port; std::chrono::steady_clock::duration lastPing; + std::set caps; }; } diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index fdf1338b3..2517002ea 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -17,7 +17,7 @@ /** @file Host.cpp * @authors: * Gav Wood - * Eric Lombrozo + * Eric Lombrozo (Windows version of populateAddresses()) * @date 2014 */ @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include "Session.h" @@ -54,55 +55,89 @@ static const set c_rejectAddresses = { {bi::address_v6::from_string("::")} }; -Host::Host(std::string const& _clientVersion, unsigned short _port, string const& _publicAddress, bool _upnp, bool _localNetworking): +Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool _start): + Worker("p2p"), m_clientVersion(_clientVersion), - m_listenPort(_port), - m_localNetworking(_localNetworking), - m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), _port)), + m_netPrefs(_n), + m_acceptor(m_ioService), m_socket(m_ioService), m_id(h512::random()) { populateAddresses(); - determinePublic(_publicAddress, _upnp); - ensureAccepting(); m_lastPeersRequest = chrono::steady_clock::time_point::min(); clog(NetNote) << "Id:" << m_id.abridged(); + if (_start) + start(); } -Host::Host(std::string const& _clientVersion, string const& _publicAddress, bool _upnp, bool _localNetworking): - m_clientVersion(_clientVersion), - m_listenPort(0), - m_localNetworking(_localNetworking), - m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)), - m_socket(m_ioService), - m_id(h512::random()) +Host::~Host() { - m_listenPort = m_acceptor.local_endpoint().port(); - - // populate addresses. - populateAddresses(); - determinePublic(_publicAddress, _upnp); - ensureAccepting(); - m_lastPeersRequest = chrono::steady_clock::time_point::min(); - clog(NetNote) << "Id:" << m_id.abridged(); + stop(); } -Host::Host(std::string const& _clientVersion): - m_clientVersion(_clientVersion), - m_listenPort(0), - m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)), - m_socket(m_ioService), - m_id(h512::random()) +void Host::start() { - // populate addresses. - populateAddresses(); + if (isWorking()) + stop(); + + for (unsigned i = 0; i < 2; ++i) + { + bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort); + try + { + m_acceptor.open(endpoint.protocol()); + m_acceptor.set_option(ba::socket_base::reuse_address(true)); + m_acceptor.bind(endpoint); + m_acceptor.listen(); + m_listenPort = i ? m_acceptor.local_endpoint().port() : m_netPrefs.listenPort; + break; + } + catch (...) + { + if (i) + { + cwarn << "Couldn't start accepting connections on host. Something very wrong with network?"; + return; + } + m_acceptor.close(); + continue; + } + } + + determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp); + ensureAccepting(); + + m_incomingPeers.clear(); + m_freePeers.clear(); + m_lastPeersRequest = chrono::steady_clock::time_point::min(); clog(NetNote) << "Id:" << m_id.abridged(); + + for (auto const& h: m_capabilities) + h.second->onStarting(); + + startWorking(); } -Host::~Host() +void Host::stop() { + for (auto const& h: m_capabilities) + h.second->onStopping(); + + stopWorking(); + + if (m_acceptor.is_open()) + { + if (m_accepting) + m_acceptor.cancel(); + m_acceptor.close(); + m_accepting = false; + } + if (m_socket.is_open()) + m_socket.close(); disconnectPeers(); + + m_ioService.reset(); } unsigned Host::protocolVersion() const @@ -283,8 +318,14 @@ std::map Host::potentialPeers() if (auto j = i.second.lock()) { auto ep = j->endpoint(); +// cnote << "Checking potential peer" << j->m_listenPort << j->endpoint() << isPrivateAddress(ep.address()) << ep.port() << j->m_id.abridged(); // Skip peers with a listen port of zero or are on a private network - bool peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_localNetworking)); + bool peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking)); + if (!peerOnNet && m_incomingPeers.count(j->m_id)) + { + ep = m_incomingPeers.at(j->m_id).first; + peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking)); + } if (peerOnNet && ep.port() && j->m_id) ret.insert(make_pair(i.first, ep)); } @@ -293,7 +334,7 @@ std::map Host::potentialPeers() void Host::ensureAccepting() { - if (m_accepting == false) + if (!m_accepting) { clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")"; m_accepting = true; @@ -315,23 +356,38 @@ void Host::ensureAccepting() clog(NetWarn) << "ERROR: " << _e.what(); } m_accepting = false; - if (ec.value() != 1) + if (ec.value() < 1) ensureAccepting(); }); } } +string Host::pocHost() +{ + vector strs; + boost::split(strs, dev::Version, boost::is_any_of(".")); + return "poc-" + strs[1] + ".ethdev.com"; +} + void Host::connect(std::string const& _addr, unsigned short _port) noexcept { - try - { - connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port)); - } - catch (exception const& e) - { - // Couldn't connect - clog(NetConnect) << "Bad host " << _addr << " (" << e.what() << ")"; - } + for (int i = 0; i < 2; ++i) + try + { + if (i == 0) + { + bi::tcp::resolver r(m_ioService); + connect(r.resolve({_addr, toString(_port)})->endpoint()); + } + else + connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port)); + break; + } + catch (exception const& e) + { + // Couldn't connect + clog(NetConnect) << "Bad host " << _addr << " (" << e.what() << ")"; + } } void Host::connect(bi::tcp::endpoint const& _ep) @@ -397,7 +453,6 @@ void Host::growPeers() m_lastPeersRequest = chrono::steady_clock::now(); } - if (!m_accepting) ensureAccepting(); @@ -406,7 +461,8 @@ void Host::growPeers() auto x = time(0) % m_freePeers.size(); m_incomingPeers[m_freePeers[x]].second++; - connect(m_incomingPeers[m_freePeers[x]].first); + if (!m_peers.count(m_freePeers[x])) + connect(m_incomingPeers[m_freePeers[x]].first); m_freePeers.erase(m_freePeers.begin() + x); } } @@ -457,11 +513,8 @@ std::vector Host::peers(bool _updatePing) const return ret; } -void Host::process() +void Host::doWork() { - for (auto const& i: m_capabilities) - if (!i.second->isInitialised()) - return; growPeers(); prunePeers(); m_ioService.poll(); diff --git a/libp2p/Host.h b/libp2p/Host.h index 54e8f967e..f5f2f9e97 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "HostCapability.h" namespace ba = boost::asio; namespace bi = boost::asio::ip; @@ -41,22 +42,28 @@ class RLPStream; namespace p2p { +struct NetworkPreferences +{ + NetworkPreferences(unsigned short p = 30303, std::string i = std::string(), bool u = true, bool l = false): listenPort(p), publicIP(i), upnp(u), localNetworking(l) {} + + unsigned short listenPort = 30303; + std::string publicIP; + bool upnp = true; + bool localNetworking = false; +}; + /** * @brief The Host class * Capabilities should be registered prior to startNetwork, since m_capabilities is not thread-safe. */ -class Host +class Host: public Worker { friend class Session; friend class HostCapabilityFace; public: /// Start server, listening for connections on the given port. - Host(std::string const& _clientVersion, unsigned short _port, std::string const& _publicAddress = std::string(), bool _upnp = true, bool _localNetworking = false); - /// Start server, listening for connections on a system-assigned port. - Host(std::string const& _clientVersion, std::string const& _publicAddress = std::string(), bool _upnp = true, bool _localNetworking = false); - /// Start server, but don't listen. - Host(std::string const& _clientVersion); + Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bool _start = false); /// Will block on network process events. virtual ~Host(); @@ -75,14 +82,10 @@ public: template std::shared_ptr cap() const { try { return std::static_pointer_cast(m_capabilities.at(T::staticName())); } catch (...) { return nullptr; } } /// Connect to a peer explicitly. + static std::string pocHost(); void connect(std::string const& _addr, unsigned short _port = 30303) noexcept; void connect(bi::tcp::endpoint const& _ep); - /// Conduct I/O, polling, syncing, whatever. - /// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway. - /// This won't touch alter the blockchain. - void process(); - /// @returns true iff we have the a peer of the given id. bool havePeer(h512 _id) const; @@ -107,11 +110,17 @@ public: /// Deserialise the data and populate the set of known peers. void restorePeers(bytesConstRef _b); + void setNetworkPreferences(NetworkPreferences const& _p) { stop(); m_netPrefs = _p; start(); } + + void start(); + void stop(); + bool isStarted() const { return isWorking(); } + h512 id() const { return m_id; } void registerPeer(std::shared_ptr _s, std::vector const& _caps); -protected: +private: /// Called when the session has provided us with a new peer we can connect to. void noteNewPeers() {} @@ -123,12 +132,19 @@ protected: void growPeers(); void prunePeers(); + /// Conduct I/O, polling, syncing, whatever. + /// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway. + /// This won't touch alter the blockchain. + virtual void doWork(); + std::map potentialPeers(); std::string m_clientVersion; - unsigned short m_listenPort; - bool m_localNetworking = false; + NetworkPreferences m_netPrefs; + + static const int NetworkStopped = -1; + int m_listenPort = NetworkStopped; ba::io_service m_ioService; bi::tcp::acceptor m_acceptor; diff --git a/libp2p/HostCapability.h b/libp2p/HostCapability.h index 4b6d38f64..1c532788b 100644 --- a/libp2p/HostCapability.h +++ b/libp2p/HostCapability.h @@ -48,7 +48,9 @@ public: protected: virtual std::string name() const = 0; virtual Capability* newPeerCapability(Session* _s) = 0; - virtual bool isInitialised() const { return true; } + + virtual void onStarting() {} + virtual void onStopping() {} void seal(bytes& _b); diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 5ed987cff..2dc60e0de 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -102,7 +102,7 @@ bool Session::interpret(RLP const& _r) return false; } try - { m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), m_listenPort, std::chrono::steady_clock::duration()}); } + { m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), m_listenPort, std::chrono::steady_clock::duration(), _r[3].toSet()}); } catch (...) { disconnect(BadProtocol); @@ -159,13 +159,13 @@ bool Session::interpret(RLP const& _r) bi::address_v4 peerAddress(_r[i][0].toHash>().asArray()); auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt()); h512 id = _r[i][2].toHash(); - if (isPrivateAddress(peerAddress) && !m_server->m_localNetworking) - goto CONTINUE; + clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")" << isPrivateAddress(peerAddress) << m_id.abridged() << isPrivateAddress(endpoint().address()) << m_server->m_incomingPeers.count(id) << (m_server->m_incomingPeers.count(id) ? isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()) : -1); - clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")"; + if (isPrivateAddress(peerAddress) && !m_server->m_netPrefs.localNetworking) + goto CONTINUE; // check that it's not us or one we already know: - if (id && (m_server->m_id == id || m_server->havePeer(id) || m_server->m_incomingPeers.count(id))) + if (!(m_id == id && isPrivateAddress(endpoint().address()) && (!m_server->m_incomingPeers.count(id) || isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()))) && (!id || m_server->m_id == id || m_server->m_incomingPeers.count(id))) goto CONTINUE; // check that we're not already connected to addr: @@ -180,7 +180,7 @@ bool Session::interpret(RLP const& _r) m_server->m_incomingPeers[id] = make_pair(ep, 0); m_server->m_freePeers.push_back(id); m_server->noteNewPeers(); - clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id << ")"; + clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id .abridged()<< ")"; CONTINUE:; } break; @@ -266,19 +266,19 @@ void Session::writeImpl(bytes& _buffer) if (!m_socket.is_open()) return; - lock_guard l(m_writeLock); - m_writeQueue.push_back(_buffer); - if (m_writeQueue.size() == 1) + bool doWrite = false; + { + lock_guard l(m_writeLock); + m_writeQueue.push_back(_buffer); + doWrite = (m_writeQueue.size() == 1); + } + + if (doWrite) write(); } void Session::write() { -// cerr << (void*)this << " write" << endl; - lock_guard l(m_writeLock); - if (m_writeQueue.empty()) - return; - const bytes& bytes = m_writeQueue[0]; auto self(shared_from_this()); ba::async_write(m_socket, ba::buffer(bytes), [this, self](boost::system::error_code ec, std::size_t /*length*/) @@ -290,12 +290,16 @@ void Session::write() { cwarn << "Error sending: " << ec.message(); dropped(); + return; } else { + lock_guard l(m_writeLock); m_writeQueue.pop_front(); - write(); + if (m_writeQueue.empty()) + return; } + write(); }); } diff --git a/libp2p/Session.h b/libp2p/Session.h index bc43934b3..7c3fc3732 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -86,7 +86,7 @@ private: Host* m_server; - std::recursive_mutex m_writeLock; + std::mutex m_writeLock; std::deque m_writeQueue; mutable bi::tcp::socket m_socket; ///< Mutable to ask for native_handle(). diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index f9be5751f..68ee1bb9d 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -105,6 +105,6 @@ else () target_link_libraries(${EXECUTABLE} boost_filesystem) find_package(Threads REQUIRED) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) - install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ) + install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) endif () diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 689daf8d7..714081dfe 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -8,41 +8,8 @@ #include #include "QEthereum.h" using namespace std; - -// types -using dev::bytes; -using dev::bytesConstRef; -using dev::h160; -using dev::h256; -using dev::u160; -using dev::u256; -using dev::u256s; -using dev::RLP; -using dev::Address; -using dev::eth::BlockInfo; -using dev::eth::Client; -using dev::eth::Instruction; -using dev::KeyPair; -using dev::eth::NodeMode; -using dev::p2p::PeerInfo; -using dev::Secret; -using dev::eth::Transaction; - -// functions -using dev::toHex; -using dev::fromHex; -using dev::right160; -using dev::simpleDebugOut; -using dev::toLog2; -using dev::toString; -using dev::operator+; -using dev::eth::disassemble; -using dev::eth::units; -using dev::eth::formatBalance; - -// vars -using dev::g_logPost; -using dev::g_logVerbosity; +using namespace dev; +using namespace dev::eth; dev::bytes toBytes(QString const& _s) { @@ -89,7 +56,7 @@ QString unpadded(QString _s) return _s; } -QEthereum::QEthereum(QObject* _p, Client* _c, QList _accounts): +QEthereum::QEthereum(QObject* _p, eth::Interface* _c, QList _accounts): QObject(_p), m_client(_c), m_accounts(_accounts) { // required to prevent crash on osx when performing addto/evaluatejavascript calls @@ -120,7 +87,7 @@ QString QEthereum::secretToAddress(QString _s) const return toQJS(KeyPair(toSecret(_s)).address()); } -Client* QEthereum::client() const +eth::Interface* QEthereum::client() const { return m_client; } @@ -162,7 +129,7 @@ QString QEthereum::coinbase() const QString QEthereum::number() const { - return m_client ? QString::number(client()->blockChain().number() + 1) : ""; + return m_client ? QString::number(client()->number() + 1) : ""; } QString QEthereum::account() const @@ -381,7 +348,7 @@ bool QEthereum::isMining() const bool QEthereum::isListening() const { - return m_client ? client()->haveNetwork() : false; + return /*m_client ? client()->haveNetwork() :*/ false; } void QEthereum::setMining(bool _l) @@ -395,19 +362,19 @@ void QEthereum::setMining(bool _l) } } -void QEthereum::setListening(bool _l) +void QEthereum::setListening(bool) { if (!m_client) return; - if (_l) +/* if (_l) client()->startNetwork(); else - client()->stopNetwork(); + client()->stopNetwork();*/ } unsigned QEthereum::peerCount() const { - return m_client ? (unsigned)client()->peerCount() : 0; + return /*m_client ? (unsigned)client()->peerCount() :*/ 0; } QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice) diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index cacf1cfc4..50f2d96a5 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -7,8 +7,7 @@ #include namespace dev { namespace eth { -class Client; -class State; +class Interface; }} class QJSEngine; @@ -99,11 +98,11 @@ class QEthereum: public QObject Q_OBJECT public: - QEthereum(QObject* _p, dev::eth::Client* _c, QList _accounts); + QEthereum(QObject* _p, dev::eth::Interface* _c, QList _accounts); virtual ~QEthereum(); - dev::eth::Client* client() const; - void setClient(dev::eth::Client* _c) { m_client = _c; } + dev::eth::Interface* client() const; + void setClient(dev::eth::Interface* _c) { m_client = _c; } /// Call when the client() is going to be deleted to make this object useless but safe. void clientDieing(); @@ -199,7 +198,7 @@ private: Q_PROPERTY(unsigned peerCount READ peerCount NOTIFY miningChanged) Q_PROPERTY(int defaultBlock READ getDefault WRITE setDefault) - dev::eth::Client* m_client; + dev::eth::Interface* m_client; std::vector m_watches; QList m_accounts; }; diff --git a/libqethereum/QmlEthereum.cpp b/libqethereum/QmlEthereum.cpp index 350427f3e..89578a29a 100644 --- a/libqethereum/QmlEthereum.cpp +++ b/libqethereum/QmlEthereum.cpp @@ -50,7 +50,7 @@ using dev::g_logVerbosity; // Can get rid of this once we've sorted out ITC for signalling & multiplexed querying. dev::eth::Client* g_qmlClient; QObject* g_qmlMain; - +#if 0 QmlAccount::QmlAccount(QObject*) { } @@ -177,6 +177,8 @@ void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _ga client()->transact(_secret, _amount, _dest, bytes(_data.data(), _data.data() + _data.size()), _gas, _gasPrice); } +#endif + // extra bits needed to link on VS #ifdef _MSC_VER diff --git a/libqethereum/QmlEthereum.h b/libqethereum/QmlEthereum.h index dcb636301..d242540a1 100644 --- a/libqethereum/QmlEthereum.h +++ b/libqethereum/QmlEthereum.h @@ -23,8 +23,8 @@ Q_DECLARE_METATYPE(dev::u256) Q_DECLARE_METATYPE(dev::Address) Q_DECLARE_METATYPE(dev::Secret) Q_DECLARE_METATYPE(dev::KeyPair) -Q_DECLARE_METATYPE(QmlAccount*) -Q_DECLARE_METATYPE(QmlEthereum*) +//Q_DECLARE_METATYPE(QmlAccount*) +//Q_DECLARE_METATYPE(QmlEthereum*) class QmlU256Helper: public QObject { @@ -75,7 +75,7 @@ public: Q_INVOKABLE QString stringOf(dev::Address _a) const { return QString::fromStdString(dev::toHex(_a.asArray())); } Q_INVOKABLE QString toAbridged(dev::Address _a) const { return QString::fromStdString(_a.abridged()); } }; - +#if 0 class QmlAccount: public QObject { Q_OBJECT @@ -155,7 +155,7 @@ private: Q_PROPERTY(bool listening READ isListening WRITE setListening) Q_PROPERTY(bool mining READ isMining WRITE setMining) }; - +#endif #if 0 template T to(QVariant const& _s) { if (_s.type() != QVariant::String) return T(); auto s = _s.toString().toLatin1(); assert(s.size() == sizeof(T)); return *(T*)s.data(); } template QVariant toQJS(T const& _s) { QLatin1String ret((char*)&_s, sizeof(T)); assert(QVariant(QString(ret)).toString().toLatin1().size() == sizeof(T)); assert(*(T*)(QVariant(QString(ret)).toString().toLatin1().data()) == _s); return QVariant(QString(ret)); } diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 93f81dd0a..55e82a36f 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -35,102 +35,50 @@ using namespace dev::p2p; using namespace dev::eth; using namespace dev::shh; -WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, unsigned short _listenPort, std::string const& _publicIP, bool _upnp, dev::u256 _networkId, bool _localNetworking): +WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, NetworkPreferences const& _n): m_clientVersion(_clientVersion), - m_net(m_clientVersion, _listenPort, _publicIP, _upnp, _localNetworking) + m_net(_clientVersion, _n) { if (_dbPath.size()) Defaults::setDBPath(_dbPath); if (_interfaces.count("eth")) - m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, _networkId)); + m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean)); // if (_interfaces.count("shh")) // m_whisper = new eth::Whisper(m_net.get()); - - static const char* c_threadName = "net"; - - UpgradableGuard l(x_work); - { - UpgradeGuard ul(l); - - if (!m_work) - m_work.reset(new thread([&]() - { - setThreadName(c_threadName); - m_workState.store(Active, std::memory_order_release); - while (m_workState.load(std::memory_order_acquire) != Deleting) - workNet(); - m_workState.store(Deleted, std::memory_order_release); - })); - - } } WebThreeDirect::~WebThreeDirect() { - UpgradableGuard l(x_work); - - if (m_work) - { - if (m_workState.load(std::memory_order_acquire) == Active) - m_workState.store(Deleting, std::memory_order_release); - while (m_workState.load(std::memory_order_acquire) != Deleted) - this_thread::sleep_for(chrono::milliseconds(10)); - m_work->join(); - } - if (m_work) - { - UpgradeGuard ul(l); - m_work.reset(nullptr); - } } std::vector WebThreeDirect::peers() { - ReadGuard l(x_work); return m_net.peers(); } size_t WebThreeDirect::peerCount() const { - ReadGuard l(x_work); return m_net.peerCount(); } void WebThreeDirect::setIdealPeerCount(size_t _n) { - ReadGuard l(x_work); return m_net.setIdealPeerCount(_n); } bytes WebThreeDirect::savePeers() { - ReadGuard l(x_work); return m_net.savePeers(); } void WebThreeDirect::restorePeers(bytesConstRef _saved) { - ReadGuard l(x_work); return m_net.restorePeers(_saved); } void WebThreeDirect::connect(std::string const& _seedHost, unsigned short _port) { - ReadGuard l(x_work); m_net.connect(_seedHost, _port); } - -void WebThreeDirect::workNet() -{ - // Process network events. - // Synchronise block chain with network. - // Will broadcast any of our (new) transactions and blocks, and collect & add any of their (new) transactions and blocks. - { - ReadGuard l(x_work); - m_net.process(); // must be in guard for now since it uses the blockchain. - } - this_thread::sleep_for(chrono::milliseconds(1)); -} - diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index cf02c3122..06717ee26 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -66,7 +66,7 @@ class WebThreeDirect public: /// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception. /// ethereum() may be safely static_cast()ed to a eth::Client*. - WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, unsigned short _listenPort = 30303, std::string const& _publicIP = std::string(), bool _upnp = true, dev::u256 _networkId = 0, bool _localNetworking = false); + WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences()); /// Destructor. ~WebThreeDirect(); @@ -104,25 +104,23 @@ public: /// Sets the ideal number of peers. void setIdealPeerCount(size_t _n); + bool haveNetwork() const { return m_net.isStarted(); } + + void setNetworkPreferences(p2p::NetworkPreferences const& _n) { auto had = haveNetwork(); if (had) stopNetwork(); m_net.setNetworkPreferences(_n); if (had) startNetwork(); } + /// Start the network subsystem. - void startNetwork() { setIdealPeerCount(5); } + void startNetwork() { m_net.start(); } /// Stop the network subsystem. - void stopNetwork() { setIdealPeerCount(0); } + void stopNetwork() { m_net.stop(); } private: - /// Do some work on the network. - void workNet(); - std::string m_clientVersion; ///< Our end-application client's name/version. std::unique_ptr m_ethereum; ///< Main interface for Ethereum ("eth") protocol. std::unique_ptr m_whisper; ///< Main interface for Whisper ("shh") protocol. p2p::Host m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required. - std::unique_ptr m_work; ///< The network thread. - mutable boost::shared_mutex x_work; ///< Lock for the network existance. - std::atomic m_workState; }; @@ -137,7 +135,7 @@ class RPCMaster {}; class EthereumSlave: public eth::Interface { public: - EthereumSlave(RPCSlave* _c) {} + EthereumSlave(RPCSlave*) {} // TODO: implement all of the virtuals with the RLPClient link. }; @@ -145,7 +143,7 @@ public: class EthereumMaster { public: - EthereumMaster(RPCMaster* _m) {} + EthereumMaster(RPCMaster*) {} // TODO: implement the master-end of whatever the RLPClient link will send over. }; @@ -155,7 +153,7 @@ public: class WhisperSlave: public shh::Interface { public: - WhisperSlave(RPCSlave* _c) {} + WhisperSlave(RPCSlave*) {} // TODO: implement all of the virtuals with the RLPClient link. }; @@ -163,7 +161,7 @@ public: class WhisperMaster { public: - WhisperMaster(RPCMaster* _m) {} + WhisperMaster(RPCMaster*) {} // TODO: implement the master-end of whatever the RLPClient link will send over. }; diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index ea79572c8..94d3233c1 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -95,7 +95,7 @@ class MessageFilter public: MessageFilter() {} MessageFilter(std::vector > const& _m): m_topicMasks(_m) {} - MessageFilter(RLP const& _r): m_topicMasks(_r.operator std::vector>()) {} + MessageFilter(RLP const& _r): m_topicMasks((std::vector>)_r) {} void fillStream(RLPStream& _s) const { _s << m_topicMasks; } h256 sha3() const { RLPStream s; fillStream(s); return dev::eth::sha3(s.out()); } diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 3e8dab70d..2b3f92947 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -11,6 +11,7 @@ set(EXECUTABLE neth) add_executable(${EXECUTABLE} ${SRC_LIST}) +target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) diff --git a/neth/main.cpp b/neth/main.cpp index e492d1a3c..0dc552e39 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -39,6 +39,7 @@ #include #include #endif +#include #include "BuildInfo.h" #undef KEY_EVENT // from windows.h @@ -304,7 +305,6 @@ int main(int argc, char** argv) unsigned short remotePort = 30303; string dbPath; bool mining = false; - NodeMode mode = NodeMode::Full; unsigned peers = 5; #if ETH_JSONRPC int jsonrpc = 8080; @@ -389,19 +389,6 @@ int main(int argc, char** argv) g_logVerbosity = atoi(argv[++i]); else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) peers = atoi(argv[++i]); - else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) - { - string m = argv[++i]; - if (m == "full") - mode = NodeMode::Full; - else if (m == "peer") - mode = NodeMode::PeerServer; - else - { - cerr << "Unknown mode: " << m << endl; - return -1; - } - } else if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") @@ -413,7 +400,8 @@ int main(int argc, char** argv) if (!clientName.empty()) clientName += "/"; - Client c("NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), coinbase, dbPath); + WebThreeDirect web3("NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath); + Client& c = *web3.ethereum(); c.setForceMining(true); @@ -479,7 +467,12 @@ int main(int argc, char** argv) wmove(mainwin, 1, 4); if (!remoteHost.empty()) - c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp); + { + web3.setIdealPeerCount(peers); + web3.setNetworkPreferences(NetworkPreferences(listenPort, publicIP, upnp)); + web3.startNetwork(); + web3.connect(remoteHost, remotePort); + } if (mining) c.startMining(); @@ -487,7 +480,7 @@ int main(int argc, char** argv) auto_ptr jsonrpcServer; if (jsonrpc > -1) { - jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c)); + jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3)); jsonrpcServer->setKeys({us}); jsonrpcServer->StartListening(); } @@ -528,18 +521,19 @@ int main(int argc, char** argv) { unsigned port; iss >> port; - c.startNetwork((short)port); + web3.setNetworkPreferences(NetworkPreferences((short)port, publicIP, upnp)); + web3.startNetwork(); } else if (cmd == "connect") { string addr; unsigned port; iss >> addr >> port; - c.connect(addr, (short)port); + web3.connect(addr, (short)port); } else if (cmd == "netstop") { - c.stopNetwork(); + web3.stopNetwork(); } else if (cmd == "minestart") { @@ -560,7 +554,7 @@ int main(int argc, char** argv) { if (jsonrpc < 0) jsonrpc = 8080; - jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), c)); + jsonrpcServer = auto_ptr(new EthStubServer(new jsonrpc::HttpServer(jsonrpc), web3)); jsonrpcServer->setKeys({us}); jsonrpcServer->StartListening(); } @@ -589,7 +583,7 @@ int main(int argc, char** argv) } else if (cmd == "peers") { - for (auto it: c.peers()) + for (auto it: web3.peers()) cout << it.host << ":" << it.port << ", " << it.clientVersion << ", " << std::chrono::duration_cast(it.lastPing).count() << "ms" << endl; @@ -925,7 +919,7 @@ int main(int argc, char** argv) // Peers y = 1; - for (PeerInfo const& i: c.peers()) + for (PeerInfo const& i: web3.peers()) { auto s = boost::format("%1% ms - %2%:%3% - %4%") % toString(chrono::duration_cast(i.lastPing).count()) % @@ -971,7 +965,7 @@ int main(int argc, char** argv) // Peers mvwprintw(peerswin, 0, x, "Peers: "); - mvwprintw(peerswin, 0, 9, toString(c.peers().size()).c_str()); + mvwprintw(peerswin, 0, 9, toString(web3.peers().size()).c_str()); // Mining flag if (c.isMining()) diff --git a/package.sh b/package.sh index 681c20096..f6d45b07c 100755 --- a/package.sh +++ b/package.sh @@ -3,7 +3,7 @@ opwd="$PWD" br=$(git branch | grep '\*' | sed 's/^..//') -n=cpp-ethereum-src-$(date "+%Y%m%d%H%M%S" --date="1970-01-01 $(git log -1 --date=short --pretty=format:%ct) sec GMT")-$(grep "EthVersion = " libethential/Common.cpp | sed 's/^[^"]*"//' | sed 's/".*$//')-$(git rev-parse HEAD | cut -c1-6) +n=cpp-ethereum-src-$(date "+%Y%m%d%H%M%S" --date="1970-01-01 $(git log -1 --date=short --pretty=format:%ct) sec GMT")-$(grep "Version = " libdevcore/Common.cpp | sed 's/^[^"]*"//' | sed 's/".*$//')-$(git rev-parse HEAD | cut -c1-6) cd /tmp git clone "$opwd" $n diff --git a/sc/cmdline.cpp b/sc/cmdline.cpp index 69e96b41e..b7a15634a 100644 --- a/sc/cmdline.cpp +++ b/sc/cmdline.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include int main(int argv, char** argc) { diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 02a883dbc..20c42a9b8 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -42,11 +42,14 @@ void mine(Client& c, int numBlocks) void connectClients(Client& c1, Client& c2) { + // TODO: Move to WebThree. eth::Client no longer handles networking. +#if 0 short c1Port = 20000; short c2Port = 21000; c1.startNetwork(c1Port); c2.startNetwork(c2Port); c2.connect("127.0.0.1", c1Port); +#endif } } diff --git a/test/peer.cpp b/test/peer.cpp index 821aab514..a99ce7201 100644 --- a/test/peer.cpp +++ b/test/peer.cpp @@ -46,7 +46,7 @@ int peerTest(int argc, char** argv) remoteHost = argv[i]; } - Host ph("Test", listenPort); + Host ph("Test", NetworkPreferences(listenPort)); if (!remoteHost.empty()) ph.connect(remoteHost, remotePort); diff --git a/test/vm.cpp b/test/vm.cpp index e177855cb..8100ee822 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -219,13 +219,13 @@ public: if (li) store[curKey] = curVal; li = s.first; - curKey = toString(li); + curKey = "0x"+toHex(toCompactBigEndian(li)); curVal = mArray(); } else for (; li != s.first; ++li) curVal.push_back(0); - push(curVal, s.second); + curVal.push_back("0x"+toHex(toCompactBigEndian(s.second))); ++li; } if (li) @@ -474,8 +474,9 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_AUTO_TEST_CASE(vm_tests) { + /* // Populate tests first: -// try + try { cnote << "Populating VM tests..."; json_spirit::mValue v; @@ -485,7 +486,7 @@ BOOST_AUTO_TEST_CASE(vm_tests) dev::test::doTests(v, true); writeFile("../../../tests/vmtests.json", asBytes(json_spirit::write_string(v, true))); } -/* catch (std::exception const& e) + catch (std::exception const& e) { BOOST_ERROR("Failed VM Test with Exception: " << e.what()); }*/ @@ -504,3 +505,30 @@ BOOST_AUTO_TEST_CASE(vm_tests) BOOST_ERROR("Failed VM Test with Exception: " << e.what()); } } + +BOOST_AUTO_TEST_CASE(vmArithmeticTest) +{ + /* + cnote << "Populating VM tests..."; + json_spirit::mValue v; + string s = asString(contents("../../../cpp-ethereum/test/vmArithmeticTestFiller.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'vmtests.json' is empty."); + json_spirit::read_string(s, v); + dev::test::doTests(v, true); + writeFile("../../../tests/vmArithmeticTest.json", asBytes(json_spirit::write_string(v, true))); + */ + + try + { + cnote << "Testing VM arithmetic commands..."; + json_spirit::mValue v; + string s = asString(contents("../../../tests/vmArithmeticTest.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'vmArithmeticTest.json' is empty. Have you cloned the 'tests' repo branch develop?"); + json_spirit::read_string(s, v); + dev::test::doTests(v, false); + } + catch (std::exception const& e) + { + BOOST_ERROR("Failed VM arithmetic test with Exception: " << e.what()); + } +} diff --git a/test/vmArithmeticTestFiller.json b/test/vmArithmeticTestFiller.json new file mode 100644 index 000000000..d7826d198 --- /dev/null +++ b/test/vmArithmeticTestFiller.json @@ -0,0 +1,2055 @@ +{ + "stop": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "0x00", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "add0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ 115792089237316195423570985008687907853269984665640564039457584007913129639935 115792089237316195423570985008687907853269984665640564039457584007913129639935) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "add1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ 115792089237316195423570985008687907853269984665640564039457584007913129639935 4) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "add2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ 115792089237316195423570985008687907853269984665640564039457584007913129639936 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "add3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ 0 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "add4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ 1 115792089237316195423570985008687907853269984665640564039457584007913129639935) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "mul0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (* 2 3) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "mul1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (* 115792089237316195423570985008687907853269984665640564039457584007913129639935 115792089237316195423570985008687907853269984665640564039457584007913129639935) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mul2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (* 0 23) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mul3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (* 23 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sub0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (- 23 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sub1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (- 2 3) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sub2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (- 0 23) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sub3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (- 0 115792089237316195423570985008687907853269984665640564039457584007913129639935) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sub4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (- 115792089237316195423570985008687907853269984665640564039457584007913129639935 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "divByZero": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (/ 2 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "divByNonZero0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (/ 5 2) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "divByNonZero1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (/ 23 24) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "divByNonZero2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (/ 0 24) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "divByNonZero3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (/ 1 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdivByZero0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV (- 0 3) (- 0 0)) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdivByZero1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV (- 0 115792089237316195423570985008687907853269984665640564039457584007913129639935) 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdiv0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV (- 0 115792089237316195423570985008687907853269984665640564039457584007913129639935) 115792089237316195423570985008687907853269984665640564039457584007913129639935) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdiv1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV 115792089237316195423570985008687907853269984665640564039457584007913129639935 (- 0 115792089237316195423570985008687907853269984665640564039457584007913129639935) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdiv2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV (- 0 2) (- 0 4) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sdiv3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SDIV 4 (- 0 2) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mod0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (% 2 3 ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mod1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (% 115792089237316195423570985008687907853269984665640564039457584007913129639935 2 ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mod2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (% 0 115792089237316195423570985008687907853269984665640564039457584007913129639935 ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mod3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (% 3 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "mod4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (% (- 0 2) 3) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "smod0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SMOD (- 0 5) (- 0 3))}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "smod1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SMOD 5 (- 0 3))}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "smod2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SMOD (- 0 5) 3)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "smod3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SMOD (- 0 2) 115792089237316195423570985008687907853269984665640564039457584007913129639935)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "smod4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SMOD (- 0 2) 0)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 2 2)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 115792089237316195423570985008687907853269984665640564039457584007913129639935 115792089237316195423570985008687907853269984665640564039457584007913129639934 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 2147483647 2147483647)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 0 2147483647)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 2147483647 0)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp5": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 257 1)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp6": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 1 257)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "exp7": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EXP 2 257)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "neg0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "neg1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG 2 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "neg2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "neg3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG (- 0 2) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "neg4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG (- 0 115792089237316195423570985008687907853269984665640564039457584007913129639935) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "neg5": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NEG (- 0 0) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "lt0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (LT (- 0 2) 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "lt1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (LT 0 (- 0 2) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "lt2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (LT 115792089237316195423570985008687907853269984665640564039457584007913129639935 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "lt3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (LT 0 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "gt0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] ( GT (- 0 2) 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "gt1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (GT 0 (- 0 2) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "gt2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (GT 115792089237316195423570985008687907853269984665640564039457584007913129639935 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "gt3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (GT 0 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "slt0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SLT (- 0 2) 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "slt1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SLT 0 (- 0 2) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "slt2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SLT 115792089237316195423570985008687907853269984665640564039457584007913129639935 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "slt3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SLT 0 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "slt4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SLT (- 0 5) (- 0 3) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sgt0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SGT (- 0 2) 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sgt1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SGT 0 (- 0 2) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sgt2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SGT 115792089237316195423570985008687907853269984665640564039457584007913129639935 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + "sgt3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SGT 0 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "sgt4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (SGT (- 0 5) (- 0 3) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "eq0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EQ (- 0 5) (- 0 3) )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "eq1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EQ 0 0)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "eq2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (EQ 115792089237316195423570985008687907853269984665640564039457584007913129639935 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "not0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NOT 115792089237316195423570985008687907853269984665640564039457584007913129639935 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + "not1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (NOT 0 )}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + + + +} diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index a68b90813..77b2bb496 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -52,7 +52,7 @@ else () endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) -target_link_libraries(${EXECUTEABLE} qethereum ethereum evm ethcore secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore) +target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore) if (APPLE) # First have qt5 install plugins and frameworks diff --git a/third/MainWin.cpp b/third/MainWin.cpp index 7bbdd721b..be8420426 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,49 +39,14 @@ #include #include #include +#include #include "BuildInfo.h" #include "MainWin.h" #include "ui_Main.h" using namespace std; - -// types -using dev::bytes; -using dev::bytesConstRef; -using dev::h160; -using dev::h256; -using dev::u160; -using dev::u256; -using dev::Address; -using dev::eth::BlockInfo; -using dev::eth::Client; -using dev::eth::Instruction; -using dev::KeyPair; -using dev::eth::NodeMode; -using dev::eth::BlockChain; -using dev::p2p::PeerInfo; -using dev::RLP; -using dev::Secret; -using dev::eth::Transaction; -using dev::eth::Executive; - -// functions -using dev::toHex; -using dev::fromHex; -using dev::left160; -using dev::right160; -using dev::simpleDebugOut; -using dev::toLog2; -using dev::toString; -using dev::operator<<; -using dev::eth::units; -using dev::eth::compileLLL; -using dev::eth::disassemble; -using dev::eth::formatBalance; -using dev::eth::sha3; - -// vars -using dev::g_logPost; -using dev::g_logVerbosity; +using namespace dev; +using namespace dev::eth; +using namespace dev::p2p; static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr) { @@ -133,12 +99,13 @@ Main::Main(QWidget *parent) : connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); - m_client.reset(new Client("Third")); + m_web3.reset(new WebThreeDirect("Third", getDataDir() + "/Third", false, {"eth", "shh"})); + m_web3->connect(Host::pocHost()); connect(ui->webView, &QWebView::loadStarted, [this]() { // NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it. - m_ethereum = new QEthereum(this, m_client.get(), owned()); + m_ethereum = new QEthereum(this, ethereum(), owned()); QWebFrame* f = ui->webView->page()->mainFrame(); f->disconnect(SIGNAL(javaScriptWindowObjectCleared())); @@ -181,6 +148,11 @@ Main::~Main() writeSettings(); } +eth::Client* Main::ethereum() const +{ + return m_web3->ethereum(); +} + void Main::onKeysChanged() { installBalancesWatch(); @@ -188,14 +160,14 @@ void Main::onKeysChanged() unsigned Main::installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f) { - auto ret = m_client->installWatch(_tf); + auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; return ret; } unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) { - auto ret = m_client->installWatch(_tf); + auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; return ret; } @@ -209,14 +181,14 @@ void Main::installWatches() void Main::installNameRegWatch() { - m_client->uninstallWatch(m_nameRegFilter); - m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)m_client->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); + ethereum()->uninstallWatch(m_nameRegFilter); + m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { - m_client->uninstallWatch(m_currenciesFilter); - m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)m_client->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); + ethereum()->uninstallWatch(m_currenciesFilter); + m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } void Main::installBalancesWatch() @@ -224,9 +196,9 @@ void Main::installBalancesWatch() dev::eth::MessageFilter tf; vector
altCoins; - Address coinsAddr = right160(m_client->stateAt(c_config, 1)); - for (unsigned i = 0; i < m_client->stateAt(coinsAddr, 0); ++i) - altCoins.push_back(right160(m_client->stateAt(coinsAddr, i + 1))); + Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); + for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) + altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); for (auto i: m_myKeys) { tf.altered(i.address()); @@ -234,7 +206,7 @@ void Main::installBalancesWatch() tf.altered(c, (u160)i.address()); } - m_client->uninstallWatch(m_balancesFilter); + ethereum()->uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); }); } @@ -295,8 +267,8 @@ QString Main::pretty(dev::Address _a) const { h256 n; - if (h160 nameReg = (u160)m_client->stateAt(c_config, 0)) - n = m_client->stateAt(nameReg, (u160)(_a)); + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) + n = ethereum()->stateAt(nameReg, (u160)(_a)); return fromRaw(n); } @@ -322,8 +294,8 @@ Address Main::fromString(QString const& _a) const memset(n.data() + sn.size(), 0, 32 - sn.size()); if (_a.size()) { - if (h160 nameReg = (u160)m_client->stateAt(c_config, 0)) - if (h256 a = m_client->stateAt(nameReg, n)) + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) + if (h256 a = ethereum()->stateAt(nameReg, n)) return right160(a); } if (_a.size() == 40) @@ -351,11 +323,11 @@ QString Main::lookup(QString const& _a) const */ h256 ret; - if (h160 dnsReg = (u160)m_client->stateAt(c_config, 4, 0)) - ret = m_client->stateAt(dnsReg, n); + if (h160 dnsReg = (u160)ethereum()->stateAt(c_config, 4, 0)) + ret = ethereum()->stateAt(dnsReg, n); /* if (!ret) - if (h160 nameReg = (u160)m_client->stateAt(c_config, 0, 0)) - ret = m_client->stateAt(nameReg, n2); + if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0, 0)) + ret = ethereum()->stateAt(nameReg, n2); */ if (ret && !((u256)ret >> 32)) return QString("%1.%2.%3.%4").arg((int)ret[28]).arg((int)ret[29]).arg((int)ret[30]).arg((int)ret[31]); @@ -385,7 +357,7 @@ void Main::writeSettings() s.setValue("address", b); s.setValue("url", ui->urlEdit->text()); - bytes d = m_client->savePeers(); + bytes d = m_web3->savePeers(); if (d.size()) m_peers = QByteArray((char*)d.data(), (int)d.size()); s.setValue("peers", m_peers); @@ -416,7 +388,7 @@ void Main::readSettings(bool _skipGeometry) m_myKeys.append(KeyPair(k)); } } - m_client->setAddress(m_myKeys.back().address()); + ethereum()->setAddress(m_myKeys.back().address()); m_peers = s.value("peers").toByteArray(); ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html on_urlEdit_returnPressed(); @@ -466,8 +438,8 @@ void Main::on_urlEdit_returnPressed() void Main::refreshMining() { - dev::eth::MineProgress p = m_client->miningProgress(); - ui->mineStatus->setText(m_client->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); + dev::eth::MineProgress 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"); } void Main::refreshBalances() @@ -477,18 +449,18 @@ void Main::refreshBalances() ui->ourAccounts->clear(); u256 totalBalance = 0; map> altCoins; - Address coinsAddr = right160(m_client->stateAt(c_config, 1)); - for (unsigned i = 0; i < m_client->stateAt(coinsAddr, 0); ++i) - altCoins[right160(m_client->stateAt(coinsAddr, m_client->stateAt(coinsAddr, i + 1)))] = make_pair(fromRaw(m_client->stateAt(coinsAddr, i + 1)), 0); + Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); + for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) + altCoins[right160(ethereum()->stateAt(coinsAddr, ethereum()->stateAt(coinsAddr, i + 1)))] = make_pair(fromRaw(ethereum()->stateAt(coinsAddr, i + 1)), 0); for (auto i: m_myKeys) { - u256 b = m_client->balanceAt(i.address()); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)m_client->countAt(i.address())), ui->ourAccounts)) + u256 b = ethereum()->balanceAt(i.address()); + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); totalBalance += b; for (auto& c: altCoins) - c.second.second += (u256)m_client->stateAt(c.first, (u160)i.address()); + c.second.second += (u256)ethereum()->stateAt(c.first, (u160)i.address()); } QString b; @@ -500,7 +472,7 @@ void Main::refreshBalances() void Main::refreshNetwork() { - auto ps = m_client->peers(); + auto ps = m_web3->peers(); ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)"); } @@ -514,8 +486,8 @@ void Main::refreshAll() void Main::refreshBlockCount() { cwatch << "refreshBlockCount()"; - auto d = m_client->blockChain().details(); - auto diff = BlockInfo(m_client->blockChain().block()).difficulty; + auto d = ethereum()->blockChain().details(); + auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty; ui->blockCount->setText(QString("#%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion)); } @@ -543,7 +515,7 @@ void Main::timerEvent(QTimerEvent*) m_ethereum->poll(); for (auto const& i: m_handlers) - if (m_client->checkWatch(i.first)) + if (ethereum()->checkWatch(i.first)) i.second(); } @@ -574,7 +546,7 @@ void Main::ensureNetwork() { string n = string("Third/v") + dev::Version; n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); - m_client->setClientVersion(n); + web3()->setClientVersion(n); int pocnumber = QString(dev::Version).section('.', 1, 1).toInt(); string defPeer; @@ -583,13 +555,16 @@ void Main::ensureNetwork() else if (pocnumber == 6) defPeer = "54.76.56.74"; - if (!m_client->haveNetwork()) - m_client->startNetwork(30303, defPeer); + if (!web3()->haveNetwork()) + { + web3()->startNetwork(); + web3()->connect(defPeer); + } else - if (!m_client->peerCount()) - m_client->connect(defPeer); + if (!m_web3->peerCount()) + m_web3->connect(defPeer); if (m_peers.size()) - m_client->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); + m_web3->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); } void Main::on_connect_triggered() @@ -600,7 +575,7 @@ void Main::on_connect_triggered() { string host = s.section(":", 0, 0).toStdString(); unsigned short port = s.section(":", 1).toInt(); - m_client->connect(host, port); + web3()->connect(host, port); } } @@ -608,11 +583,11 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { - m_client->setAddress(m_myKeys.last().address()); - m_client->startMining(); + ethereum()->setAddress(m_myKeys.last().address()); + ethereum()->startMining(); } else - m_client->stopMining(); + ethereum()->stopMining(); } // extra bits needed to link on VS diff --git a/third/MainWin.h b/third/MainWin.h index 76505d603..df05d6828 100644 --- a/third/MainWin.h +++ b/third/MainWin.h @@ -36,7 +36,8 @@ namespace Ui { class Main; } -namespace dev { namespace eth { +namespace dev { class WebThreeDirect; +namespace eth { class Client; class State; class MessageFilter; @@ -52,7 +53,8 @@ public: explicit Main(QWidget *parent = 0); ~Main(); - dev::eth::Client* client() { return m_client.get(); } + dev::WebThreeDirect* web3() const { return m_web3.get(); } + dev::eth::Client* ethereum() const; QList const& owned() const { return m_myKeys; } @@ -111,7 +113,7 @@ private: std::unique_ptr ui; - std::unique_ptr m_client; + std::unique_ptr m_web3; QList m_myKeys; diff --git a/walleth/MainWin.cpp b/walleth/MainWin.cpp index ade04c4fa..3fa5a9388 100644 --- a/walleth/MainWin.cpp +++ b/walleth/MainWin.cpp @@ -61,7 +61,7 @@ Main::Main(QWidget *parent) : g_qmlMain = this; - m_client.reset(new Client("Walleth", Address(), dev::eth::getDataDir() + "/Walleth")); + m_client.reset(new Client("Walleth", Address(), dev::getDataDir() + "/Walleth")); g_qmlClient = m_client.get(); diff --git a/windows/Alethzero.vcxproj b/windows/Alethzero.vcxproj index 721c0729e..d418e5d03 100644 --- a/windows/Alethzero.vcxproj +++ b/windows/Alethzero.vcxproj @@ -209,6 +209,24 @@ + + $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" + + + $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" + + + $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" + + + $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" + + + $(IntDir)moc_%(FileName).cpp + $(IntDir)moc_%(FileName).cpp + $(IntDir)moc_%(FileName).cpp + $(IntDir)moc_%(FileName).cpp + $(Lua) moc.lua "$(QtBin)/moc" "$(IntDir)moc_%(FileName).cpp" "@(ClCompile->'%(AdditionalIncludeDirectories)');$(IncludePath)" "@(ClCompile->'%(PreprocessorDefinitions)');_MSC_VER=1800" "%(FullPath)" @@ -289,4 +307,4 @@ - \ No newline at end of file + diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index 6403d7fad..26fe794c2 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -23,8 +23,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMiniUPnPc", "LibMiniUPnP EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlethZero", "Alethzero.vcxproj", "{BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Walleth", "Walleth.vcxproj", "{326EF470-463F-4751-A22A-48BBAAD8B143}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibQEthereum", "LibQEthereum.vcxproj", "{DF3C5B07-A1A2-4F16-B37F-A27333622CDD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eth", "Eth.vcxproj", "{C60C065C-2135-4B2B-AFD4-35FD7AC56B40}" diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 196325353..134171843 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -527,4 +527,4 @@ - \ No newline at end of file + diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 5a650b0c5..b6e2dc070 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -175,6 +175,9 @@ libwhisper + + libethereum + @@ -384,6 +387,9 @@ libwhisper + + libethereum +