Browse Source

Remote mining hook.

cl-refactor
Gav Wood 10 years ago
parent
commit
0de7d63dc1
  1. 28
      libethcore/ProofOfWork.h
  2. 103
      libethereum/Client.cpp
  3. 50
      libethereum/Client.h
  4. 5
      libethereum/Interface.h
  5. 12
      libethereum/Miner.cpp
  6. 28
      libethereum/Miner.h
  7. 18
      libethereum/State.cpp
  8. 4
      libethereum/State.h
  9. 12
      libweb3jsonrpc/WebThreeStubServer.h
  10. 15
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  11. 3
      libweb3jsonrpc/WebThreeStubServerBase.h
  12. 12
      libweb3jsonrpc/abstractwebthreestubserver.h
  13. 4
      libweb3jsonrpc/spec.json
  14. 2
      mix/MixClient.h

28
libethcore/ProofOfWork.h

@ -51,7 +51,7 @@ class ProofOfWorkEngine: public Evaluator
public: public:
static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)Evaluator::eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; } 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<MineInfo, h256> mine(h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
protected: protected:
h256 m_last; h256 m_last;
@ -79,14 +79,14 @@ using SHA3ProofOfWork = ProofOfWorkEngine<SHA3Evaluator>;
using ProofOfWork = SHA3ProofOfWork; using ProofOfWork = SHA3ProofOfWork;
template <class Evaluator> template <class Evaluator>
MineInfo ProofOfWorkEngine<Evaluator>::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) std::pair<MineInfo, h256> ProofOfWorkEngine<Evaluator>::mine(h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo)
{ {
MineInfo ret; std::pair<MineInfo, h256> ret;
static std::mt19937_64 s_eng((time(0) + (unsigned)m_last)); static std::mt19937_64 s_eng((time(0) + (unsigned)m_last));
u256 s = (m_last = h256::random(s_eng)); u256 s = (m_last = h256::random(s_eng));
bigint d = (bigint(1) << 256) / _difficulty; bigint d = (bigint(1) << 256) / _difficulty;
ret.requirement = log2((double)d); ret.first.requirement = log2((double)d);
// 2^ 0 32 64 128 256 // 2^ 0 32 64 128 256
// [--------*-------------------------] // [--------*-------------------------]
@ -95,20 +95,26 @@ MineInfo ProofOfWorkEngine<Evaluator>::mine(h256& o_solution, h256 const& _root,
auto startTime = std::chrono::steady_clock::now(); auto startTime = std::chrono::steady_clock::now();
if (!_turbo) if (!_turbo)
std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100)); 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; solution = (h256)s;
auto e = (bigint)(u256)Evaluator::eval(_root, o_solution); auto e = (bigint)(u256)Evaluator::eval(_root, solution);
ret.best = std::min<double>(ret.best, log2((double)e)); best = std::min<double>(best, log2((double)e));
if (e <= d) if (e <= d)
{ {
ret.completed = true; ret.first.completed = true;
break; break;
} }
} }
ret.first.hashes = h;
ret.first.best = best;
ret.second = solution;
if (ret.completed) if (ret.first.completed)
assert(verify(_root, o_solution, _difficulty)); assert(verify(_root, solution, _difficulty));
return ret; return ret;
} }

103
libethereum/Client.cpp

@ -126,7 +126,7 @@ void Client::killChain()
m_tq.clear(); m_tq.clear();
m_bq.clear(); m_bq.clear();
m_miners.clear(); m_localMiners.clear();
m_preMine = State(); m_preMine = State();
m_postMine = State(); m_postMine = State();
@ -167,8 +167,8 @@ void Client::clearPending()
} }
{ {
ReadGuard l(x_miners); ReadGuard l(x_localMiners);
for (auto& m: m_miners) for (auto& m: m_localMiners)
m.noteStateChange(); m.noteStateChange();
} }
@ -320,8 +320,8 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
void Client::setForceMining(bool _enable) void Client::setForceMining(bool _enable)
{ {
m_forceMining = _enable; m_forceMining = _enable;
ReadGuard l(x_miners); ReadGuard l(x_localMiners);
for (auto& m: m_miners) for (auto& m: m_localMiners)
m.noteStateChange(); m.noteStateChange();
} }
@ -330,19 +330,19 @@ void Client::setMiningThreads(unsigned _threads)
stopMining(); stopMining();
auto t = _threads ? _threads : thread::hardware_concurrency(); auto t = _threads ? _threads : thread::hardware_concurrency();
WriteGuard l(x_miners); WriteGuard l(x_localMiners);
m_miners.clear(); m_localMiners.clear();
m_miners.resize(t); m_localMiners.resize(t);
unsigned i = 0; unsigned i = 0;
for (auto& m: m_miners) for (auto& m: m_localMiners)
m.setup(this, i++); m.setup(this, i++);
} }
MineProgress Client::miningProgress() const MineProgress Client::miningProgress() const
{ {
MineProgress ret; MineProgress ret;
ReadGuard l(x_miners); ReadGuard l(x_localMiners);
for (auto& m: m_miners) for (auto& m: m_localMiners)
ret.combine(m.miningProgress()); ret.combine(m.miningProgress());
return ret; return ret;
} }
@ -351,13 +351,13 @@ std::list<MineInfo> Client::miningHistory()
{ {
std::list<MineInfo> ret; std::list<MineInfo> ret;
ReadGuard l(x_miners); ReadGuard l(x_localMiners);
if (m_miners.empty()) if (m_localMiners.empty())
return ret; return ret;
ret = m_miners[0].miningHistory(); ret = m_localMiners[0].miningHistory();
for (unsigned i = 1; i < m_miners.size(); ++i) 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 ri = ret.begin();
auto li = l.begin(); auto li = l.begin();
for (; ri != ret.end() && li != l.end(); ++ri, ++li) for (; ri != ret.end() && li != l.end(); ++ri, ++li)
@ -474,6 +474,22 @@ void Client::inject(bytesConstRef _rlp)
m_tq.attemptImport(_rlp); m_tq.attemptImport(_rlp);
} }
pair<h256, u256> 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() void Client::doWork()
{ {
// TODO: Use condition variable rather than polling. // TODO: Use condition variable rather than polling.
@ -481,27 +497,34 @@ void Client::doWork()
cworkin << "WORK"; cworkin << "WORK";
h256Set changeds; h256Set changeds;
auto maintainMiner = [&](Miner& m)
{ {
ReadGuard l(x_miners); if (m.isComplete())
for (auto& m: m_miners) {
if (m.isComplete()) cwork << "CHAIN <== postSTATE";
h256s hs;
{ {
cwork << "CHAIN <== postSTATE"; WriteGuard l(x_stateDB);
h256s hs; hs = m_bc.attemptImport(m.blockData(), m_stateDB);
{ }
WriteGuard l(x_stateDB); if (hs.size())
hs = m_bc.attemptImport(m.blockData(), m_stateDB); {
} for (auto const& h: hs)
if (hs.size()) appendFromNewBlock(h, changeds);
{ changeds.insert(ChainChangedFilter);
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();
} }
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. // 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 // if there are no checkpoints before our fork) reverting to the genesis block and replaying
// all blocks. // all blocks.
// Resynchronise state with block chain & trans // Resynchronise state with block chain & trans
bool rsm = false; bool resyncStateNeeded = false;
{ {
WriteGuard l(x_stateDB); WriteGuard l(x_stateDB);
cwork << "BQ ==> CHAIN ==> STATE"; cwork << "BQ ==> CHAIN ==> STATE";
@ -534,7 +557,7 @@ void Client::doWork()
if (isMining()) if (isMining())
cnote << "New block on chain: Restarting mining operation."; cnote << "New block on chain: Restarting mining operation.";
m_postMine = m_preMine; m_postMine = m_preMine;
rsm = true; resyncStateNeeded = true;
changeds.insert(PendingChangedFilter); changeds.insert(PendingChangedFilter);
// TODO: Move transactions pending from m_postMine back to transaction queue. // TODO: Move transactions pending from m_postMine back to transaction queue.
} }
@ -550,13 +573,13 @@ void Client::doWork()
if (isMining()) if (isMining())
cnote << "Additional transaction ready: Restarting mining operation."; cnote << "Additional transaction ready: Restarting mining operation.";
rsm = true; resyncStateNeeded = true;
} }
} }
if (rsm) if (resyncStateNeeded)
{ {
ReadGuard l(x_miners); ReadGuard l(x_localMiners);
for (auto& m: m_miners) for (auto& m: m_localMiners)
m.noteStateChange(); m.noteStateChange();
} }

50
libethereum/Client.h

@ -135,6 +135,28 @@ template <class T> T abiOut(bytes const& _data)
return ABIDeserialiser<T>::deserialise(o); return ABIDeserialiser<T>::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. * @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). /// Stops mining and sets the number of mining threads (0 for automatic).
virtual void setMiningThreads(unsigned _threads = 0); virtual void setMiningThreads(unsigned _threads = 0);
/// Get the effective number of mining threads. /// 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. /// Start mining.
/// NOT thread-safe - call it & stopMining only from a single thread /// 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. /// Stop mining.
/// NOT thread-safe /// 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? /// 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. /// Check the progress of the mining.
virtual MineProgress miningProgress() const; virtual MineProgress miningProgress() const;
/// Get and clear the mining history. /// Get and clear the mining history.
std::list<MineInfo> miningHistory(); std::list<MineInfo> 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<h256, u256> getWork() override;
/// Submit the nonce for the proof-of-work.
virtual bool submitNonce(h256 const&_nonce) override;
// Debug stuff: // Debug stuff:
DownloadMan const* downloadMan() const; DownloadMan const* downloadMan() const;
@ -295,6 +323,7 @@ private:
/// Do some work. Handles blockchain maintenance and mining. /// Do some work. Handles blockchain maintenance and mining.
virtual void doWork(); virtual void doWork();
/// Called when Worker is exiting.
virtual void doneWorking(); virtual void doneWorking();
/// Overrides for being a mining host. /// Overrides for being a mining host.
@ -309,24 +338,27 @@ private:
State asOf(unsigned _h) const; State asOf(unsigned _h) const;
VersionChecker m_vc; ///< Dummy object to check & update the protocol version. 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. 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). 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. 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_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). State m_postMine; ///< The state of the client which we're mining (i.e. it'll have all the rewards added).
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock. std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::vector<Miner> m_miners; mutable Mutex x_remoteMiner; ///< The remote miner lock.
mutable SharedMutex x_miners; RemoteMiner m_remoteMiner; ///< The remote miner.
std::vector<LocalMiner> 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_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_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? bool m_forceMining = false; ///< Mine even when there are no transactions pending?
mutable std::mutex m_filterLock; mutable Mutex m_filterLock;
std::map<h256, InstalledFilter> m_filters; std::map<h256, InstalledFilter> m_filters;
std::map<unsigned, ClientWatch> m_watches; std::map<unsigned, ClientWatch> m_watches;

5
libethereum/Interface.h

@ -149,6 +149,11 @@ public:
/// Are we mining now? /// Are we mining now?
virtual bool isMining() = 0; virtual bool isMining() = 0;
/// Get hash of the current block to be mined minus the nonce (the 'work hash').
virtual std::pair<h256, u256> getWork() = 0;
/// Submit the nonce for the proof-of-work.
virtual bool submitNonce(h256 const&) = 0;
/// Check the progress of the mining. /// Check the progress of the mining.
virtual MineProgress miningProgress() const = 0; virtual MineProgress miningProgress() const = 0;

12
libethereum/Miner.cpp

@ -15,8 +15,8 @@
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file Miner.cpp /** @file Miner.cpp
* @author Alex Leverington <nessence@gmail.com>
* @author Gav Wood <i@gavwood.com> * @author Gav Wood <i@gavwood.com>
* @author Giacomo Tazzari
* @date 2014 * @date 2014
*/ */
@ -28,19 +28,21 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
Miner::Miner(MinerHost* _host, unsigned _id): Miner::~Miner() {}
LocalMiner::LocalMiner(MinerHost* _host, unsigned _id):
Worker("miner-" + toString(_id)), Worker("miner-" + toString(_id)),
m_host(_host) m_host(_host)
{ {
} }
void Miner::setup(MinerHost* _host, unsigned _id) void LocalMiner::setup(MinerHost* _host, unsigned _id)
{ {
m_host = _host; m_host = _host;
setName("miner-" + toString(_id)); setName("miner-" + toString(_id));
} }
void Miner::doWork() void LocalMiner::doWork()
{ {
// Do some mining. // Do some mining.
if (m_miningStatus != Waiting && m_miningStatus != Mined) if (m_miningStatus != Waiting && m_miningStatus != Mined)
@ -63,7 +65,7 @@ void Miner::doWork()
if (m_miningStatus == Mining) if (m_miningStatus == Mining)
{ {
// Mine for a while. // Mine for a while.
MineInfo mineInfo = m_mineState.mine(100, m_host->turbo()); MineInfo mineInfo = m_mineState.mine(100, m_host->turbo());
{ {

28
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. 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. * @brief Implements Miner.
* To begin mining, use start() & stop(). noteStateChange() can be used to reset the mining and set up the * To begin mining, use start() & stop(). noteStateChange() can be used to reset the mining and set up the
@ -75,23 +85,23 @@ public:
* @threadsafe * @threadsafe
* @todo Signal Miner to restart once with condition variables. * @todo Signal Miner to restart once with condition variables.
*/ */
class Miner: Worker class LocalMiner: public Miner, Worker
{ {
public: public:
/// Null constructor. /// Null constructor.
Miner(): m_host(nullptr) {} LocalMiner(): m_host(nullptr) {}
/// Constructor. /// Constructor.
Miner(MinerHost* _host, unsigned _id = 0); LocalMiner(MinerHost* _host, unsigned _id = 0);
/// Move-constructor. /// 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. /// 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. /// Destructor. Stops miner.
~Miner() { stop(); } ~LocalMiner() { stop(); }
/// Setup its basics. /// Setup its basics.
void setup(MinerHost* _host, unsigned _id = 0); void setup(MinerHost* _host, unsigned _id = 0);
@ -103,16 +113,16 @@ public:
void stop() { stopWorking(); } void stop() { stopWorking(); }
/// Call to notify Miner of a state change. /// 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(). /// @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(); } bool isRunning() { return isWorking(); }
/// @returns true if mining is complete. /// @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. /// @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. /// Check the progress of the mining.
MineProgress miningProgress() const { Guard l(x_mineInfo); return m_mineProgress; } MineProgress miningProgress() const { Guard l(x_mineInfo); return m_mineProgress; }

18
libethereum/State.cpp

@ -774,19 +774,31 @@ MineInfo State::mine(unsigned _msTimeout, bool _turbo)
// Update difficulty according to timestamp. // Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
MineInfo ret;
// TODO: Miner class that keeps dagger between mine calls (or just non-polling mining). // 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) if (!ret.completed)
m_currentBytes.clear(); m_currentBytes.clear();
else 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); 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; 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() void State::completeMine()
{ {
cdebug << "Completing mine!"; cdebug << "Completing mine!";

4
libethereum/State.h

@ -113,6 +113,10 @@ public:
/// This may be called multiple times and without issue. /// This may be called multiple times and without issue.
void commitToMine(BlockChain const& _bc); 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. /// 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. /// 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. /// @param _msTimeout Timeout before return in milliseconds.

12
libweb3jsonrpc/WebThreeStubServer.h

@ -44,13 +44,13 @@ public:
WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts); WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts);
private: private:
dev::eth::Interface* client() override; virtual dev::eth::Interface* client() override;
std::shared_ptr<dev::shh::Interface> face() override; virtual std::shared_ptr<dev::shh::Interface> face() override;
dev::WebThreeNetworkFace* network() override; virtual dev::WebThreeNetworkFace* network() override;
dev::WebThreeStubDatabaseFace* db() override; virtual dev::WebThreeStubDatabaseFace* db() override;
std::string get(std::string const& _name, std::string const& _key) override; virtual 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 void put(std::string const& _name, std::string const& _key, std::string const& _value) override;
private: private:
dev::WebThreeDirect& m_web3; dev::WebThreeDirect& m_web3;

15
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -428,6 +428,21 @@ int WebThreeStubServerBase::eth_newFilterString(std::string const& _filter)
return ret; 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) std::string WebThreeStubServerBase::shh_newGroup(std::string const& _id, std::string const& _who)
{ {
(void)_id; (void)_id;

3
libweb3jsonrpc/WebThreeStubServerBase.h

@ -103,6 +103,9 @@ public:
virtual Json::Value eth_uncleByNumber(int const& _number, int const& _i); virtual Json::Value eth_uncleByNumber(int const& _number, int const& _i);
virtual bool eth_uninstallFilter(int const& _id); 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_get(std::string const& _name, std::string const& _key);
virtual std::string db_getString(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); virtual bool db_put(std::string const& _name, std::string const& _key, std::string const& _value);

12
libweb3jsonrpc/abstractwebthreestubserver.h

@ -49,6 +49,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
this->bindAndAddMethod(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_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_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_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_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_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); 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::AbstractServer<AbstractWebThr
{ {
response = this->eth_logs(request[0u]); response = this->eth_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) 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()); response = this->db_put(request[0u].asString(), request[1u].asString(), request[2u].asString());
@ -296,6 +306,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual Json::Value eth_changed(const int& param1) = 0; virtual Json::Value eth_changed(const int& param1) = 0;
virtual Json::Value eth_filterLogs(const int& param1) = 0; virtual Json::Value eth_filterLogs(const int& param1) = 0;
virtual Json::Value eth_logs(const Json::Value& param1) = 0; virtual Json::Value eth_logs(const Json::Value& param1) = 0;
virtual Json::Value eth_getWork() = 0;
virtual int eth_submitWork(const std::string& param1) = 0;
virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0;
virtual std::string db_get(const std::string& param1, const std::string& param2) = 0; virtual std::string db_get(const std::string& param1, const std::string& param2) = 0;
virtual bool db_putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0; virtual bool db_putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0;

4
libweb3jsonrpc/spec.json

@ -36,7 +36,6 @@
{ "name": "eth_solidity", "params": [""], "order": [], "returns": ""}, { "name": "eth_solidity", "params": [""], "order": [], "returns": ""},
{ "name": "eth_serpent", "params": [""], "order": [], "returns": ""}, { "name": "eth_serpent", "params": [""], "order": [], "returns": ""},
{ "name": "eth_newFilter", "params": [{}], "order": [], "returns": 0}, { "name": "eth_newFilter", "params": [{}], "order": [], "returns": 0},
{ "name": "eth_newFilterString", "params": [""], "order": [], "returns": 0}, { "name": "eth_newFilterString", "params": [""], "order": [], "returns": 0},
{ "name": "eth_uninstallFilter", "params": [0], "order": [], "returns": true}, { "name": "eth_uninstallFilter", "params": [0], "order": [], "returns": true},
@ -44,6 +43,9 @@
{ "name": "eth_filterLogs", "params": [0], "order": [], "returns": []}, { "name": "eth_filterLogs", "params": [0], "order": [], "returns": []},
{ "name": "eth_logs", "params": [{}], "order": [], "returns": []}, { "name": "eth_logs", "params": [{}], "order": [], "returns": []},
{ "name": "eth_getWork", "params": [], "order": [], "returns": []},
{ "name": "eth_submitWork", "params": [""], "order": [], "returns": 0},
{ "name": "db_put", "params": ["", "", ""], "order": [], "returns": true}, { "name": "db_put", "params": ["", "", ""], "order": [], "returns": true},
{ "name": "db_get", "params": ["", ""], "order": [], "returns": ""}, { "name": "db_get", "params": ["", ""], "order": [], "returns": ""},
{ "name": "db_putString", "params": ["", "", ""], "order": [], "returns": true}, { "name": "db_putString", "params": ["", "", ""], "order": [], "returns": true},

2
mix/MixClient.h

@ -86,6 +86,8 @@ public:
void stopMining() override; void stopMining() override;
bool isMining() override; bool isMining() override;
eth::MineProgress miningProgress() const override; eth::MineProgress miningProgress() const override;
std::pair<h256, u256> getWork() override { return std::pair<h256, u256>(); }
bool submitNonce(h256 const&) override { return false; }
private: private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state); void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);

Loading…
Cancel
Save