diff --git a/alethzero/MainFace.cpp b/alethzero/MainFace.cpp index 4b2236e76..5c9651f73 100644 --- a/alethzero/MainFace.cpp +++ b/alethzero/MainFace.cpp @@ -25,6 +25,18 @@ using namespace std; using namespace dev; using namespace az; +void AccountNamer::noteKnownChanged() +{ + if (m_main) + m_main->noteKnownAddressesChanged(this); +} + +void AccountNamer::noteNamesChanged() +{ + if (m_main) + m_main->noteAddressNamesChanged(this); +} + void MainFace::notePlugin(std::function const& _new) { if (!s_linkedPlugins) diff --git a/alethzero/MainFace.h b/alethzero/MainFace.h index 21dbd80b0..525cc312d 100644 --- a/alethzero/MainFace.h +++ b/alethzero/MainFace.h @@ -47,15 +47,26 @@ namespace az static bool s_notePlugin = [](){ MainFace::notePlugin([](MainFace* m){ return new ClassName(m); }); return true; }() class Plugin; +class MainFace; +class Main; using WatchHandler = std::function; class AccountNamer { + friend class Main; + public: virtual std::string toName(Address const&) const { return std::string(); } virtual Address toAddress(std::string const&) const { return Address(); } virtual Addresses knownAddresses() const { return Addresses(); } + +protected: + void noteKnownChanged(); + void noteNamesChanged(); + +private: + MainFace* m_main = nullptr; }; class MainFace: public QMainWindow, public Context @@ -86,7 +97,8 @@ public: // Account naming API virtual void install(AccountNamer* _adopt) = 0; virtual void uninstall(AccountNamer* _kill) = 0; - virtual void noteAddressesChanged() = 0; + virtual void noteKnownAddressesChanged(AccountNamer*) = 0; + virtual void noteAddressNamesChanged(AccountNamer*) = 0; virtual Address toAddress(std::string const&) const = 0; virtual std::string toName(Address const&) const = 0; virtual Addresses allKnownAddresses() const = 0; @@ -100,7 +112,8 @@ protected: static std::vector>* s_linkedPlugins; signals: - void allKnownAddressesChanged(); + void knownAddressesChanged(); + void addressNamesChanged(); void keyManagerChanged(); private: diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a05911781..26dec2345 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -309,6 +309,7 @@ string Main::fromRaw(h256 const& _n, unsigned* _inc) void Main::install(AccountNamer* _adopt) { m_namers.insert(_adopt); + _adopt->m_main = this; refreshAll(); } @@ -319,9 +320,15 @@ void Main::uninstall(AccountNamer* _kill) refreshAll(); } -void Main::noteAddressesChanged() +void Main::noteKnownAddressesChanged(AccountNamer*) { - emit allKnownAddressesChanged(); + emit knownAddressesChanged(); + refreshAll(); +} + +void Main::noteAddressNamesChanged(AccountNamer*) +{ + emit addressNamesChanged(); refreshAll(); } @@ -1234,7 +1241,13 @@ void Main::refreshBalances() for (auto const& address: m_keyManager.accounts()) { u256 b = ethereum()->balanceAt(address); - QListWidgetItem* li = new QListWidgetItem(QString("<%5> %4 %2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(address))).arg((unsigned)ethereum()->countAt(address)).arg(QString::fromStdString(m_keyManager.accountName(address))).arg(m_keyManager.haveKey(address) ? "KEY" : "BRAIN"), ui->ourAccounts); + QListWidgetItem* li = new QListWidgetItem( + QString("<%1> %2: %3 [%4]") + .arg(m_keyManager.haveKey(address) ? "KEY" : "BRAIN") + .arg(QString::fromStdString(render(address))) + .arg(formatBalance(b).c_str()) + .arg((unsigned)ethereum()->countAt(address)) + , ui->ourAccounts); li->setData(Qt::UserRole, QByteArray((char const*)address.data(), Address::size)); li->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); li->setCheckState(m_beneficiary == address ? Qt::Checked : Qt::Unchecked); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 86b15e78a..b23a33697 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -109,7 +109,8 @@ public: // Account naming API. void install(AccountNamer* _adopt) override; void uninstall(AccountNamer* _kill) override; - void noteAddressesChanged() override; + void noteKnownAddressesChanged(AccountNamer*) override; + void noteAddressNamesChanged(AccountNamer*) override; Address toAddress(std::string const&) const override; std::string toName(Address const&) const override; Addresses allKnownAddresses() const override; diff --git a/alethzero/OtherAccounts.cpp b/alethzero/OtherAccounts.cpp index 1ad7fd109..fc2d518bc 100644 --- a/alethzero/OtherAccounts.cpp +++ b/alethzero/OtherAccounts.cpp @@ -54,7 +54,7 @@ void OtherAccounts::import() m_toAddress[name] = addr; } main()->noteSettingsChanged(); - main()->noteAddressesChanged(); + noteKnownChanged(); } } @@ -71,6 +71,7 @@ void OtherAccounts::readSettings(QSettings const& _s) m_toAddress[l[1].toStdString()] = Address(l[0].toStdString()); } } + noteKnownChanged(); } void OtherAccounts::writeSettings(QSettings& _s) diff --git a/alethzero/OurAccounts.cpp b/alethzero/OurAccounts.cpp index 0e8b8820c..7f868af05 100644 --- a/alethzero/OurAccounts.cpp +++ b/alethzero/OurAccounts.cpp @@ -63,4 +63,5 @@ void OurAccounts::updateNames() m_names.clear(); for (Address const& i: main()->keyManager().accounts()) m_names[main()->keyManager().accountName(i)] = i; + noteKnownChanged(); } diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 61175496e..7e239bc1c 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -139,7 +139,7 @@ void Transact::updateDestination() for (Address const& a: m_main->allKnownAddresses()) { cdebug << "Adding" << a << m_main->toName(a) << " -> " << (m_main->toName(a) + " (" + ICAP(a).encoded() + ")"); - ui->destination->addItem(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QVariant(QByteArray((char const*)a.data(), a.size))); + ui->destination->addItem(QString::fromStdString(m_main->toName(a) + " (" + ICAP(a).encoded() + ")"), QString::fromStdString(a.hex())); } } @@ -167,8 +167,8 @@ void Transact::on_destination_currentTextChanged(QString) if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") { pair p; - if (!ui->destination->currentData().isNull()) - p.first = Address(bytesConstRef((uint8_t const*)ui->destination->currentData().toByteArray().data_ptr(), 20)); + if (!ui->destination->currentData().isNull() && ui->destination->currentText() == ui->destination->itemText(ui->destination->currentIndex())) + p.first = Address(ui->destination->currentData().toString().toStdString()); else p = m_main->fromString(ui->destination->currentText().toStdString()); diff --git a/ethminer/Farm.h b/ethminer/Farm.h deleted file mode 100644 index ae2ef5a7d..000000000 --- a/ethminer/Farm.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! - */ - -#ifndef JSONRPC_CPP_STUB_FARM_H_ -#define JSONRPC_CPP_STUB_FARM_H_ - -#include - -class Farm : public jsonrpc::Client -{ - public: - Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} - - Json::Value eth_getWork() throw (jsonrpc::JsonRpcException) - { - Json::Value p; - p = Json::nullValue; - Json::Value result = this->CallMethod("eth_getWork",p); - if (result.isArray()) - return result; - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - } - bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) - { - Json::Value p; - p.append(param1); - p.append(param2); - p.append(param3); - Json::Value result = this->CallMethod("eth_submitWork",p); - if (result.isBool()) - return result.asBool(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - } -}; - -#endif //JSONRPC_CPP_STUB_FARM_H_ diff --git a/ethminer/FarmClient.h b/ethminer/FarmClient.h new file mode 100644 index 000000000..7f5f29182 --- /dev/null +++ b/ethminer/FarmClient.h @@ -0,0 +1,70 @@ +/** + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! + */ + +#ifndef JSONRPC_CPP_STUB_FARMCLIENT_H_ +#define JSONRPC_CPP_STUB_FARMCLIENT_H_ + +#include + +class FarmClient : public jsonrpc::Client +{ + public: + FarmClient(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} + + Json::Value eth_getWork() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->CallMethod("eth_getWork",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + p.append(param2); + p.append(param3); + Json::Value result = this->CallMethod("eth_submitWork",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + bool eth_submitHashrate(int param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + p.append(param2); + Json::Value result = this->CallMethod("eth_submitHashrate",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + Json::Value eth_awaitNewWork() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->CallMethod("eth_awaitNewWork",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + bool eth_progress() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->CallMethod("eth_progress",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } +}; + +#endif //JSONRPC_CPP_STUB_FARMCLIENT_H_ diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index a378312ed..2f20d7db8 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -52,7 +52,7 @@ #include "BuildInfo.h" #if ETH_JSONRPC || !ETH_TRUE #include "PhoneHome.h" -#include "Farm.h" +#include "FarmClient.h" #endif using namespace std; using namespace dev; @@ -482,7 +482,8 @@ private: #if ETH_JSONRPC || !ETH_TRUE jsonrpc::HttpClient client(_remote); - Farm rpc(client); + h256 id = h256::random(); + ::FarmClient rpc(client); GenericFarm f; f.setSealers(sealers); if (_m == MinerType::CPU) @@ -504,10 +505,16 @@ private: }); for (unsigned i = 0; !completed; ++i) { + auto mp = f.miningProgress(); + f.resetMiningProgress(); if (current) - minelog << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); + minelog << "Mining on PoWhash" << current.headerHash << ": " << mp; else minelog << "Getting work package..."; + + auto rate = mp.rate(); + rpc.eth_submitHashrate((int)rate, "0x" + id.hex()); + Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); h256 newSeedHash(v[1].asString()); diff --git a/ethminer/farm.json b/ethminer/farm.json index ff0a2e9e7..4d4981510 100644 --- a/ethminer/farm.json +++ b/ethminer/farm.json @@ -1,6 +1,7 @@ [ { "name": "eth_getWork", "params": [], "order": [], "returns": []}, - { "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true} + { "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true}, + { "name": "eth_submitHashrate", "params": [0, ""], "order": [], "returns": true}, { "name": "eth_awaitNewWork", "params": [], "order": [], "returns": []}, { "name": "eth_progress", "params": [], "order": [], "returns": true} ] diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 2631a28cb..3a6087ea5 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -509,9 +509,10 @@ WorkingProgress Client::miningProgress() const uint64_t Client::hashrate() const { + uint64_t r = externalHashrate(); if (Ethash::isWorking(m_sealEngine.get())) - return Ethash::workingProgress(m_sealEngine.get()).rate(); - return 0; + r += Ethash::workingProgress(m_sealEngine.get()).rate(); + return r; } std::list Client::miningHistory() diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 60ac3f32d..f11d533a6 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -21,7 +21,7 @@ */ #include "ClientBase.h" - +#include #include #include "BlockChain.h" #include "Executive.h" @@ -492,11 +492,10 @@ int ClientBase::compareBlockHashes(h256 _h1, h256 _h2) const BlockNumber n1 = numberFromHash(_h1); BlockNumber n2 = numberFromHash(_h2); - if (n1 > n2) { + if (n1 > n2) return 1; - } else if (n1 == n2) { + else if (n1 == n2) return 0; - } return -1; } @@ -524,3 +523,19 @@ bool ClientBase::isKnownTransaction(h256 const& _blockHash, unsigned _i) const { return isKnown(_blockHash) && bc().transactions().size() > _i; } + +void ClientBase::submitExternalHashrate(int _rate, h256 const& _id) +{ + m_externalRates[_id] = make_pair(_rate, chrono::steady_clock::now()); +} + +uint64_t ClientBase::externalHashrate() const +{ + uint64_t ret = 0; + for (auto i = m_externalRates.begin(); i != m_externalRates.end();) + if (chrono::steady_clock::now() - i->second.second > chrono::seconds(5)) + i = m_externalRates.erase(i); + else + ret += i++->second.first; + return ret; +} diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 8cbc31be2..e5e93e5d1 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -167,6 +167,8 @@ public: virtual uint64_t hashrate() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::hashrate")); } virtual WorkingProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::miningProgress")); } + virtual void submitExternalHashrate(int _rate, h256 const& _id) override; + Block asOf(BlockNumber _h) const; protected: @@ -180,6 +182,8 @@ protected: virtual void prepareForTransaction() = 0; /// } + uint64_t externalHashrate() const; + TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. // filters @@ -188,6 +192,9 @@ protected: std::unordered_map m_specialFilters = std::unordered_map>{{PendingChangedFilter, {}}, {ChainChangedFilter, {}}}; ///< The dictionary of special filters and their additional data std::map m_watches; ///< Each and every watch - these reference a filter. + + // external hashrate + mutable std::unordered_map> m_externalRates; }; }} diff --git a/libethereum/Interface.h b/libethereum/Interface.h index ef35d808c..9c109000f 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -217,7 +217,8 @@ public: virtual std::tuple getEthashWork() { BOOST_THROW_EXCEPTION(InterfaceNotSupported("Interface::getEthashWork")); } /// Submit the nonce for the proof-of-work. virtual bool submitEthashWork(h256 const&, h64 const&) { BOOST_THROW_EXCEPTION(InterfaceNotSupported("Interface::submitEthashWork")); } - + /// Submit the ongoing hashrate of a particular external miner. + virtual void submitExternalHashrate(int, h256 const&) { BOOST_THROW_EXCEPTION(InterfaceNotSupported("Interface::submitExternalHashrate")); } /// Check the progress of the mining. virtual WorkingProgress miningProgress() const = 0; diff --git a/libp2p/Capability.cpp b/libp2p/Capability.cpp index 2b8e6be63..21cd09686 100644 --- a/libp2p/Capability.cpp +++ b/libp2p/Capability.cpp @@ -35,7 +35,7 @@ Capability::Capability(std::shared_ptr _s, HostCapabilityFace* _h, unsi void Capability::disable(std::string const& _problem) { - clog(NetNote) << "DISABLE: Disabling capability '" << m_hostCap->name() << "'. Reason:" << _problem; + clog(NetTriviaSummary) << "DISABLE: Disabling capability '" << m_hostCap->name() << "'. Reason:" << _problem; m_enabled = false; } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index e5d442acb..03b2be8d8 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -780,6 +780,12 @@ bool WebThreeStubServerBase::eth_submitWork(string const& _nonce, string const&, } } +bool WebThreeStubServerBase::eth_submitHashrate(int _hashes, string const& _id) +{ + client()->submitExternalHashrate(_hashes, jsToFixed<32>(_id)); + return true; +} + string WebThreeStubServerBase::eth_register(string const& _address) { try diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index 8160c6cac..f4ca99d83 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -139,6 +139,7 @@ public: virtual Json::Value eth_getLogsEx(Json::Value const& _json); virtual Json::Value eth_getWork(); virtual bool eth_submitWork(std::string const& _nonce, std::string const&, std::string const& _mixHash); + virtual bool eth_submitHashrate(int _hashes, std::string const& _id); virtual std::string eth_register(std::string const& _address); virtual bool eth_unregister(std::string const& _accountId); virtual Json::Value eth_fetchQueuedTransactions(std::string const& _accountId); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 6ae546931..0009fdcc2 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -60,6 +60,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("eth_getLogsEx", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_getLogsExI); this->bindAndAddMethod(jsonrpc::Procedure("eth_getWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_getWorkI); this->bindAndAddMethod(jsonrpc::Procedure("eth_submitWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_submitWorkI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_submitHashrate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_submitHashrateI); this->bindAndAddMethod(jsonrpc::Procedure("eth_register", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_registerI); this->bindAndAddMethod(jsonrpc::Procedure("eth_unregister", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_unregisterI); this->bindAndAddMethod(jsonrpc::Procedure("eth_fetchQueuedTransactions", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_fetchQueuedTransactionsI); @@ -312,6 +313,10 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_submitWork(request[0u].asString(), request[1u].asString(), request[2u].asString()); } + inline virtual void eth_submitHashrateI(const Json::Value &request, Json::Value &response) + { + response = this->eth_submitHashrate(request[0u].asInt(), request[1u].asString()); + } inline virtual void eth_registerI(const Json::Value &request, Json::Value &response) { response = this->eth_register(request[0u].asString()); @@ -529,6 +534,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerCallMethod("eth_submitHashrate",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } std::string eth_register(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p;