From 4f5b15345282768fe78a8331ac69e6d9d60ad457 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 7 Oct 2014 16:40:13 +0200 Subject: [PATCH] Better state management. --- libethereum/EthereumHost.cpp | 14 ++++++++------ libethereum/EthereumHost.h | 2 +- libethereum/EthereumPeer.cpp | 25 ++++++++++++++++--------- libethereum/EthereumPeer.h | 1 + 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 4bd34f201..c5c3e90cd 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -84,13 +84,15 @@ void EthereumHost::noteNeedsSyncing(EthereumPeer* _who) _who->attemptSync(); } -void EthereumHost::updateSyncer(EthereumPeer* _syncer) +void EthereumHost::changeSyncer(EthereumPeer* _syncer) { - if (_syncer) + m_syncer = _syncer; + if (isSyncing()) { - for (auto j: peers()) - if (j->cap().get() != _syncer && j->cap()->m_asking == Asking::Nothing) - j->cap()->transition(Asking::Blocks); + if (_syncer->m_asking == Asking::Blocks) + for (auto j: peers()) + if (j->cap().get() != _syncer && j->cap()->m_asking == Asking::Nothing) + j->cap()->transition(Asking::Blocks); } else { @@ -115,7 +117,7 @@ void EthereumHost::noteDoneBlocks(EthereumPeer* _who, bool _clemency) _who->addRating(m_man.chain().size() / 100); m_man.reset(); } - if (_who->isSyncing()) + else if (_who->isSyncing()) { if (_clemency) clog(NetNote) << "Chain download failed. Aborted while incomplete."; diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 2ce5b9971..12ce28f23 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -101,7 +101,7 @@ private: virtual void onStarting() { startWorking(); } virtual void onStopping() { stopWorking(); } - void updateSyncer(EthereumPeer* _ignore); + void changeSyncer(EthereumPeer* _ignore); BlockChain const& m_chain; TransactionQueue& m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index c80912c30..45e850de6 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -105,7 +105,7 @@ void EthereumPeer::transition(Asking _a, bool _force) m_syncingLatestHash = m_latestHash; m_syncingTotalDifficulty = m_totalDifficulty; - m_latestHash = h256(); + resetNeedsSyncing(); setAsking(_a, true); s.appendList(3) << GetBlockHashesPacket << m_syncingLatestHash << c_maxHashesAsk; @@ -134,15 +134,14 @@ void EthereumPeer::transition(Asking _a, bool _force) { clog(NetNote) << "Difficulty of hashchain HIGHER. Grabbing" << m_syncingNeededBlocks.size() << "blocks [latest now" << m_syncingLatestHash.abridged() << ", was" << host()->m_latestBlockSent.abridged() << "]"; - m_syncingLatestHash = h256(); - host()->m_man.resetToChain(m_syncingNeededBlocks); host()->m_latestBlockSent = m_syncingLatestHash; + } else { clog(NetNote) << "Difficulty of hashchain not HIGHER. Ignoring."; - m_latestHash = h256(); + m_syncingLatestHash = h256(); setAsking(Asking::Nothing, false); return; } @@ -151,7 +150,7 @@ void EthereumPeer::transition(Asking _a, bool _force) if (m_asking == Asking::Nothing || m_asking == Asking::Hashes || m_asking == Asking::Blocks) { // Looks like it's the best yet for total difficulty. Set to download. - setAsking(Asking::Blocks, true); + setAsking(Asking::Blocks, true); // will kick off other peers to help if available. auto blocks = m_sub.nextFetch(c_maxBlocksAsk); if (blocks.size()) { @@ -202,9 +201,12 @@ void EthereumPeer::transition(Asking _a, bool _force) void EthereumPeer::setAsking(Asking _a, bool _isSyncing) { + bool changedAsking = (m_asking != _a); m_asking = _a; - if (_isSyncing != (host()->m_syncer == this)) - host()->updateSyncer(_isSyncing ? this : nullptr); + + if (_isSyncing != (host()->m_syncer == this) || (_isSyncing && changedAsking)) + host()->changeSyncer(_isSyncing ? this : nullptr); + if (!_isSyncing) { m_syncingLatestHash = h256(); @@ -221,7 +223,10 @@ void EthereumPeer::setNeedsSyncing(h256 _latestHash, u256 _td) m_latestHash = _latestHash; m_totalDifficulty = _td; - host()->noteNeedsSyncing(this); + if (m_latestHash) + host()->noteNeedsSyncing(this); + + session()->addNote("sync", string(isSyncing() ? "ongoing" : "holding") + (needsSyncing() ? " & needed" : "")); } bool EthereumPeer::isSyncing() const @@ -269,7 +274,7 @@ void EthereumPeer::attemptSync() if (td >= m_totalDifficulty) { clogS(NetAllDetail) << "No. Our chain is better."; - m_latestHash = h256(); + resetNeedsSyncing(); transition(Asking::Nothing); } else @@ -287,6 +292,8 @@ bool EthereumPeer::interpret(RLP const& _r) { m_protocolVersion = _r[1].toInt(); m_networkId = _r[2].toInt(); + + // a bit dirty as we're misusing these to communicate the values to transition, but harmless. m_totalDifficulty = _r[3].toInt(); m_latestHash = _r[4].toHash(); auto genesisHash = _r[5].toHash(); diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 3a625f369..00788d019 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -82,6 +82,7 @@ private: /// Update our syncing requirements state. void setNeedsSyncing(h256 _latestHash, u256 _td); + void resetNeedsSyncing() { setNeedsSyncing(h256(), 0); } /// Do we presently need syncing with this peer? bool needsSyncing() const { return !!m_latestHash; }