Browse Source

Move misc to dev.* JS API.

Potential crash fix.
UPnP in thread.
cl-refactor
Gav Wood 10 years ago
parent
commit
6706c26471
  1. 4
      alethzero/MainWin.cpp
  2. 1
      alethzero/MainWin.h
  3. 1
      libdevcore/Worker.cpp
  4. 1
      libdevcore/Worker.h
  5. 51
      libp2p/Host.cpp
  6. 5
      libp2p/Host.h
  7. 2
      libp2p/UPnP.h
  8. 8
      libqethereum/QEthereum.cpp
  9. 69
      libqethereum/QEthereum.h
  10. 4
      third/MainWin.cpp
  11. 1
      third/MainWin.h

4
alethzero/MainWin.cpp

@ -135,15 +135,17 @@ Main::Main(QWidget *parent) :
connect(ui->webView, &QWebView::loadStarted, [this]() connect(ui->webView, &QWebView::loadStarted, [this]()
{ {
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it. // NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_dev = new QDev(this);
m_ethereum = new QEthereum(this, ethereum(), owned()); m_ethereum = new QEthereum(this, ethereum(), owned());
m_whisper = new QWhisper(this, whisper()); m_whisper = new QWhisper(this, whisper());
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
QWebFrame* f = ui->webView->page()->mainFrame(); QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared())); f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
auto qdev = m_dev;
auto qeth = m_ethereum; auto qeth = m_ethereum;
auto qshh = m_whisper; auto qshh = m_whisper;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, qeth, qshh, this)); connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh));
}); });
connect(ui->webView, &QWebView::loadFinished, [=]() connect(ui->webView, &QWebView::loadFinished, [=]()

1
alethzero/MainWin.h

@ -247,6 +247,7 @@ private:
QString m_logHistory; QString m_logHistory;
bool m_logChanged = true; bool m_logChanged = true;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr; QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr; QWhisper* m_whisper = nullptr;
}; };

1
libdevcore/Worker.cpp

@ -38,6 +38,7 @@ void Worker::startWorking()
m_work.reset(new thread([&]() m_work.reset(new thread([&]()
{ {
setThreadName(m_name.c_str()); setThreadName(m_name.c_str());
startedWorking();
while (!m_stop) while (!m_stop)
{ {
this_thread::sleep_for(chrono::milliseconds(30)); this_thread::sleep_for(chrono::milliseconds(30));

1
libdevcore/Worker.h

@ -46,6 +46,7 @@ protected:
void startWorking(); void startWorking();
void stopWorking(); void stopWorking();
bool isWorking() const { Guard l(x_work); return !!m_work; } bool isWorking() const { Guard l(x_work); return !!m_work; }
virtual void startedWorking() {}
virtual void doWork() = 0; virtual void doWork() = 0;
virtual void doneWorking() {} virtual void doneWorking() {}

51
libp2p/Host.cpp

@ -110,14 +110,6 @@ void Host::start()
} }
} }
determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
ensureAccepting();
if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
noteNode(id(), m_public, Origin::Perfect, false);
clog(NetNote) << "Id:" << id().abridged();
for (auto const& h: m_capabilities) for (auto const& h: m_capabilities)
h.second->onStarting(); h.second->onStarting();
@ -549,31 +541,31 @@ void Host::connect(bi::tcp::endpoint const& _ep)
}); });
} }
void Node::connect(Host* _h) void Host::connect(std::shared_ptr<Node> const& _n)
{ {
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here. // if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!_h->m_ioService) if (!m_ioService)
return; return;
clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address << "from" << _h->id().abridged(); clog(NetConnect) << "Attempting connection to node" << _n->id.abridged() << "@" << _n->address << "from" << id().abridged();
lastAttempted = std::chrono::system_clock::now(); _n->lastAttempted = std::chrono::system_clock::now();
failedAttempts++; _n->failedAttempts++;
_h->m_ready -= index; m_ready -= _n->index;
bi::tcp::socket* s = new bi::tcp::socket(*_h->m_ioService); bi::tcp::socket* s = new bi::tcp::socket(*m_ioService);
s->async_connect(address, [=](boost::system::error_code const& ec) s->async_connect(_n->address, [=](boost::system::error_code const& ec)
{ {
if (ec) if (ec)
{ {
clog(NetConnect) << "Connection refused to node" << id.abridged() << "@" << address << "(" << ec.message() << ")"; clog(NetConnect) << "Connection refused to node" << _n->id.abridged() << "@" << _n->address << "(" << ec.message() << ")";
lastDisconnect = TCPError; _n->lastDisconnect = TCPError;
lastAttempted = std::chrono::system_clock::now(); _n->lastAttempted = std::chrono::system_clock::now();
_h->m_ready += index; m_ready += _n->index;
} }
else else
{ {
clog(NetConnect) << "Connected to" << id.abridged() << "@" << address; clog(NetConnect) << "Connected to" << _n->id.abridged() << "@" << _n->address;
lastConnected = std::chrono::system_clock::now(); _n->lastConnected = std::chrono::system_clock::now();
auto p = make_shared<Session>(_h, std::move(*s), _h->node(id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism. auto p = make_shared<Session>(this, std::move(*s), node(_n->id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism.
p->start(); p->start();
} }
delete s; delete s;
@ -638,7 +630,7 @@ void Host::growPeers()
if (ns.size()) if (ns.size())
for (Node const& i: ns) for (Node const& i: ns)
{ {
m_nodes[i.id]->connect(this); connect(m_nodes[i.id]);
if (!--morePeers) if (!--morePeers)
return; return;
} }
@ -704,6 +696,17 @@ PeerInfos Host::peers(bool _updatePing) const
return ret; return ret;
} }
void Host::startedWorking()
{
determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
ensureAccepting();
if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
noteNode(id(), m_public, Origin::Perfect, false);
clog(NetNote) << "Id:" << id().abridged();
}
void Host::doWork() void Host::doWork()
{ {
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here. // if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.

5
libp2p/Host.h

@ -97,8 +97,6 @@ struct Node
else else
return score < _n.score; return score < _n.score;
} }
void connect(Host* _h);
}; };
using Nodes = std::vector<Node>; using Nodes = std::vector<Node>;
@ -147,6 +145,7 @@ public:
static std::string pocHost(); static std::string pocHost();
void connect(std::string const& _addr, unsigned short _port = 30303) noexcept; void connect(std::string const& _addr, unsigned short _port = 30303) noexcept;
void connect(bi::tcp::endpoint const& _ep); void connect(bi::tcp::endpoint const& _ep);
void connect(std::shared_ptr<Node> const& _n);
/// @returns true iff we have the a peer of the given id. /// @returns true iff we have the a peer of the given id.
bool havePeer(NodeId _id) const; bool havePeer(NodeId _id) const;
@ -197,6 +196,8 @@ private:
void growPeers(); void growPeers();
void prunePeers(); void prunePeers();
virtual void startedWorking();
/// Conduct I/O, polling, syncing, whatever. /// Conduct I/O, polling, syncing, whatever.
/// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway. /// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway.
/// This won't touch alter the blockchain. /// This won't touch alter the blockchain.

2
libp2p/UPnP.h

@ -25,6 +25,7 @@
#include <set> #include <set>
#include <string> #include <string>
#include <memory> #include <memory>
#include <thread>
struct UPNPUrls; struct UPNPUrls;
struct IGDdatas; struct IGDdatas;
@ -46,6 +47,7 @@ public:
bool isValid() const { return m_ok; } bool isValid() const { return m_ok; }
private:
std::set<int> m_reg; std::set<int> m_reg;
bool m_ok; bool m_ok;
std::shared_ptr<struct UPNPUrls> m_urls; std::shared_ptr<struct UPNPUrls> m_urls;

8
libqethereum/QEthereum.cpp

@ -96,22 +96,22 @@ QString QEthereum::lll(QString _s) const
return toQJS(dev::eth::compileLLL(_s.toStdString())); return toQJS(dev::eth::compileLLL(_s.toStdString()));
} }
QString QEthereum::sha3(QString _s) const QString QDev::sha3(QString _s) const
{ {
return toQJS(dev::sha3(toBytes(_s))); return toQJS(dev::sha3(toBytes(_s)));
} }
QString QEthereum::sha3(QString _s1, QString _s2) const QString QDev::sha3(QString _s1, QString _s2) const
{ {
return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)))); return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32))));
} }
QString QEthereum::sha3(QString _s1, QString _s2, QString _s3) const QString QDev::sha3(QString _s1, QString _s2, QString _s3) const
{ {
return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)) + asBytes(padded(_s3, 32)))); return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)) + asBytes(padded(_s3, 32))));
} }
QString QEthereum::offset(QString _s, int _i) const QString QDev::offset(QString _s, int _i) const
{ {
return toQJS(toU256(_s) + _i); return toQJS(toU256(_s) + _i);
} }

69
libqethereum/QEthereum.h

@ -98,6 +98,27 @@ inline QString fromBinary(QString const& _s, unsigned _padding = 32)
return fromBinary(asBytes(_s), _padding); return fromBinary(asBytes(_s), _padding);
} }
class QDev: public QObject
{
Q_OBJECT
public:
QDev(QObject* _p): QObject(_p) {}
virtual ~QDev() {}
Q_INVOKABLE QString sha3(QString _s) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2, QString _s3) const;
Q_INVOKABLE QString offset(QString _s, int _offset) const;
Q_INVOKABLE QString toAscii(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromAscii(QString _s) const { return ::fromBinary(_s, 32); }
Q_INVOKABLE QString fromAscii(QString _s, unsigned _padding) const { return ::fromBinary(_s, _padding); }
Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); }
Q_INVOKABLE double fromFixed(QString _s) const { return ::fromFixed(_s); }
Q_INVOKABLE QString toFixed(double _d) const { return ::toFixed(_d); }
};
class QEthereum: public QObject class QEthereum: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -114,24 +135,11 @@ public:
void setAccounts(QList<dev::KeyPair> _l) { m_accounts = _l; keysChanged(); } void setAccounts(QList<dev::KeyPair> _l) { m_accounts = _l; keysChanged(); }
Q_INVOKABLE QString ethTest() const { return "Hello world!"; }
Q_INVOKABLE QEthereum* self() { return this; } Q_INVOKABLE QEthereum* self() { return this; }
Q_INVOKABLE QString secretToAddress(QString _s) const; Q_INVOKABLE QString secretToAddress(QString _s) const;
Q_INVOKABLE QString lll(QString _s) const; Q_INVOKABLE QString lll(QString _s) const;
Q_INVOKABLE QString sha3(QString _s) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2, QString _s3) const;
Q_INVOKABLE QString offset(QString _s, int _offset) const;
Q_INVOKABLE QString toAscii(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromAscii(QString _s) const { return ::fromBinary(_s, 32); }
Q_INVOKABLE QString fromAscii(QString _s, unsigned _padding) const { return ::fromBinary(_s, _padding); }
Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); }
Q_INVOKABLE double fromFixed(QString _s) const { return ::fromFixed(_s); }
Q_INVOKABLE QString toFixed(double _d) const { return ::toFixed(_d); }
// [NEW API] - Use this instead. // [NEW API] - Use this instead.
Q_INVOKABLE QString/*dev::u256*/ balanceAt(QString/*dev::Address*/ _a, int _block) const; Q_INVOKABLE QString/*dev::u256*/ balanceAt(QString/*dev::Address*/ _a, int _block) const;
Q_INVOKABLE double countAt(QString/*dev::Address*/ _a, int _block) const; Q_INVOKABLE double countAt(QString/*dev::Address*/ _a, int _block) const;
@ -247,27 +255,28 @@ private:
}; };
// TODO: add p2p object // TODO: add p2p object
#define QETH_INSTALL_JS_NAMESPACE(frame, eth, shh, env) [frame, eth, shh, env]() \ #define QETH_INSTALL_JS_NAMESPACE(_frame, _env, _dev, _eth, _shh) [_frame, _env, _dev, _eth, _shh]() \
{ \ { \
frame->disconnect(); \ _frame->disconnect(); \
frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \ _frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
if (eth) \ _frame->addToJavaScriptWindowObject("dev", _dev, QWebFrame::ScriptOwnership); \
if (_eth) \
{ \ { \
frame->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \ _frame->addToJavaScriptWindowObject("eth", _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.transact = function(a, f) { var r = eth.doTransact(JSON.stringify(a)); if (f) f(r); }"); \ _frame->evaluateJavaScript("eth.transact = function(a, f) { var r = eth.doTransact(JSON.stringify(a)); if (f) f(r); }"); \
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.block = function(a) { return JSON.parse(eth.getBlock(a)); }"); \ _frame->evaluateJavaScript("eth.block = function(a) { return JSON.parse(eth.getBlock(a)); }"); \
frame->evaluateJavaScript("eth.transaction = function(a) { return JSON.parse(eth.getTransaction(a)); }"); \ _frame->evaluateJavaScript("eth.transaction = function(a) { return JSON.parse(eth.getTransaction(a)); }"); \
frame->evaluateJavaScript("eth.uncle = function(a) { return JSON.parse(eth.getUncle(a)); }"); \ _frame->evaluateJavaScript("eth.uncle = function(a) { return JSON.parse(eth.getUncle(a)); }"); \
} \ } \
if (shh) \ if (_shh) \
{ \ { \
frame->addToJavaScriptWindowObject("shh", shh, QWebFrame::ScriptOwnership); \ _frame->addToJavaScriptWindowObject("shh", _shh, QWebFrame::ScriptOwnership); \
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)) }"); \
} \ } \
} }

4
third/MainWin.cpp

@ -105,14 +105,16 @@ Main::Main(QWidget *parent) :
connect(ui->webView, &QWebView::loadStarted, [this]() connect(ui->webView, &QWebView::loadStarted, [this]()
{ {
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it. // NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_dev = new QDev(this);
m_ethereum = new QEthereum(this, ethereum(), owned()); m_ethereum = new QEthereum(this, ethereum(), owned());
m_whisper = new QWhisper(this, whisper()); m_whisper = new QWhisper(this, whisper());
QWebFrame* f = ui->webView->page()->mainFrame(); QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared())); f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
auto qdev = m_dev;
auto qeth = m_ethereum; auto qeth = m_ethereum;
auto qshh = m_whisper; auto qshh = m_whisper;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, qeth, qshh, this)); connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh));
}); });
connect(ui->webView, &QWebView::loadFinished, [=]() connect(ui->webView, &QWebView::loadFinished, [=]()

1
third/MainWin.h

@ -132,6 +132,7 @@ private:
QNetworkAccessManager m_webCtrl; QNetworkAccessManager m_webCtrl;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr; QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr; QWhisper* m_whisper = nullptr;
}; };

Loading…
Cancel
Save