diff --git a/libethcore/ProofOfWork.h b/libethcore/ProofOfWork.h index d942d06f7..64ce502af 100644 --- a/libethcore/ProofOfWork.h +++ b/libethcore/ProofOfWork.h @@ -51,7 +51,7 @@ class ProofOfWorkEngine: public Evaluator public: static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)Evaluator::eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; } - inline MineInfo mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false); + inline std::pair mine(h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false); protected: h256 m_last; @@ -79,14 +79,14 @@ using SHA3ProofOfWork = ProofOfWorkEngine; using ProofOfWork = SHA3ProofOfWork; template -MineInfo ProofOfWorkEngine::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) +std::pair ProofOfWorkEngine::mine(h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) { - MineInfo ret; + std::pair ret; static std::mt19937_64 s_eng((time(0) + (unsigned)m_last)); u256 s = (m_last = h256::random(s_eng)); bigint d = (bigint(1) << 256) / _difficulty; - ret.requirement = log2((double)d); + ret.first.requirement = log2((double)d); // 2^ 0 32 64 128 256 // [--------*-------------------------] @@ -95,20 +95,26 @@ MineInfo ProofOfWorkEngine::mine(h256& o_solution, h256 const& _root, auto startTime = std::chrono::steady_clock::now(); if (!_turbo) std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100)); - for (; (std::chrono::steady_clock::now() - startTime) < std::chrono::milliseconds(_msTimeout) && _continue; s++, ret.hashes++) + double best = 1e99; // high enough to be effectively infinity :) + h256 solution; + unsigned h = 0; + for (; (std::chrono::steady_clock::now() - startTime) < std::chrono::milliseconds(_msTimeout) && _continue; s++, h++) { - o_solution = (h256)s; - auto e = (bigint)(u256)Evaluator::eval(_root, o_solution); - ret.best = std::min(ret.best, log2((double)e)); + solution = (h256)s; + auto e = (bigint)(u256)Evaluator::eval(_root, solution); + best = std::min(best, log2((double)e)); if (e <= d) { - ret.completed = true; + ret.first.completed = true; break; } } + ret.first.hashes = h; + ret.first.best = best; + ret.second = solution; - if (ret.completed) - assert(verify(_root, o_solution, _difficulty)); + if (ret.first.completed) + assert(verify(_root, solution, _difficulty)); return ret; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 70b0cf26a..a42d1df99 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -126,7 +126,7 @@ void Client::killChain() m_tq.clear(); m_bq.clear(); - m_miners.clear(); + m_localMiners.clear(); m_preMine = State(); m_postMine = State(); @@ -167,8 +167,8 @@ void Client::clearPending() } { - ReadGuard l(x_miners); - for (auto& m: m_miners) + ReadGuard l(x_localMiners); + for (auto& m: m_localMiners) m.noteStateChange(); } @@ -320,8 +320,8 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed) void Client::setForceMining(bool _enable) { m_forceMining = _enable; - ReadGuard l(x_miners); - for (auto& m: m_miners) + ReadGuard l(x_localMiners); + for (auto& m: m_localMiners) m.noteStateChange(); } @@ -330,19 +330,19 @@ void Client::setMiningThreads(unsigned _threads) stopMining(); auto t = _threads ? _threads : thread::hardware_concurrency(); - WriteGuard l(x_miners); - m_miners.clear(); - m_miners.resize(t); + WriteGuard l(x_localMiners); + m_localMiners.clear(); + m_localMiners.resize(t); unsigned i = 0; - for (auto& m: m_miners) + for (auto& m: m_localMiners) m.setup(this, i++); } MineProgress Client::miningProgress() const { MineProgress ret; - ReadGuard l(x_miners); - for (auto& m: m_miners) + ReadGuard l(x_localMiners); + for (auto& m: m_localMiners) ret.combine(m.miningProgress()); return ret; } @@ -351,13 +351,13 @@ std::list Client::miningHistory() { std::list ret; - ReadGuard l(x_miners); - if (m_miners.empty()) + ReadGuard l(x_localMiners); + if (m_localMiners.empty()) return ret; - ret = m_miners[0].miningHistory(); - for (unsigned i = 1; i < m_miners.size(); ++i) + ret = m_localMiners[0].miningHistory(); + for (unsigned i = 1; i < m_localMiners.size(); ++i) { - auto l = m_miners[i].miningHistory(); + auto l = m_localMiners[i].miningHistory(); auto ri = ret.begin(); auto li = l.begin(); for (; ri != ret.end() && li != l.end(); ++ri, ++li) @@ -474,6 +474,22 @@ void Client::inject(bytesConstRef _rlp) m_tq.attemptImport(_rlp); } +pair Client::getWork() +{ + Guard l(x_remoteMiner); + { + ReadGuard l(x_stateDB); + m_remoteMiner.update(m_postMine, m_bc); + } + return make_pair(m_remoteMiner.workHash(), m_remoteMiner.difficulty()); +} + +bool Client::submitNonce(h256 const&_nonce) +{ + Guard l(x_remoteMiner); + return m_remoteMiner.submitWork(_nonce); +} + void Client::doWork() { // TODO: Use condition variable rather than polling. @@ -481,27 +497,34 @@ void Client::doWork() cworkin << "WORK"; h256Set changeds; + auto maintainMiner = [&](Miner& m) { - ReadGuard l(x_miners); - for (auto& m: m_miners) - if (m.isComplete()) + if (m.isComplete()) + { + cwork << "CHAIN <== postSTATE"; + h256s hs; { - cwork << "CHAIN <== postSTATE"; - h256s hs; - { - WriteGuard l(x_stateDB); - hs = m_bc.attemptImport(m.blockData(), m_stateDB); - } - if (hs.size()) - { - for (auto h: hs) - appendFromNewBlock(h, changeds); - changeds.insert(ChainChangedFilter); - //changeds.insert(PendingChangedFilter); // if we mined the new block, then we've probably reset the pending transactions. - } - for (auto& m: m_miners) - m.noteStateChange(); + WriteGuard l(x_stateDB); + hs = m_bc.attemptImport(m.blockData(), m_stateDB); + } + if (hs.size()) + { + for (auto const& h: hs) + appendFromNewBlock(h, changeds); + changeds.insert(ChainChangedFilter); } + for (auto& m: m_localMiners) + m.noteStateChange(); + } + }; + { + ReadGuard l(x_localMiners); + for (auto& m: m_localMiners) + maintainMiner(m); + } + { + Guard l(x_remoteMiner); + maintainMiner(m_remoteMiner); } // Synchronise state to block chain. @@ -511,7 +534,7 @@ void Client::doWork() // if there are no checkpoints before our fork) reverting to the genesis block and replaying // all blocks. // Resynchronise state with block chain & trans - bool rsm = false; + bool resyncStateNeeded = false; { WriteGuard l(x_stateDB); cwork << "BQ ==> CHAIN ==> STATE"; @@ -534,7 +557,7 @@ void Client::doWork() if (isMining()) cnote << "New block on chain: Restarting mining operation."; m_postMine = m_preMine; - rsm = true; + resyncStateNeeded = true; changeds.insert(PendingChangedFilter); // TODO: Move transactions pending from m_postMine back to transaction queue. } @@ -550,13 +573,13 @@ void Client::doWork() if (isMining()) cnote << "Additional transaction ready: Restarting mining operation."; - rsm = true; + resyncStateNeeded = true; } } - if (rsm) + if (resyncStateNeeded) { - ReadGuard l(x_miners); - for (auto& m: m_miners) + ReadGuard l(x_localMiners); + for (auto& m: m_localMiners) m.noteStateChange(); } diff --git a/libethereum/Client.h b/libethereum/Client.h index 48fe1fac3..ce3506bde 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -135,6 +135,28 @@ template T abiOut(bytes const& _data) return ABIDeserialiser::deserialise(o); } +class RemoteMiner: public Miner +{ +public: + RemoteMiner() {} + + void update(State const& _provisional, BlockChain const& _bc) { m_state = _provisional; m_state.commitToMine(_bc); } + + h256 workHash() const { return m_state.info().headerHash(IncludeNonce::WithoutNonce); } + u256 const& difficulty() const { return m_state.info().difficulty; } + + bool submitWork(h256 const& _nonce) { return (m_isComplete = m_state.completeMine(_nonce)); } + + virtual bool isComplete() const override { return m_isComplete; } + virtual bytes const& blockData() const { return m_state.blockData(); } + + virtual void noteStateChange() override {} + +private: + bool m_isComplete = false; + State m_state; +}; + /** * @brief Main API hub for interfacing with Ethereum. */ @@ -253,20 +275,26 @@ public: /// Stops mining and sets the number of mining threads (0 for automatic). virtual void setMiningThreads(unsigned _threads = 0); /// Get the effective number of mining threads. - virtual unsigned miningThreads() const { ReadGuard l(x_miners); return m_miners.size(); } + virtual unsigned miningThreads() const { ReadGuard l(x_localMiners); return m_localMiners.size(); } /// Start mining. /// NOT thread-safe - call it & stopMining only from a single thread - virtual void startMining() { startWorking(); ReadGuard l(x_miners); for (auto& m: m_miners) m.start(); } + virtual void startMining() { startWorking(); ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.start(); } /// Stop mining. /// NOT thread-safe - virtual void stopMining() { ReadGuard l(x_miners); for (auto& m: m_miners) m.stop(); } + virtual void stopMining() { ReadGuard l(x_localMiners); for (auto& m: m_localMiners) m.stop(); } /// Are we mining now? - virtual bool isMining() { ReadGuard l(x_miners); return m_miners.size() && m_miners[0].isRunning(); } + virtual bool isMining() { ReadGuard l(x_localMiners); return m_localMiners.size() && m_localMiners[0].isRunning(); } /// Check the progress of the mining. virtual MineProgress miningProgress() const; /// Get and clear the mining history. std::list miningHistory(); + /// Update to the latest transactions and get hash of the current block to be mined minus the + /// nonce (the 'work hash') and the difficulty to be met. + virtual std::pair getWork() override; + /// Submit the nonce for the proof-of-work. + virtual bool submitNonce(h256 const&_nonce) override; + // Debug stuff: DownloadMan const* downloadMan() const; @@ -295,6 +323,7 @@ private: /// Do some work. Handles blockchain maintenance and mining. virtual void doWork(); + /// Called when Worker is exiting. virtual void doneWorking(); /// Overrides for being a mining host. @@ -309,24 +338,27 @@ private: State asOf(unsigned _h) const; VersionChecker m_vc; ///< Dummy object to check & update the protocol version. - CanonBlockChain m_bc; ///< Maintains block database. + CanonBlockChain 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). - mutable SharedMutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine. + mutable SharedMutex 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::weak_ptr m_host; ///< Our Ethereum Host. Don't do anything if we can't lock. - std::vector m_miners; - mutable SharedMutex x_miners; + mutable Mutex x_remoteMiner; ///< The remote miner lock. + RemoteMiner m_remoteMiner; ///< The remote miner. + + std::vector m_localMiners; ///< The in-process miners. + mutable SharedMutex x_localMiners; ///< The in-process miners lock. bool m_paranoia = false; ///< Should we be paranoid about our state? bool m_turboMining = false; ///< Don't squander all of our time mining actually just sleeping. bool m_forceMining = false; ///< Mine even when there are no transactions pending? - mutable std::mutex m_filterLock; + mutable Mutex m_filterLock; std::map m_filters; std::map m_watches; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 35cd59663..09a134f1f 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -149,6 +149,11 @@ public: /// Are we mining now? virtual bool isMining() = 0; + /// Get hash of the current block to be mined minus the nonce (the 'work hash'). + virtual std::pair getWork() = 0; + /// Submit the nonce for the proof-of-work. + virtual bool submitNonce(h256 const&) = 0; + /// Check the progress of the mining. virtual MineProgress miningProgress() const = 0; diff --git a/libethereum/Miner.cpp b/libethereum/Miner.cpp index 638947a89..a049fca2f 100644 --- a/libethereum/Miner.cpp +++ b/libethereum/Miner.cpp @@ -15,8 +15,8 @@ along with cpp-ethereum. If not, see . */ /** @file Miner.cpp - * @author Alex Leverington * @author Gav Wood + * @author Giacomo Tazzari * @date 2014 */ @@ -28,19 +28,21 @@ using namespace std; using namespace dev; using namespace dev::eth; -Miner::Miner(MinerHost* _host, unsigned _id): +Miner::~Miner() {} + +LocalMiner::LocalMiner(MinerHost* _host, unsigned _id): Worker("miner-" + toString(_id)), m_host(_host) { } -void Miner::setup(MinerHost* _host, unsigned _id) +void LocalMiner::setup(MinerHost* _host, unsigned _id) { m_host = _host; setName("miner-" + toString(_id)); } -void Miner::doWork() +void LocalMiner::doWork() { // Do some mining. if (m_miningStatus != Waiting && m_miningStatus != Mined) @@ -63,7 +65,7 @@ void Miner::doWork() if (m_miningStatus == Mining) { - // Mine for a while. + // Mine for a while. MineInfo mineInfo = m_mineState.mine(100, m_host->turbo()); { diff --git a/libethereum/Miner.h b/libethereum/Miner.h index 358a0428b..fd449e995 100644 --- a/libethereum/Miner.h +++ b/libethereum/Miner.h @@ -63,6 +63,16 @@ public: virtual bool force() const = 0; ///< @returns true iff the Miner should mine regardless of the number of transactions. }; +class Miner +{ +public: + virtual ~Miner(); + + virtual void noteStateChange() = 0; + virtual bool isComplete() const = 0; + virtual bytes const& blockData() const = 0; +}; + /** * @brief Implements Miner. * To begin mining, use start() & stop(). noteStateChange() can be used to reset the mining and set up the @@ -75,23 +85,23 @@ public: * @threadsafe * @todo Signal Miner to restart once with condition variables. */ -class Miner: Worker +class LocalMiner: public Miner, Worker { public: /// Null constructor. - Miner(): m_host(nullptr) {} + LocalMiner(): m_host(nullptr) {} /// Constructor. - Miner(MinerHost* _host, unsigned _id = 0); + LocalMiner(MinerHost* _host, unsigned _id = 0); /// Move-constructor. - Miner(Miner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); } + LocalMiner(LocalMiner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); } /// Move-assignment. - Miner& operator=(Miner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); return *this; } + LocalMiner& operator=(LocalMiner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); return *this; } /// Destructor. Stops miner. - ~Miner() { stop(); } + ~LocalMiner() { stop(); } /// Setup its basics. void setup(MinerHost* _host, unsigned _id = 0); @@ -103,16 +113,16 @@ public: void stop() { stopWorking(); } /// Call to notify Miner of a state change. - void noteStateChange() { m_miningStatus = Preparing; } + virtual void noteStateChange() override { 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 isWorking(); } /// @returns true if mining is complete. - bool isComplete() const { return m_miningStatus == Mined; } + virtual bool isComplete() const override { return m_miningStatus == Mined; } /// @returns the internal State object. - bytes const& blockData() { return m_mineState.blockData(); } + virtual bytes const& blockData() const override { return m_mineState.blockData(); } /// Check the progress of the mining. MineProgress miningProgress() const { Guard l(x_mineInfo); return m_mineProgress; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index fd5f9187f..e44b81c83 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -774,19 +774,31 @@ MineInfo State::mine(unsigned _msTimeout, bool _turbo) // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); + MineInfo ret; // TODO: Miner class that keeps dagger between mine calls (or just non-polling mining). - auto ret = m_pow.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHash(WithoutNonce), m_currentBlock.difficulty, _msTimeout, true, _turbo); + tie(ret, m_currentBlock.nonce) = m_pow.mine(m_currentBlock.headerHash(WithoutNonce), m_currentBlock.difficulty, _msTimeout, true, _turbo); if (!ret.completed) m_currentBytes.clear(); else - { cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock.headerHash(WithoutNonce), m_currentBlock.nonce, m_currentBlock.difficulty); - } return ret; } +bool State::completeMine(h256 const& _nonce) +{ + if (!m_pow.verify(m_currentBlock.headerHash(WithoutNonce), _nonce, m_currentBlock.difficulty)) + return false; + + m_currentBlock.nonce = _nonce; + cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock.headerHash(WithoutNonce), m_currentBlock.nonce, m_currentBlock.difficulty); + + completeMine(); + + return true; +} + void State::completeMine() { cdebug << "Completing mine!"; diff --git a/libethereum/State.h b/libethereum/State.h index 65a333fb4..17e773a95 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -113,6 +113,10 @@ public: /// This may be called multiple times and without issue. void commitToMine(BlockChain const& _bc); + /// Pass in a solution to the proof-of-work. + /// @returns true iff the given nonce is a proof-of-work for this State's block. + bool completeMine(h256 const& _nonce); + /// Attempt to find valid nonce for block that this state represents. /// This function is thread-safe. You can safely have other interactions with this object while it is happening. /// @param _msTimeout Timeout before return in milliseconds. diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index d401c38fc..106842981 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -44,13 +44,13 @@ public: WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); private: - dev::eth::Interface* client() override; - std::shared_ptr face() override; - dev::WebThreeNetworkFace* network() override; - dev::WebThreeStubDatabaseFace* db() override; + virtual dev::eth::Interface* client() override; + virtual std::shared_ptr face() override; + virtual dev::WebThreeNetworkFace* network() override; + virtual dev::WebThreeStubDatabaseFace* db() override; - std::string get(std::string const& _name, std::string const& _key) override; - void put(std::string const& _name, std::string const& _key, std::string const& _value) override; + virtual std::string get(std::string const& _name, std::string const& _key) override; + virtual void put(std::string const& _name, std::string const& _key, std::string const& _value) override; private: dev::WebThreeDirect& m_web3; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 583645749..d4b6c9706 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -428,6 +428,21 @@ int WebThreeStubServerBase::eth_newFilterString(std::string const& _filter) return ret; } +Json::Value WebThreeStubServerBase::eth_getWork() +{ + Json::Value ret(Json::arrayValue); + auto r = client()->getWork(); + ret.append(toJS(r.first)); + ret.append(toJS(r.second)); + return ret; +} + +int WebThreeStubServerBase::eth_submitWork(std::string const& _nonce) +{ + client()->submitNonce(jsToFixed<32>(_nonce)); + return 0; +} + std::string WebThreeStubServerBase::shh_newGroup(std::string const& _id, std::string const& _who) { (void)_id; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index ffb9e1738..cf279a082 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -103,6 +103,9 @@ public: virtual Json::Value eth_uncleByNumber(int const& _number, int const& _i); virtual bool eth_uninstallFilter(int const& _id); + virtual Json::Value eth_getWork(); + virtual int eth_submitWork(std::string const& _nonce); + virtual std::string db_get(std::string const& _name, std::string const& _key); virtual std::string db_getString(std::string const& _name, std::string const& _key); virtual bool db_put(std::string const& _name, std::string const& _key, std::string const& _value); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 0c25f9842..9d4b4f467 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -49,6 +49,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_getWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_getWorkI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_submitWork", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_submitWorkI); this->bindAndAddMethod(new jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI); this->bindAndAddMethod(new jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI); this->bindAndAddMethod(new jsonrpc::Procedure("db_putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putStringI); @@ -211,6 +213,14 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_logs(request[0u]); } + inline virtual void eth_getWorkI(const Json::Value &request, Json::Value &response) + { + response = this->eth_getWork(); + } + inline virtual void eth_submitWorkI(const Json::Value &request, Json::Value &response) + { + response = this->eth_submitWork(request[0u].asString()); + } inline virtual void db_putI(const Json::Value &request, Json::Value &response) { response = this->db_put(request[0u].asString(), request[1u].asString(), request[2u].asString()); @@ -296,6 +306,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer getWork() override { return std::pair(); } + bool submitNonce(h256 const&) override { return false; } private: void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);