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()
{
// 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;
writeSettings();
}
@ -379,7 +383,8 @@ void Main::eval(QString const& _js)
{
if (_js.trimmed().isEmpty())
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;
if (ev.isNull())
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>";
else if (ev.type() == QVariant::Int || ev.type() == QVariant::Double)
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
s = "<span style=\"color: #888\">unknown type</span>";
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);
if (it == m_watches.end())
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->second.refCount)
m_filters.erase(fit);
m_watches.erase(it);
}
void Client::appendFromNewPending(h256 _bloom, h256Set& o_changed) const
{
lock_guard<mutex> l(m_filterLock);
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);
}
@ -176,7 +176,7 @@ void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const
lock_guard<mutex> l(m_filterLock);
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);
}
@ -587,13 +587,13 @@ PastMessages Client::transactions(TransactionFilter const& _f) const
ClientGuard l(this);
PastMessages ret;
unsigned begin = numberOf(_f.latest());
unsigned end = min(begin, numberOf(_f.earliest()));
unsigned begin = min<unsigned>(m_bc.number(), (unsigned)_f.latest());
unsigned end = min(begin, (unsigned)_f.earliest());
unsigned m = _f.max();
unsigned s = _f.skip();
// 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)
{
@ -608,19 +608,15 @@ PastMessages Client::transactions(TransactionFilter const& _f) const
s--;
else
// 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
unsigned skipped = 0;
unsigned falsePos = 0;
#endif
auto cn = m_bc.number();
auto h = m_bc.numberHash(begin);
unsigned n = begin;
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--;
else
// 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

6
libethereum/Client.h

@ -102,7 +102,7 @@ typedef std::vector<PastMessage> PastMessages;
class TransactionFilter
{
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;
h256 sha3() const;
@ -131,8 +131,8 @@ private:
std::set<Address> m_to;
std::set<std::pair<Address, u256>> m_stateAltered;
std::set<Address> m_altered;
int m_earliest;
int m_latest;
int m_earliest = 0;
int m_latest = -1;
unsigned m_max;
unsigned m_skip;
};

77
libqethereum/QEthereum.cpp

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

7
libqethereum/QEthereum.h

@ -92,6 +92,9 @@ public:
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 teardown(QWebFrame* _e);
@ -186,8 +189,8 @@ private:
frame->disconnect(); \
frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \
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.watch = function(a) { return makeWatch(JSON.stringify(a)); }"); \
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 eth.makeWatch(JSON.stringify(a)) }"); \
frame->evaluateJavaScript("eth.watchChain = function() { return eth.makeWatch('chainChanged') }"); \
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) }"); \

Loading…
Cancel
Save