Browse Source

Can grab block info from JS. Stephan will be pleased.

cl-refactor
Gav Wood 11 years ago
parent
commit
8bf5251d5a
  1. 23
      libethereum/Client.cpp
  2. 68
      libethereum/Client.h
  3. 9
      libethereum/Interface.h
  4. 1
      libp2p/Session.h
  5. 87
      libqethereum/QEthereum.cpp
  6. 20
      libqethereum/QEthereum.h

23
libethereum/Client.cpp

@ -232,12 +232,9 @@ void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const
void Client::setForceMining(bool _enable) void Client::setForceMining(bool _enable)
{ {
m_forceMining = _enable; m_forceMining = _enable;
if (!m_host.lock()) ReadGuard l(x_miners);
{ for (auto& m: m_miners)
ReadGuard l(x_miners); m.noteStateChange();
for (auto& m: m_miners)
m.noteStateChange();
}
} }
void Client::setMiningThreads(unsigned _threads) void Client::setMiningThreads(unsigned _threads)
@ -550,6 +547,20 @@ bytes Client::codeAt(Address _a, int _block) const
return asOf(_block).code(_a); return asOf(_block).code(_a);
} }
Transaction Client::transaction(h256 _blockHash, unsigned _i) const
{
auto bl = m_bc.block(_blockHash);
RLP b(bl);
return Transaction(b[1][_i].data());
}
BlockInfo Client::uncle(h256 _blockHash, unsigned _i) const
{
auto bl = m_bc.block(_blockHash);
RLP b(bl);
return BlockInfo::fromHeader(b[2][_i].data());
}
PastMessages Client::messages(MessageFilter const& _f) const PastMessages Client::messages(MessageFilter const& _f) const
{ {
PastMessages ret; PastMessages ret;

68
libethereum/Client.h

@ -119,23 +119,23 @@ public:
explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0); explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0);
/// Destructor. /// Destructor.
~Client(); virtual ~Client();
/// Submits the given message-call transaction. /// Submits the given message-call transaction.
void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); virtual void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
/// Submits a new contract-creation transaction. /// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through). /// @returns the new contract's address (assuming it all goes through).
Address transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo); virtual Address transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly. /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
void inject(bytesConstRef _rlp); virtual void inject(bytesConstRef _rlp);
/// Blocks until all pending transactions have been processed. /// Blocks until all pending transactions have been processed.
void flushTransactions(); virtual void flushTransactions();
/// Makes the given call. Nothing is recorded into the state. /// Makes the given call. Nothing is recorded into the state.
bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); virtual bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
// Informational stuff // Informational stuff
@ -147,20 +147,20 @@ public:
using Interface::codeAt; using Interface::codeAt;
using Interface::storageAt; using Interface::storageAt;
u256 balanceAt(Address _a, int _block) const; virtual u256 balanceAt(Address _a, int _block) const;
u256 countAt(Address _a, int _block) const; virtual u256 countAt(Address _a, int _block) const;
u256 stateAt(Address _a, u256 _l, int _block) const; virtual u256 stateAt(Address _a, u256 _l, int _block) const;
bytes codeAt(Address _a, int _block) const; virtual bytes codeAt(Address _a, int _block) const;
std::map<u256, u256> storageAt(Address _a, int _block) const; virtual std::map<u256, u256> storageAt(Address _a, int _block) const;
unsigned installWatch(MessageFilter const& _filter); virtual unsigned installWatch(MessageFilter const& _filter);
unsigned installWatch(h256 _filterId); virtual unsigned installWatch(h256 _filterId);
void uninstallWatch(unsigned _watchId); virtual void uninstallWatch(unsigned _watchId);
bool peekWatch(unsigned _watchId) const { std::lock_guard<std::mutex> l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } } virtual bool peekWatch(unsigned _watchId) const { std::lock_guard<std::mutex> l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } }
bool checkWatch(unsigned _watchId) { std::lock_guard<std::mutex> l(m_filterLock); bool ret = false; try { ret = m_watches.at(_watchId).changes != 0; m_watches.at(_watchId).changes = 0; } catch (...) {} return ret; } virtual bool checkWatch(unsigned _watchId) { std::lock_guard<std::mutex> l(m_filterLock); bool ret = false; try { ret = m_watches.at(_watchId).changes != 0; m_watches.at(_watchId).changes = 0; } catch (...) {} return ret; }
PastMessages messages(unsigned _watchId) const { try { std::lock_guard<std::mutex> l(m_filterLock); return messages(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return PastMessages(); } } virtual PastMessages messages(unsigned _watchId) const { try { std::lock_guard<std::mutex> l(m_filterLock); return messages(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return PastMessages(); } }
PastMessages messages(MessageFilter const& _filter) const; virtual PastMessages messages(MessageFilter const& _filter) const;
// [EXTRA API]: // [EXTRA API]:
@ -169,19 +169,25 @@ public:
/// Get a map containing each of the pending transactions. /// Get a map containing each of the pending transactions.
/// @TODO: Remove in favour of transactions(). /// @TODO: Remove in favour of transactions().
Transactions pending() const { return m_postMine.pending(); } virtual Transactions pending() const { return m_postMine.pending(); }
virtual h256 hashFromNumber(unsigned _number) const { return m_bc.numberHash(_number); }
virtual BlockInfo blockInfo(h256 _hash) const { return BlockInfo(m_bc.block(_hash)); }
virtual BlockDetails blockDetails(h256 _hash) const { return m_bc.details(_hash); }
virtual Transaction transaction(h256 _blockHash, unsigned _i) const;
virtual BlockInfo uncle(h256 _blockHash, unsigned _i) const;
/// Differences between transactions. /// Differences between transactions.
using Interface::diff; using Interface::diff;
StateDiff diff(unsigned _txi, h256 _block) const; virtual StateDiff diff(unsigned _txi, h256 _block) const;
StateDiff diff(unsigned _txi, int _block) const; virtual StateDiff diff(unsigned _txi, int _block) const;
/// Get a list of all active addresses. /// Get a list of all active addresses.
using Interface::addresses; using Interface::addresses;
std::vector<Address> addresses(int _block) const; virtual std::vector<Address> addresses(int _block) const;
/// Get the remaining gas limit in this block. /// Get the remaining gas limit in this block.
u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); } virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); }
// [PRIVATE API - only relevant for base clients, not available in general] // [PRIVATE API - only relevant for base clients, not available in general]
@ -210,23 +216,23 @@ public:
void setTurboMining(bool _enable = true) { m_turboMining = _enable; } void setTurboMining(bool _enable = true) { m_turboMining = _enable; }
/// Set the coinbase address. /// Set the coinbase address.
void setAddress(Address _us) { m_preMine.setAddress(_us); } virtual void setAddress(Address _us) { m_preMine.setAddress(_us); }
/// Get the coinbase address. /// Get the coinbase address.
Address address() const { return m_preMine.address(); } virtual Address address() const { return m_preMine.address(); }
/// Stops mining and sets the number of mining threads (0 for automatic). /// Stops mining and sets the number of mining threads (0 for automatic).
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.
unsigned miningThreads() const { ReadGuard l(x_miners); return m_miners.size(); } virtual unsigned miningThreads() const { ReadGuard l(x_miners); return m_miners.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
void startMining() { startWorking(); ReadGuard l(x_miners); for (auto& m: m_miners) m.start(); } virtual void startMining() { startWorking(); ReadGuard l(x_miners); for (auto& m: m_miners) m.start(); }
/// Stop mining. /// Stop mining.
/// NOT thread-safe /// NOT thread-safe
void stopMining() { ReadGuard l(x_miners); for (auto& m: m_miners) m.stop(); } virtual void stopMining() { ReadGuard l(x_miners); for (auto& m: m_miners) m.stop(); }
/// Are we mining now? /// Are we mining now?
bool isMining() { ReadGuard l(x_miners); return m_miners.size() && m_miners[0].isRunning(); } virtual bool isMining() { ReadGuard l(x_miners); return m_miners.size() && m_miners[0].isRunning(); }
/// Check the progress of the mining. /// Check the progress of the mining.
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();

9
libethereum/Interface.h

@ -29,6 +29,7 @@
#include "MessageFilter.h" #include "MessageFilter.h"
#include "Transaction.h" #include "Transaction.h"
#include "AccountDiff.h" #include "AccountDiff.h"
#include "BlockDetails.h"
#include "Miner.h" #include "Miner.h"
namespace dev namespace dev
@ -95,7 +96,13 @@ public:
virtual bool peekWatch(unsigned _watchId) const = 0; virtual bool peekWatch(unsigned _watchId) const = 0;
virtual bool checkWatch(unsigned _watchId) = 0; virtual bool checkWatch(unsigned _watchId) = 0;
// TODO: Block query API. // [BLOCK QUERY API]
virtual h256 hashFromNumber(unsigned _number) const = 0;
virtual BlockInfo blockInfo(h256 _hash) const = 0;
virtual BlockDetails blockDetails(h256 _hash) const = 0;
virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0;
virtual BlockInfo uncle(h256 _blockHash, unsigned _i) const = 0;
// [EXTRA API]: // [EXTRA API]:

1
libp2p/Session.h

@ -110,6 +110,7 @@ private:
unsigned m_rating; unsigned m_rating;
std::map<CapDesc, std::shared_ptr<Capability>> m_capabilities; std::map<CapDesc, std::shared_ptr<Capability>> m_capabilities;
std::set<h512> m_knownPeers;
bool m_willBeDeleted = false; ///< True if we already posted a deleter on the strand. bool m_willBeDeleted = false; ///< True if we already posted a deleter on the strand.
}; };

87
libqethereum/QEthereum.cpp

@ -336,6 +336,93 @@ static QString toJson(dev::eth::PastMessages const& _pms)
return QString::fromUtf8(QJsonDocument(jsonArray).toJson()); return QString::fromUtf8(QJsonDocument(jsonArray).toJson());
} }
static QString toJson(dev::eth::BlockInfo const& _bi, dev::eth::BlockDetails const& _bd)
{
QJsonObject v;
v["hash"] = toQJS(_bi.hash);
v["parentHash"] = toQJS(_bi.parentHash);
v["sha3Uncles"] = toQJS(_bi.sha3Uncles);
v["miner"] = toQJS(_bi.coinbaseAddress);
v["stateRoot"] = toQJS(_bi.stateRoot);
v["transactionsRoot"] = toQJS(_bi.transactionsRoot);
v["difficulty"] = toQJS(_bi.difficulty);
v["number"] = (int)_bi.number;
v["minGasPrice"] = toQJS(_bi.minGasPrice);
v["gasLimit"] = (int)_bi.gasLimit;
v["gasUsed"] = (int)_bi.gasUsed;
v["timestamp"] = (int)_bi.timestamp;
v["extraData"] = ::fromBinary(_bi.extraData);
v["nonce"] = toQJS(_bi.nonce);
QJsonArray children;
for (auto c: _bd.children)
children.append(toQJS(c));
v["children"] = children;
v["totalDifficulty"] = toQJS(_bd.totalDifficulty);
v["bloom"] = toQJS(_bd.bloom);
return QString::fromUtf8(QJsonDocument(v).toJson());
}
static QString toJson(dev::eth::BlockInfo const& _bi)
{
QJsonObject v;
v["hash"] = toQJS(_bi.hash);
v["parentHash"] = toQJS(_bi.parentHash);
v["sha3Uncles"] = toQJS(_bi.sha3Uncles);
v["miner"] = toQJS(_bi.coinbaseAddress);
v["stateRoot"] = toQJS(_bi.stateRoot);
v["transactionsRoot"] = toQJS(_bi.transactionsRoot);
v["difficulty"] = toQJS(_bi.difficulty);
v["number"] = (int)_bi.number;
v["minGasPrice"] = toQJS(_bi.minGasPrice);
v["gasLimit"] = (int)_bi.gasLimit;
v["gasUsed"] = (int)_bi.gasUsed;
v["timestamp"] = (int)_bi.timestamp;
v["extraData"] = ::fromBinary(_bi.extraData);
v["nonce"] = toQJS(_bi.nonce);
return QString::fromUtf8(QJsonDocument(v).toJson());
}
static QString toJson(dev::eth::Transaction const& _bi)
{
QJsonObject v;
v["hash"] = toQJS(_bi.sha3());
v["input"] = ::fromBinary(_bi.data);
v["to"] = toQJS(_bi.receiveAddress);
v["from"] = toQJS(_bi.sender());
v["gas"] = (int)_bi.gas;
v["gasPrice"] = toQJS(_bi.gasPrice);
v["nonce"] = toQJS(_bi.nonce);
v["value"] = toQJS(_bi.value);
return QString::fromUtf8(QJsonDocument(v).toJson());
}
QString QEthereum::getUncle(QString _numberOrHash, int _i) const
{
auto n = toU256(_numberOrHash);
auto h = n < m_client->number() ? m_client->hashFromNumber((unsigned)n) : ::toFixed<32>(_numberOrHash);
return m_client ? toJson(m_client->uncle(h, _i)) : "";
}
QString QEthereum::getTransaction(QString _numberOrHash, int _i) const
{
auto n = toU256(_numberOrHash);
auto h = n < m_client->number() ? m_client->hashFromNumber((unsigned)n) : ::toFixed<32>(_numberOrHash);
return m_client ? toJson(m_client->transaction(h, _i)) : "";
}
QString QEthereum::getBlock(QString _numberOrHash) const
{
auto n = toU256(_numberOrHash);
auto h = n < m_client->number() ? m_client->hashFromNumber((unsigned)n) : ::toFixed<32>(_numberOrHash);
return m_client ? toJson(m_client->blockInfo(h), m_client->blockDetails(h)) : "";
}
QString QEthereum::getMessages(QString _json) const QString QEthereum::getMessages(QString _json) const
{ {
return m_client ? toJson(m_client->messages(toMessageFilter(_json))) : ""; return m_client ? toJson(m_client->messages(toMessageFilter(_json))) : "";

20
libqethereum/QEthereum.h

@ -148,6 +148,10 @@ public:
Q_INVOKABLE QString/*dev::u256*/ stateAt(QString/*dev::Address*/ _a, QString/*dev::u256*/ _p) const; Q_INVOKABLE QString/*dev::u256*/ stateAt(QString/*dev::Address*/ _a, QString/*dev::u256*/ _p) const;
Q_INVOKABLE QString/*dev::u256*/ codeAt(QString/*dev::Address*/ _a) const; Q_INVOKABLE QString/*dev::u256*/ codeAt(QString/*dev::Address*/ _a) const;
Q_INVOKABLE QString/*json*/ getBlock(QString _numberOrHash/*unsigned if < number(), hash otherwise*/) const;
Q_INVOKABLE QString/*json*/ getTransaction(QString _numberOrHash/*unsigned if < number(), hash otherwise*/, int _index) const;
Q_INVOKABLE QString/*json*/ getUncle(QString _numberOrHash/*unsigned if < number(), hash otherwise*/, int _index) const;
Q_INVOKABLE QString/*json*/ getMessages(QString _attribs/*json*/) const; Q_INVOKABLE QString/*json*/ getMessages(QString _attribs/*json*/) const;
Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice); Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice);
@ -255,20 +259,12 @@ private:
frame->addToJavaScriptWindowObject("shh", eth, QWebFrame::ScriptOwnership); \ frame->addToJavaScriptWindowObject("shh", eth, QWebFrame::ScriptOwnership); \
frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \ frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \
frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \ frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \
frame->evaluateJavaScript("eth.watchChain = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.watch('chain') INSTEAD.'); return eth.makeWatch('chain') }"); \ frame->evaluateJavaScript("eth.transact = function(a, f) { var r = eth.doTransact(JSON.stringify(a)); if (f) f(r); }"); \
frame->evaluateJavaScript("eth.watchPending = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.watch('pending') INSTEAD.'); return eth.makeWatch('pending') }"); \
frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { env.warn('THIS CALL IS DEPRECATED. USE eth.transact INSTEAD.'); var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \
frame->evaluateJavaScript("eth.transact = function(a_s, f_v, t, d, g, p, f) { if (t == null) { var r = eth.doTransact(JSON.stringify(a_s)); if (f_v) f_v(r); } else { env.warn('THIS FORM OF THIS CALL IS DEPRECATED.'); eth.doTransact(a_s, f_v, t, d, g, p); if (f) f() } }"); \
frame->evaluateJavaScript("eth.call = function(a, f) { var ret = eth.doCallJson(JSON.stringify(a)); if (f) f(ret); return ret; }"); \ frame->evaluateJavaScript("eth.call = function(a, f) { var ret = eth.doCallJson(JSON.stringify(a)); if (f) f(ret); return ret; }"); \
frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \
frame->evaluateJavaScript("eth.transactions = function(a) { env.warn('THIS CALL IS DEPRECATED. USE eth.messages INSTEAD.'); return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ frame->evaluateJavaScript("eth.block = function(a) { return JSON.parse(eth.getBlock(a)); }"); \
frame->evaluateJavaScript("String.prototype.pad = function(l, r) { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.pad(this, l, r) }"); \ frame->evaluateJavaScript("eth.transaction = function(a) { return JSON.parse(eth.getTransaction(a)); }"); \
frame->evaluateJavaScript("String.prototype.bin = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.toAscii(this) }"); \ frame->evaluateJavaScript("eth.uncle = function(a) { return JSON.parse(eth.getUncle(a)); }"); \
frame->evaluateJavaScript("String.prototype.unbin = function(l) { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.fromAscii(this) }"); \
frame->evaluateJavaScript("String.prototype.unpad = function(l) { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.unpad(this) }"); \
frame->evaluateJavaScript("String.prototype.dec = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.toDecimal(this) }"); \
frame->evaluateJavaScript("String.prototype.fix = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.toFixed(this) }"); \
frame->evaluateJavaScript("String.prototype.sha3 = function() { env.warn('THIS CALL IS DEPRECATED. USE eth.* INSTEAD.'); return eth.sha3old(this) }"); \
frame->evaluateJavaScript("shh.makeWatch = function(a) { var ww = shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { shh.killWatch(w); }; ret.changed = function(f) { shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(shh.watchMessages(this.w)) }; return ret; }"); \ frame->evaluateJavaScript("shh.makeWatch = function(a) { var ww = shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { shh.killWatch(w); }; ret.changed = function(f) { shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(shh.watchMessages(this.w)) }; return ret; }"); \
frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \ frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \
} }

Loading…
Cancel
Save