diff --git a/alethzero/Main.ui b/alethzero/Main.ui index b59c9ce2d..14f3f5b67 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -45,6 +45,13 @@ + + + + #0 + + + @@ -118,7 +125,7 @@ 0 0 1617 - 22 + 24 diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a295d8333..33ced7e98 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -161,8 +161,11 @@ Main::Main(QWidget *parent) : statusBar()->addPermanentWidget(ui->balance); statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->mineStatus); + statusBar()->addPermanentWidget(ui->chainStatus); statusBar()->addPermanentWidget(ui->blockCount); + ui->blockCount->setText(QString("PV%2 D%3 H%4 v%5").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(c_ethashVersion).arg(dev::Version)); + connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); QSettings s("ethereum", "alethzero"); @@ -301,14 +304,23 @@ unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f) void Main::uninstallWatch(unsigned _w) { + cdebug << "!!! Main: uninstalling watch" << _w; ethereum()->uninstallWatch(_w); m_handlers.erase(_w); } void Main::installWatches() { - installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); }); - installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); }); + auto newBlockId = installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ + onNewBlock(); + }); + auto newPendingId = installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ + onNewPending(); + }); + + cdebug << "newBlock watch ID: " << newBlockId; + cdebug << "newPending watch ID: " << newPendingId; + installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); } @@ -1089,9 +1101,9 @@ void Main::refreshAccounts() void Main::refreshBlockCount() { - cwatch << "refreshBlockCount()"; auto d = ethereum()->blockChain().details(); - ui->blockCount->setText(QString("%4 #%1 PV%2 D%3 H%5").arg(d.number).arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(c_ethashVersion)); + BlockQueueStatus b = ethereum()->blockQueueStatus(); + ui->chainStatus->setText(QString("%3 ready %4 future %5 unknown %6 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.ready).arg(b.future).arg(b.unknown).arg(b.bad)); } void Main::on_turboMining_triggered() @@ -1270,6 +1282,7 @@ void Main::timerEvent(QTimerEvent*) refreshNetwork(); refreshWhispers(); refreshCache(); + refreshBlockCount(); poll(); } else diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 883914ea6..dc0f42bf7 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.4"; +char const* Version = "0.9.5"; } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 2357ac4c1..a4061a1a0 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -714,21 +714,21 @@ tuple BlockChain::treeRoute(h256 const& _from, h256 const tn--; // cdebug << "to:" << tn << _to.abridged(); } - while (from != to) + for (;; from = details(from).parent, to = details(to).parent) { - if (!from) - assert(from); - if (!to) - assert(to); - from = details(from).parent; - to = details(to).parent; if (_pre && (from != to || _common)) ret.push_back(from); if (_post && (from != to || (!_pre && _common))) back.push_back(to); fn--; tn--; - // cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged(); +// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged(); + if (from == to) + break; + if (!from) + assert(from); + if (!to) + assert(to); } ret.reserve(ret.size() + back.size()); unsigned i = ret.size() - (int)(_common && !ret.empty() && !back.empty()); diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 802ac98ba..ce0582db2 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -38,6 +38,14 @@ class BlockChain; struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 4; }; #define cblockq dev::LogOutputStream() +struct BlockQueueStatus +{ + size_t ready; + size_t future; + size_t unknown; + size_t bad; +}; + /** * @brief A queue of blocks. Sits between network or other I/O and the BlockChain. * Sorts them ready for blockchain insertion (with the BlockChain::sync() method). @@ -72,6 +80,9 @@ public: /// Return first block with an unknown parent. h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); } + /// Get some infomration on the current status. + BlockQueueStatus status() const { ReadGuard l(m_lock); return BlockQueueStatus{m_ready.size(), m_future.size(), m_unknown.size(), m_knownBad.size()}; } + private: void noteReadyWithoutWriteGuard(h256 _b); void notePresentWithoutWriteGuard(bytesConstRef _block); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 9590a0ebc..c8d0482c2 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -514,7 +514,7 @@ void Client::doWork() m_tq.drop(th); stillGotWork = stillGotWork | sgw; - if (fresh.size()) + if (!fresh.empty()) { for (auto i: fresh) appendFromNewBlock(i, changeds); diff --git a/libethereum/Client.h b/libethereum/Client.h index f07e4c590..1891f34ca 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -168,6 +168,8 @@ public: dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; } /// Get the object representing the current canonical blockchain. CanonBlockChain const& blockChain() const { return m_bc; } + /// Get some information on the block queue. + BlockQueueStatus blockQueueStatus() const { return m_bq.status(); } // Mining stuff: diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 557b08818..10e4ca84b 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -108,6 +108,7 @@ public: virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override; virtual LocalisedLogEntries checkWatch(unsigned _watchId) override; + // TODO: switch all the _blockHash arguments to also accept _blockNumber virtual h256 hashFromNumber(unsigned _number) const override; virtual eth::BlockInfo blockInfo(h256 _hash) const override; virtual eth::BlockDetails blockDetails(h256 _hash) const override; diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index bfc380a67..de85d94bb 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -162,6 +162,11 @@ void EthereumHost::doWork() maintainTransactions(); maintainBlocks(h); } + + for (auto p: peerSessions()) + if (shared_ptr const& ep = p.first->cap()) + ep->tick(); + // return netChange; // TODO: Figure out what to do with netChange. (void)netChange; diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 4ecec9689..3bd7ecab3 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -220,6 +220,8 @@ void EthereumPeer::setAsking(Asking _a, bool _isSyncing) m_syncingNeededBlocks.clear(); } + m_lastAsk = chrono::system_clock::now(); + session()->addNote("ask", _a == Asking::Nothing ? "nothing" : _a == Asking::State ? "state" : _a == Asking::Hashes ? "hashes" : _a == Asking::Blocks ? "blocks" : "?"); session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : "")); } @@ -235,6 +237,13 @@ void EthereumPeer::setNeedsSyncing(h256 _latestHash, u256 _td) session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : "")); } +void EthereumPeer::tick() +{ + if (chrono::system_clock::now() - m_lastAsk > chrono::seconds(10) && m_asking != Asking::Nothing) + // timeout + session()->disconnect(PingTimeout); +} + bool EthereumPeer::isSyncing() const { return host()->m_syncer == this; diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index c95df6945..da144134b 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -105,6 +105,9 @@ private: /// Check whether the session should bother grabbing the peer's blocks. bool shouldGrabBlocks() const; + /// Runs period checks to check up on the peer. + void tick(); + /// Peer's protocol version. unsigned m_protocolVersion; /// Peer's network id. @@ -112,6 +115,8 @@ private: /// What, if anything, we last asked the other peer for. Asking m_asking = Asking::Nothing; + /// When we asked for it. Allows a time out. + std::chrono::system_clock::time_point m_lastAsk; /// Whether this peer is in the process of syncing or not. Only one peer can be syncing at once. bool m_isSyncing = false; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index da0108b3e..79fd75d77 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -385,7 +385,7 @@ string WebThreeStubServerBase::eth_getBlockTransactionCountByNumber(string const { try { - return toJS(client()->transactionCount(client()->hashFromNumber(toBlockNumber(_blockNumber)))); + return toJS(_blockNumber == "pending" ? client()->pending().size() : client()->transactionCount(client()->hashFromNumber(toBlockNumber(_blockNumber)))); } catch (...) {