Browse Source

Nearly complete differential changelog system.

cl-refactor
Gav Wood 11 years ago
parent
commit
0d2f5439ce
  1. 9
      alethzero/MainWin.cpp
  2. 24
      libethereum/Client.cpp
  3. 6
      libethereum/Client.h
  4. 77
      libqethereum/QEthereum.cpp
  5. 7
      libqethereum/QEthereum.h

9
alethzero/MainWin.cpp

@ -212,6 +212,10 @@ Main::Main(QWidget *parent) :
Main::~Main() Main::~Main()
{ {
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
m_ethereum->clientDieing();
g_logPost = simpleDebugOut; g_logPost = simpleDebugOut;
writeSettings(); writeSettings();
} }
@ -379,7 +383,8 @@ void Main::eval(QString const& _js)
{ {
if (_js.trimmed().isEmpty()) if (_js.trimmed().isEmpty())
return; return;
QVariant ev = ui->webView->page()->currentFrame()->evaluateJavaScript(_js); QVariant ev = ui->webView->page()->currentFrame()->evaluateJavaScript("___RET=(" + _js + ")");
QVariant jsonEv = ui->webView->page()->currentFrame()->evaluateJavaScript("JSON.stringify(__RET)");
QString s; QString s;
if (ev.isNull()) if (ev.isNull())
s = "<span style=\"color: #888\">null</span>"; s = "<span style=\"color: #888\">null</span>";
@ -387,6 +392,8 @@ void Main::eval(QString const& _js)
s = "<span style=\"color: #444\">\"</span><span style=\"color: #c00\">" + ev.toString().toHtmlEscaped() + "</span><span style=\"color: #444\">\"</span>"; s = "<span style=\"color: #444\">\"</span><span style=\"color: #c00\">" + ev.toString().toHtmlEscaped() + "</span><span style=\"color: #444\">\"</span>";
else if (ev.type() == QVariant::Int || ev.type() == QVariant::Double) else if (ev.type() == QVariant::Int || ev.type() == QVariant::Double)
s = "<span style=\"color: #00c\">" + ev.toString().toHtmlEscaped() + "</span>"; s = "<span style=\"color: #00c\">" + ev.toString().toHtmlEscaped() + "</span>";
else if (jsonEv.type() == QVariant::String)
s = "<span style=\"color: #840\">" + jsonEv.toString().toHtmlEscaped() + "</span>";
else else
s = "<span style=\"color: #888\">unknown type</span>"; s = "<span style=\"color: #888\">unknown type</span>";
m_consoleHistory.push_back(qMakePair(_js, s)); m_consoleHistory.push_back(qMakePair(_js, s));

24
libethereum/Client.cpp

@ -153,20 +153,20 @@ void Client::uninstallWatch(unsigned _i)
auto it = m_watches.find(_i); auto it = m_watches.find(_i);
if (it == m_watches.end()) if (it == m_watches.end())
return; return;
auto id = it->second.id;
m_watches.erase(it);
auto fit = m_filters.find(it->second.id); auto fit = m_filters.find(id);
if (fit != m_filters.end()) if (fit != m_filters.end())
if (!--fit->second.refCount) if (!--fit->second.refCount)
m_filters.erase(fit); m_filters.erase(fit);
m_watches.erase(it);
} }
void Client::appendFromNewPending(h256 _bloom, h256Set& o_changed) const void Client::appendFromNewPending(h256 _bloom, h256Set& o_changed) const
{ {
lock_guard<mutex> l(m_filterLock); lock_guard<mutex> l(m_filterLock);
for (pair<h256, InstalledFilter> const& i: m_filters) for (pair<h256, InstalledFilter> const& i: m_filters)
if (numberOf(i.second.filter.latest()) == m_postMine.info().number && i.second.filter.matches(_bloom)) if ((unsigned)i.second.filter.latest() >= m_postMine.info().number && i.second.filter.matches(_bloom))
o_changed.insert(i.first); o_changed.insert(i.first);
} }
@ -176,7 +176,7 @@ void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const
lock_guard<mutex> l(m_filterLock); lock_guard<mutex> l(m_filterLock);
for (pair<h256, InstalledFilter> const& i: m_filters) for (pair<h256, InstalledFilter> const& i: m_filters)
if (numberOf(i.second.filter.latest()) >= d.number && i.second.filter.matches(d.bloom)) if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.bloom))
o_changed.insert(i.first); o_changed.insert(i.first);
} }
@ -587,13 +587,13 @@ PastMessages Client::transactions(TransactionFilter const& _f) const
ClientGuard l(this); ClientGuard l(this);
PastMessages ret; PastMessages ret;
unsigned begin = numberOf(_f.latest()); unsigned begin = min<unsigned>(m_bc.number(), (unsigned)_f.latest());
unsigned end = min(begin, numberOf(_f.earliest())); unsigned end = min(begin, (unsigned)_f.earliest());
unsigned m = _f.max(); unsigned m = _f.max();
unsigned s = _f.skip(); unsigned s = _f.skip();
// Handle pending transactions differently as they're not on the block chain. // Handle pending transactions differently as they're not on the block chain.
if (_f.latest() == 0) if (begin == m_bc.number())
{ {
for (unsigned i = 0; i < m_postMine.pending().size(); ++i) for (unsigned i = 0; i < m_postMine.pending().size(); ++i)
{ {
@ -608,19 +608,15 @@ PastMessages Client::transactions(TransactionFilter const& _f) const
s--; s--;
else else
// Have a transaction that contains a matching message. // Have a transaction that contains a matching message.
ret.insert(ret.begin(), pm[j].polish(h256(), ts, 0)); ret.insert(ret.begin(), pm[j].polish(h256(), ts, m_bc.number() + 1));
} }
} }
// Early exit here since we can't rely on begin/end, being out of the blockchain as we are.
if (_f.earliest() == 0)
return ret;
} }
#if ETH_DEBUG #if ETH_DEBUG
unsigned skipped = 0; unsigned skipped = 0;
unsigned falsePos = 0; unsigned falsePos = 0;
#endif #endif
auto cn = m_bc.number();
auto h = m_bc.numberHash(begin); auto h = m_bc.numberHash(begin);
unsigned n = begin; unsigned n = begin;
for (; ret.size() != m && n != end; n--, h = m_bc.details(h).parent) for (; ret.size() != m && n != end; n--, h = m_bc.details(h).parent)
@ -653,7 +649,7 @@ PastMessages Client::transactions(TransactionFilter const& _f) const
s--; s--;
else else
// Have a transaction that contains a matching message. // Have a transaction that contains a matching message.
ret.insert(ret.begin(), pm[j].polish(h, ts, cn - n + 2)); ret.insert(ret.begin(), pm[j].polish(h, ts, n));
} }
} }
#if ETH_DEBUG #if ETH_DEBUG

6
libethereum/Client.h

@ -102,7 +102,7 @@ typedef std::vector<PastMessage> PastMessages;
class TransactionFilter class TransactionFilter
{ {
public: public:
TransactionFilter(int _earliest = GenesisBlock, int _latest = 0, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} TransactionFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {}
void fillStream(RLPStream& _s) const; void fillStream(RLPStream& _s) const;
h256 sha3() const; h256 sha3() const;
@ -131,8 +131,8 @@ private:
std::set<Address> m_to; std::set<Address> m_to;
std::set<std::pair<Address, u256>> m_stateAltered; std::set<std::pair<Address, u256>> m_stateAltered;
std::set<Address> m_altered; std::set<Address> m_altered;
int m_earliest; int m_earliest = 0;
int m_latest; int m_latest = -1;
unsigned m_max; unsigned m_max;
unsigned m_skip; unsigned m_skip;
}; };

77
libqethereum/QEthereum.cpp

@ -97,11 +97,18 @@ QEthereum::~QEthereum()
clearWatches(); clearWatches();
} }
void QEthereum::clientDieing()
{
clearWatches();
m_client = nullptr;
}
void QEthereum::clearWatches() void QEthereum::clearWatches()
{ {
for (auto i: m_watches) if (m_client)
m_client->uninstallWatch(i); for (auto i: m_watches)
m_watches.clear(); m_client->uninstallWatch(i);
m_watches.clear();
} }
QString QEthereum::secretToAddress(QString _s) const QString QEthereum::secretToAddress(QString _s) const
@ -135,12 +142,12 @@ QString QEthereum::sha3(QString _s) const
QString QEthereum::coinbase() const QString QEthereum::coinbase() const
{ {
return toQJS(client()->address()); return m_client ? toQJS(client()->address()) : "";
} }
QString QEthereum::number() const QString QEthereum::number() const
{ {
return QString::number(client()->blockChain().number() + 1); return m_client ? QString::number(client()->blockChain().number() + 1) : "";
} }
QString QEthereum::account() const QString QEthereum::account() const
@ -175,7 +182,7 @@ QStringList QEthereum::keys() const
void QEthereum::setCoinbase(QString _a) void QEthereum::setCoinbase(QString _a)
{ {
if (client()->address() != toAddress(_a)) if (m_client && client()->address() != toAddress(_a))
{ {
client()->setAddress(toAddress(_a)); client()->setAddress(toAddress(_a));
coinbaseChanged(); coinbaseChanged();
@ -184,58 +191,75 @@ void QEthereum::setCoinbase(QString _a)
QString QEthereum::balanceAt(QString _a) const QString QEthereum::balanceAt(QString _a) const
{ {
return toQJS(client()->postState().balance(toAddress(_a))); return m_client ? toQJS(client()->postState().balance(toAddress(_a))) : "";
} }
QString QEthereum::storageAt(QString _a, QString _p) const QString QEthereum::storageAt(QString _a, QString _p) const
{ {
if (!m_client)
return "";
eth::ClientGuard l(const_cast<Client*>(m_client)); eth::ClientGuard l(const_cast<Client*>(m_client));
return toQJS(client()->postState().storage(toAddress(_a), toU256(_p))); return toQJS(client()->postState().storage(toAddress(_a), toU256(_p)));
} }
double QEthereum::txCountAt(QString _a) const double QEthereum::txCountAt(QString _a) const
{ {
if (!m_client)
return 0.0;
eth::ClientGuard l(const_cast<Client*>(m_client));
return (double)client()->postState().transactionsFrom(toAddress(_a)); return (double)client()->postState().transactionsFrom(toAddress(_a));
} }
bool QEthereum::isContractAt(QString _a) const bool QEthereum::isContractAt(QString _a) const
{ {
if (!m_client)
return false;
eth::ClientGuard l(const_cast<Client*>(m_client));
return client()->postState().addressHasCode(toAddress(_a)); return client()->postState().addressHasCode(toAddress(_a));
} }
u256 QEthereum::balanceAt(Address _a) const u256 QEthereum::balanceAt(Address _a) const
{ {
if (!m_client)
return 0;
eth::ClientGuard l(const_cast<Client*>(m_client));
return client()->postState().balance(_a); return client()->postState().balance(_a);
} }
double QEthereum::txCountAt(Address _a) const double QEthereum::txCountAt(Address _a) const
{ {
if (!m_client)
return 0.0;
eth::ClientGuard l(const_cast<Client*>(m_client));
return (double)client()->postState().transactionsFrom(_a); return (double)client()->postState().transactionsFrom(_a);
} }
bool QEthereum::isContractAt(Address _a) const bool QEthereum::isContractAt(Address _a) const
{ {
if (!m_client)
return false;
eth::ClientGuard l(const_cast<Client*>(m_client));
return client()->postState().addressHasCode(_a); return client()->postState().addressHasCode(_a);
} }
QString QEthereum::balanceAt(QString _a, int _block) const QString QEthereum::balanceAt(QString _a, int _block) const
{ {
return toQJS(client()->balanceAt(toAddress(_a), _block)); return m_client ? toQJS(client()->balanceAt(toAddress(_a), _block)) : "";
} }
QString QEthereum::stateAt(QString _a, QString _p, int _block) const QString QEthereum::stateAt(QString _a, QString _p, int _block) const
{ {
return toQJS(client()->stateAt(toAddress(_a), toU256(_p), _block)); return m_client ? toQJS(client()->stateAt(toAddress(_a), toU256(_p), _block)) : "";
} }
QString QEthereum::codeAt(QString _a, int _block) const QString QEthereum::codeAt(QString _a, int _block) const
{ {
return ::fromBinary(client()->codeAt(toAddress(_a), _block)); return m_client ? ::fromBinary(client()->codeAt(toAddress(_a), _block)) : "";
} }
double QEthereum::countAt(QString _a, int _block) const double QEthereum::countAt(QString _a, int _block) const
{ {
return (double)(uint64_t)client()->countAt(toAddress(_a), _block); return m_client ? (double)(uint64_t)client()->countAt(toAddress(_a), _block) : 0;
} }
static eth::TransactionFilter toTransactionFilter(QString _json) static eth::TransactionFilter toTransactionFilter(QString _json)
@ -309,29 +333,34 @@ static QString toJson(eth::PastMessages const& _pms)
QString QEthereum::getTransactions(QString _json) const QString QEthereum::getTransactions(QString _json) const
{ {
return toJson(m_client->transactions(toTransactionFilter(_json))); return m_client ? toJson(m_client->transactions(toTransactionFilter(_json))) : "";
} }
bool QEthereum::isMining() const bool QEthereum::isMining() const
{ {
return client()->isMining(); return m_client ? client()->isMining() : false;
} }
bool QEthereum::isListening() const bool QEthereum::isListening() const
{ {
return client()->haveNetwork(); return m_client ? client()->haveNetwork() : false;
} }
void QEthereum::setMining(bool _l) void QEthereum::setMining(bool _l)
{ {
if (_l) if (m_client)
client()->startMining(); {
else if (_l)
client()->stopMining(); client()->startMining();
else
client()->stopMining();
}
} }
void QEthereum::setListening(bool _l) void QEthereum::setListening(bool _l)
{ {
if (!m_client)
return;
if (_l) if (_l)
client()->startNetwork(); client()->startNetwork();
else else
@ -340,11 +369,13 @@ void QEthereum::setListening(bool _l)
unsigned QEthereum::peerCount() const unsigned QEthereum::peerCount() const
{ {
return (unsigned)client()->peerCount(); return m_client ? (unsigned)client()->peerCount() : 0;
} }
QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice) QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice)
{ {
if (!m_client)
return "";
auto ret = toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice))); auto ret = toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice)));
client()->flushTransactions(); client()->flushTransactions();
return ret; return ret;
@ -352,12 +383,16 @@ QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QSt
void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice) void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice)
{ {
if (!m_client)
return;
client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice)); client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice));
client()->flushTransactions(); client()->flushTransactions();
} }
unsigned QEthereum::newWatch(QString _json) unsigned QEthereum::newWatch(QString _json)
{ {
if (!m_client)
return (unsigned)-1;
unsigned ret; unsigned ret;
if (_json == "chainChanged") if (_json == "chainChanged")
ret = m_client->installWatch(eth::NewBlockFilter); ret = m_client->installWatch(eth::NewBlockFilter);
@ -371,11 +406,15 @@ unsigned QEthereum::newWatch(QString _json)
QString QEthereum::watchTransactions(unsigned _w) QString QEthereum::watchTransactions(unsigned _w)
{ {
if (!m_client)
return "";
return toJson(m_client->transactions(_w)); return toJson(m_client->transactions(_w));
} }
void QEthereum::killWatch(unsigned _w) void QEthereum::killWatch(unsigned _w)
{ {
if (!m_client)
return;
m_client->uninstallWatch(_w); m_client->uninstallWatch(_w);
std::remove(m_watches.begin(), m_watches.end(), _w); std::remove(m_watches.begin(), m_watches.end(), _w);
} }

7
libqethereum/QEthereum.h

@ -92,6 +92,9 @@ public:
eth::Client* client() const; eth::Client* client() const;
/// Call when the client() is going to be deleted to make this object useless but safe.
void clientDieing();
void setup(QWebFrame* _e); void setup(QWebFrame* _e);
void teardown(QWebFrame* _e); void teardown(QWebFrame* _e);
@ -186,8 +189,8 @@ private:
frame->disconnect(); \ frame->disconnect(); \
frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \ frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \
frame->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \ frame->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \
frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); return { w: ww, uninstall: function() { eth.killWatch(w) }, changed: function(f) { eth.watchChanged.connect(function(nw) { if (nw == this.w) f() }) }, transactions: function() { return JSON.parse(eth.watchTransactions(w)) } }; }"); \ 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) { env.note('check:' + nw + ' vs ' + ww); if (nw == ww) f() }); }; ret.transactions = function() { return JSON.parse(eth.watchTransactions(this.w)) }; return ret; }"); \
frame->evaluateJavaScript("eth.watch = function(a) { return makeWatch(JSON.stringify(a)); }"); \ frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \
frame->evaluateJavaScript("eth.watchChain = function() { return eth.makeWatch('chainChanged') }"); \ frame->evaluateJavaScript("eth.watchChain = function() { return eth.makeWatch('chainChanged') }"); \
frame->evaluateJavaScript("eth.watchPending = function() { return eth.makeWatch('pendingChanged') }"); \ frame->evaluateJavaScript("eth.watchPending = function() { return eth.makeWatch('pendingChanged') }"); \
frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \ frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \

Loading…
Cancel
Save