From da1fcbb19b4e07e9d40f1d29de0b190100f7e9d1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 12 May 2015 16:46:42 +0300 Subject: [PATCH] DAG generation improvements. Generate next DAG in AZ! Cleanups to Ethash & Aux. DAG Progress in AZ. --- alethzero/Main.ui | 6 +++ alethzero/MainWin.cpp | 39 +++++++++----- alethzero/MainWin.h | 1 + alethzero/Transact.cpp | 5 +- eth/main.cpp | 107 ++++++++++++++++++++++----------------- libdevcore/Common.h | 8 +-- libdevcore/Worker.cpp | 10 ++-- libethcore/Ethash.cpp | 6 ++- libethcore/Ethash.h | 2 +- libethcore/EthashAux.cpp | 46 ++++++++++++----- libethcore/EthashAux.h | 14 ++++- libethereum/ClientBase.h | 4 +- libethereum/State.cpp | 4 +- 13 files changed, 161 insertions(+), 91 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 5b0ad7582..e0852142a 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -151,6 +151,7 @@ + @@ -1727,6 +1728,11 @@ font-size: 14pt In&ject Block + + + Prepare Next &DAG + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 87c9c2dc9..7551eaa35 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -204,7 +204,7 @@ Main::Main(QWidget *parent) : QSettings s("ethereum", "alethzero"); m_networkConfig = s.value("peers").toByteArray(); bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size()); - m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth", "shh"}, p2p::NetworkPreferences(), network)); + m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth"/*, "shh"*/}, p2p::NetworkPreferences(), network)); m_httpConnector.reset(new jsonrpc::HttpServer(SensibleHttpPort, "", "", dev::SensibleHttpThreads)); m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), this)); @@ -943,22 +943,30 @@ void Main::on_preview_triggered() refreshAll(); } +void Main::on_prepNextDAG_triggered() +{ + EthashAux::computeFull(ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH); +} + void Main::refreshMining() { + pair gp = EthashAux::fullGeneratingProgress(); + QString t; + if (gp.first != EthashAux::NotGenerating) + t = QString("DAG for #%1-#%2: %3% complete; ").arg(gp.first).arg(gp.first + ETHASH_EPOCH_LENGTH - 1).arg(gp.second); MiningProgress p = ethereum()->miningProgress(); - ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); - if (!ui->miningView->isVisible()) - return; - list l = ethereum()->miningHistory(); - static unsigned lh = 0; - if (p.hashes < lh) - ui->miningView->resetStats(); - lh = p.hashes; - ui->miningView->appendStats(l, p); -/* if (p.ms) - for (MineInfo const& i: l) - cnote << i.hashes * 10 << "h/sec, need:" << i.requirement << " best:" << i.best << " best-so-far:" << p.best << " avg-speed:" << (p.hashes * 1000 / p.ms) << "h/sec"; -*/ + ui->mineStatus->setText(t + (ethereum()->isMining() ? p.hashes > 0 ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Awaiting DAG" : "Not mining")); + if (ethereum()->isMining() && p.hashes > 0) + { + if (!ui->miningView->isVisible()) + return; + list l = ethereum()->miningHistory(); + static unsigned lh = 0; + if (p.hashes < lh) + ui->miningView->resetStats(); + lh = p.hashes; + ui->miningView->appendStats(l, p); + } } void Main::setBeneficiary(Address const& _b) @@ -1878,6 +1886,7 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { +// EthashAux::computeFull(ethereum()->blockChain().number()); ethereum()->setAddress(m_beneficiary); ethereum()->startMining(); } @@ -2027,6 +2036,7 @@ std::string Main::prettyU256(dev::u256 const& _n) const void Main::on_post_clicked() { + return; shh::Message m; m.setTo(stringToPublic(ui->shhTo->currentText())); m.setPayload(parseData(ui->shhData->toPlainText().toStdString())); @@ -2051,6 +2061,7 @@ int Main::authenticate(QString _title, QString _text) void Main::refreshWhispers() { + return; ui->whispers->clear(); for (auto const& w: whisper()->all()) { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 51d4cc8f4..d9075d178 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -124,6 +124,7 @@ private slots: // Mining void on_mine_triggered(); + void on_prepNextDAG_triggered(); // View void on_refresh_triggered(); diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index bc37db8ef..f2a8ef0d5 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -299,8 +299,9 @@ void Transact::rejigData() return; // Determine how much balance we have to play with... - auto s = findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice()); - auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock); + //findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice()); + auto s = fromAccount(); + auto b = ethereum()->balanceAt(s, PendingBlock); m_allGood = true; QString htmlInfo; diff --git a/eth/main.cpp b/eth/main.cpp index d6582e4d3..abb78c20d 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -158,6 +158,11 @@ void help() << " --port Connect to remote port (default: 30303)." << endl << " --network-id Only connect to other hosts with this network id (default:0)." << endl << " --upnp Use UPnP for NAT (default: on)." << endl + << endl + << "Client structured logging:" << endl + << " --structured-logging Enable structured logging (default output to stdout)." << endl + << " --structured-logging-format Set the structured logging time format." << endl + << " --structured-logging-url Set the structured logging destination (currently only file:// supported)." << endl #if ETH_JSONRPC || !ETH_TRUE << endl << "Work farming mode:" << endl @@ -806,8 +811,11 @@ int main(int argc, char** argv) structuredLoggingFormat = string(argv[++i]); else if (arg == "--structured-logging") structuredLogging = true; - else if (arg == "--structured-logging-destination" && i + 1 < argc) + else if (arg == "--structured-logging-url" && i + 1 < argc) + { + structuredLogging = true; structuredLoggingURL = argv[++i]; + } else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) dbPath = argv[++i]; else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) @@ -1033,6 +1041,28 @@ int main(int argc, char** argv) if (!clientName.empty()) clientName += "/"; + string logbuf; + bool silence = false; + std::string additional; + g_logPost = [&](std::string const& a, char const*){ + if (silence) + logbuf += a + "\n"; + else + cout << "\r \r" << a << endl << additional << flush; + }; + + auto getPassword = [&](string const& prompt){ + auto s = silence; + silence = true; + cout << endl; + string ret = dev::getPassword(prompt); + silence = s; + return ret; + }; + auto getAccountPassword = [&](Address const& a){ + return getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): "); + }; + StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat, structuredLoggingURL); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); @@ -1042,13 +1072,38 @@ int main(int argc, char** argv) clientImplString, dbPath, killChain, - nodeMode == NodeMode::Full ? set{"eth", "shh"} : set(), + nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); if (mode == OperationMode::DAGInit) doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0)); + if (keyManager.exists()) + while (masterPassword.empty()) + { + masterPassword = getPassword("Please enter your MASTER password: "); + if (!keyManager.load(masterPassword)) + { + cout << "Password invalid. Try again." << endl; + masterPassword.clear(); + } + } + else + { + while (masterPassword.empty()) + { + masterPassword = getPassword("Please enter a MASTER password to protect your key store (make it strong!): "); + string confirm = getPassword("Please confirm the password by entering it again: "); + if (masterPassword != confirm) + { + cout << "Passwords were different. Try again." << endl; + masterPassword.clear(); + } + } + keyManager.create(masterPassword); + } + auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); @@ -1137,53 +1192,13 @@ int main(int argc, char** argv) if (remoteHost.size()) web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); - if (keyManager.exists()) - while (masterPassword.empty()) - { - masterPassword = getPassword("Please enter your MASTER password: "); - if (!keyManager.load(masterPassword)) - { - cout << "Password invalid. Try again." << endl; - masterPassword.clear(); - } - } - else - { - while (masterPassword.empty()) - { - masterPassword = getPassword("Please enter a MASTER password to protect your key store (make it strong!): "); - string confirm = getPassword("Please confirm the password by entering it again: "); - if (masterPassword != confirm) - { - cout << "Passwords were different. Try again." << endl; - masterPassword.clear(); - } - } - keyManager.create(masterPassword); - } - - string logbuf; - bool silence = false; - std::string additional; - g_logPost = [&](std::string const& a, char const*) { if (silence) logbuf += a + "\n"; else cout << "\r \r" << a << endl << additional << flush; }; - - // TODO: give hints &c. - auto getPassword = [&](Address const& a){ - auto s = silence; - silence = true; - cout << endl; - string ret = dev::getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): "); - silence = s; - return ret; - }; - #if ETH_JSONRPC || !ETH_TRUE shared_ptr jsonrpcServer; unique_ptr jsonrpcConnector; if (jsonrpc > -1) { jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getAccountPassword, keyManager), vector())); jsonrpcServer->StartListening(); } #endif @@ -1327,7 +1342,7 @@ int main(int argc, char** argv) if (jsonrpc < 0) jsonrpc = SensibleHttpPort; jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getAccountPassword, keyManager), vector())); jsonrpcServer->StartListening(); } else if (cmd == "jsonstop") @@ -1479,7 +1494,7 @@ int main(int argc, char** argv) try { Address dest = h160(fromHex(hexAddr, WhenError::Throw)); - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), amount, dest, bytes(), minGas); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), amount, dest, bytes(), minGas); } catch (BadHexCharacter& _e) { @@ -1548,7 +1563,7 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), endowment, init, gas, gasPrice); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), endowment, init, gas, gasPrice); } else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 41f1b1d49..95817e41c 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -199,12 +199,12 @@ private: #define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__) #endif -#define DEV_TIMED_IF(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) -#define DEV_TIMED_SCOPE_IF(S) ::dev::TimerHelper __eth_t(S, MS) +#define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) +#define DEV_TIMED_SCOPE_ABOVE(S) ::dev::TimerHelper __eth_t(S, MS) #if WIN32 -#define DEV_TIMED_FUNCTION_IF(MS) DEV_TIMED_SCOPE_IF(__FUNCSIG__, MS) +#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS) #else -#define DEV_TIMED_FUNCTION_IF(MS) DEV_TIMED_SCOPE_IF(__PRETTY_FUNCTION__, MS) +#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__PRETTY_FUNCTION__, MS) #endif enum class WithExisting: int diff --git a/libdevcore/Worker.cpp b/libdevcore/Worker.cpp index 7d790ccf6..ab19b2f74 100644 --- a/libdevcore/Worker.cpp +++ b/libdevcore/Worker.cpp @@ -65,15 +65,15 @@ void Worker::startWorking() m_state.exchange(ex); // cnote << "Waiting until not Stopped..."; - DEV_TIMED_IF(Worker stopping, 100) + DEV_TIMED_ABOVE(Worker stopping, 100) while (m_state == WorkerState::Stopped) this_thread::sleep_for(chrono::milliseconds(20)); } })); // cnote << "Spawning" << m_name; } - DEV_TIMED_IF(Start worker, 100) - while (m_state != WorkerState::Started) + DEV_TIMED_ABOVE(Start worker, 100) + while (m_state == WorkerState::Starting) this_thread::sleep_for(chrono::microseconds(20)); } @@ -85,7 +85,7 @@ void Worker::stopWorking() WorkerState ex = WorkerState::Started; m_state.compare_exchange_strong(ex, WorkerState::Stopping); - DEV_TIMED_IF(Stop worker, 100) + DEV_TIMED_ABOVE(Stop worker, 100) while (m_state != WorkerState::Stopped) this_thread::sleep_for(chrono::microseconds(20)); } @@ -99,7 +99,7 @@ void Worker::terminate() { m_state.exchange(WorkerState::Killing); - DEV_TIMED_IF(Terminate worker, 100) + DEV_TIMED_ABOVE(Terminate worker, 100) m_work->join(); m_work.reset(); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index db1a17b0a..3724d8255 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -76,9 +76,9 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) return ret; } -void Ethash::prep(BlockInfo const& _header) +void Ethash::prep(BlockInfo const& _header, std::function const& _f) { - EthashAux::full(_header); + EthashAux::full((unsigned)_header.number, _f); } bool Ethash::preVerify(BlockInfo const& _header) @@ -310,6 +310,8 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; + if (!EthashAux::computeFull(w.blockNumber)) + return; EthashAux::FullType dag = EthashAux::full(w.blockNumber); bytesConstRef dagData = dag->data(); m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 1fcab55de..82db15e87 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -74,7 +74,7 @@ public: static std::string name(); static unsigned revision(); - static void prep(BlockInfo const& _header); + static void prep(BlockInfo const& _header, std::function const& _f = std::function()); static bool verify(BlockInfo const& _header); static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 7bcb976d6..f7a0ac41d 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -149,11 +149,6 @@ bytesConstRef EthashAux::FullAllocation::data() const return bytesConstRef((byte const*)ethash_full_dag(full), size()); } -EthashAux::FullType EthashAux::full(BlockInfo const& _header, function const& _f) -{ - return full((uint64_t)_header.number, _f); -} - static std::function s_dagCallback; static int dagCallbackShim(unsigned _p) { @@ -167,16 +162,43 @@ EthashAux::FullType EthashAux::full(uint64_t _blockNumber, functionx_fulls); - if ((ret = get()->m_fulls[seedHash].lock())) + DEV_GUARDED(get()->x_fulls) + if ((ret = get()->m_fulls[seedHash].lock())) + { + get()->m_lastUsedFull = ret; + return ret; + } + + s_dagCallback = _f; + ret = make_shared(l->light, dagCallbackShim); + + DEV_GUARDED(get()->x_fulls) + get()->m_fulls[seedHash] = get()->m_lastUsedFull = ret; + return ret; +} + +unsigned EthashAux::computeFull(uint64_t _blockNumber) +{ + Guard l(get()->x_fulls); + h256 seedHash = EthashAux::seedHash(_blockNumber); + if (FullType ret = get()->m_fulls[seedHash].lock()) { get()->m_lastUsedFull = ret; - return ret; + return 100; } - s_dagCallback = _f; - ret = get()->m_lastUsedFull = make_shared(l->light, dagCallbackShim); - get()->m_fulls[seedHash] = ret; - return ret; + + if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable()) + { + get()->m_fullProgress = 0; + get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; + get()->m_fullGenerator = unique_ptr(new thread([=](){ + get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }); + get()->m_fullProgress = 0; + get()->m_generatingFullNumber = NotGenerating; + })); + } + + return (get()->m_generatingFullNumber == _blockNumber) ? get()->m_fullProgress : 0; } Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index dbfe54d43..f57f7a4d3 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -19,7 +19,9 @@ * @date 2014 */ +#include #include +#include #include "Ethash.h" namespace dev @@ -65,7 +67,13 @@ public: static LightType light(BlockInfo const& _header); static LightType light(uint64_t _blockNumber); - static FullType full(BlockInfo const& _header, std::function const& _f = std::function()); + + static const uint64_t NotGenerating = (uint64_t)-1; + /// Kicks off generation of DAG for @a _blocknumber and @returns false or @returns true if ready. + static unsigned computeFull(uint64_t _blockNumber); + /// Information on the generation progress. + static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } + /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result. static FullType full(uint64_t _blockNumber, std::function const& _f = std::function()); static Ethash::Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); } @@ -83,8 +91,12 @@ private: std::unordered_map> m_lights; Mutex x_fulls; + std::condition_variable m_fullsChanged; std::unordered_map> m_fulls; FullType m_lastUsedFull; + std::unique_ptr m_fullGenerator; + uint64_t m_generatingFullNumber = NotGenerating; + unsigned m_fullProgress; Mutex x_epochs; std::unordered_map m_epochs; diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 235a6f540..2b271b1df 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -84,11 +84,11 @@ public: using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. - virtual ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; + virtual ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) override; using Interface::call; /// Makes the given create. Nothing is recorded into the state. - virtual ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; + virtual ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) override; using Interface::create; using Interface::balanceAt; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 50e4b26ab..584de461b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -515,10 +515,10 @@ pair State::sync(BlockChain const& _bc, TransactionQu cnote << i.first << "Dropping old transaction (nonce too low)"; _tq.drop(i.first); } - else if (got > req + 5) + else if (got > req + 25) { // too new - cnote << i.first << "Dropping new transaction (> 5 nonces ahead)"; + cnote << i.first << "Dropping new transaction (> 25 nonces ahead)"; _tq.drop(i.first); } else