Browse Source

resync after downloading unknown new block

cl-refactor
arkpar 10 years ago
parent
commit
566b2b6354
  1. 36
      libethereum/EthereumHost.cpp
  2. 2
      libethereum/EthereumHost.h
  3. 19
      libp2p/Host.cpp
  4. 1
      libp2p/Host.h

36
libethereum/EthereumHost.cpp

@ -81,6 +81,7 @@ void EthereumHost::reset()
m_hashMan.reset(m_chain.number() + 1); m_hashMan.reset(m_chain.number() + 1);
m_needSyncBlocks = true; m_needSyncBlocks = true;
m_needSyncHashes = true; m_needSyncHashes = true;
m_syncingNewHashes = false;
m_syncingLatestHash = h256(); m_syncingLatestHash = h256();
m_syncingTotalDifficulty = 0; m_syncingTotalDifficulty = 0;
m_latestBlockSent = h256(); m_latestBlockSent = h256();
@ -88,6 +89,14 @@ void EthereumHost::reset()
m_hashes.clear(); m_hashes.clear();
} }
void EthereumHost::resetSyncTo(h256 const& _h)
{
m_needSyncHashes = true;
m_needSyncBlocks = true;
m_syncingLatestHash = _h;
m_syncingNewHashes = false;
}
void EthereumHost::doWork() void EthereumHost::doWork()
{ {
bool netChange = ensureInitialised(); bool netChange = ensureInitialised();
@ -366,8 +375,13 @@ void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes, bool
} }
if (_complete) if (_complete)
{ {
clog(NetMessageSummary) << "Start new blocks download...";
m_needSyncBlocks = true; m_needSyncBlocks = true;
continueSync(); m_syncingNewHashes = true;
m_man.resetToChain(m_hashes);
m_hashes.clear();
m_hashMan.reset(m_chain.number() + 1);
continueSync(_peer);
} }
else if (syncByNumber && m_hashMan.isComplete()) else if (syncByNumber && m_hashMan.isComplete())
{ {
@ -425,6 +439,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
unsigned unknown = 0; unsigned unknown = 0;
unsigned got = 0; unsigned got = 0;
unsigned repeated = 0; unsigned repeated = 0;
h256 lastUnknown;
for (unsigned i = 0; i < itemCount; ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
@ -453,6 +468,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
break; break;
case ImportResult::UnknownParent: case ImportResult::UnknownParent:
lastUnknown = h;
unknown++; unknown++;
break; break;
@ -467,6 +483,13 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
} }
clog(NetMessageSummary) << dec << success << "imported OK," << unknown << "with unknown parents," << future << "with future timestamps," << got << " already known," << repeated << " repeats received."; clog(NetMessageSummary) << dec << success << "imported OK," << unknown << "with unknown parents," << future << "with future timestamps," << got << " already known," << repeated << " repeats received.";
if (m_syncingNewHashes && unknown > 0)
{
_peer->m_latestHash = lastUnknown;
resetSyncTo(lastUnknown);
}
continueSync(_peer); continueSync(_peer);
} }
@ -486,7 +509,7 @@ void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r) void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
{ {
RecursiveGuard l(x_sync); RecursiveGuard l(x_sync);
if (isSyncing_UNSAFE() || _peer->isConversing()) if ((isSyncing_UNSAFE() || _peer->isConversing()) && !m_syncingNewHashes)
{ {
clog(NetMessageSummary) << "Ignoring new blocks since we're already downloading."; clog(NetMessageSummary) << "Ignoring new blocks since we're already downloading.";
return; return;
@ -526,9 +549,7 @@ void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
clog(NetMessageSummary) << "Received block with no known parent. Resyncing..."; clog(NetMessageSummary) << "Received block with no known parent. Resyncing...";
_peer->m_latestHash = h; _peer->m_latestHash = h;
_peer->m_totalDifficulty = difficulty; _peer->m_totalDifficulty = difficulty;
m_needSyncHashes = true; resetSyncTo(h);;
m_needSyncBlocks = true;
m_syncingLatestHash = h;
sync = true; sync = true;
} }
} }
@ -646,7 +667,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
{ {
_peer->requestHashes(m_syncingLatestHash); _peer->requestHashes(m_syncingLatestHash);
m_syncingV61 = false; m_syncingV61 = false;
m_estimatedHashes = _peer->m_expectedHashes; m_estimatedHashes = _peer->m_expectedHashes - (_peer->m_protocolVersion == protocolVersion() ? 0 : c_chainReorgSize);
} }
else else
_peer->setIdle(); _peer->setIdle();
@ -658,6 +679,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
{ {
// Done our chain-get. // Done our chain-get.
m_needSyncBlocks = false; m_needSyncBlocks = false;
m_syncingNewHashes = false;
clog(NetNote) << "Chain download complete."; clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash. // 1/100th for each useful block hash.
_peer->addRating(m_man.chainSize() / 100); //TODO: what about other peers? _peer->addRating(m_man.chainSize() / 100); //TODO: what about other peers?
@ -742,6 +764,6 @@ HashChainStatus EthereumHost::status()
RecursiveGuard l(x_sync); RecursiveGuard l(x_sync);
if (m_syncingV61) if (m_syncingV61)
return HashChainStatus { static_cast<unsigned>(m_hashMan.chainSize()), static_cast<unsigned>(m_hashMan.gotCount()), false }; return HashChainStatus { static_cast<unsigned>(m_hashMan.chainSize()), static_cast<unsigned>(m_hashMan.gotCount()), false };
return HashChainStatus { m_estimatedHashes > 0 ? m_estimatedHashes - c_chainReorgSize : 0, static_cast<unsigned>(m_hashes.size()), m_estimatedHashes > 0 }; return HashChainStatus { m_estimatedHashes > 0 ? m_estimatedHashes : 0, static_cast<unsigned>(m_hashes.size()), m_estimatedHashes > 0 };
} }

2
libethereum/EthereumHost.h

@ -97,6 +97,7 @@ private:
void foreachPeerPtr(std::function<void(std::shared_ptr<EthereumPeer>)> const& _f) const; void foreachPeerPtr(std::function<void(std::shared_ptr<EthereumPeer>)> const& _f) const;
void foreachPeer(std::function<void(EthereumPeer*)> const& _f) const; void foreachPeer(std::function<void(EthereumPeer*)> const& _f) const;
bool isSyncing_UNSAFE() const; bool isSyncing_UNSAFE() const;
void resetSyncTo(h256 const& _h);
/// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network. /// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network.
void doWork(); void doWork();
@ -151,6 +152,7 @@ private:
bool m_needSyncBlocks = true; ///< Indicates if we still need to download some blocks bool m_needSyncBlocks = true; ///< Indicates if we still need to download some blocks
h256 m_syncingLatestHash; ///< Latest block's hash, as of the current sync. h256 m_syncingLatestHash; ///< Latest block's hash, as of the current sync.
u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty, as of the current sync. u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty, as of the current sync.
bool m_syncingNewHashes = false; ///< True if currently downloading hashes received with NewHashes
h256s m_hashes; ///< List of hashes with unknown block numbers. Used for PV60 chain downloading and catching up to a particular unknown h256s m_hashes; ///< List of hashes with unknown block numbers. Used for PV60 chain downloading and catching up to a particular unknown
unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only. unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only.
bool m_syncingV61 = false; ///< True if recent activity was over pv61+. Used for status reporting only. bool m_syncingV61 = false; ///< True if recent activity was over pv61+. Used for status reporting only.

19
libp2p/Host.cpp

@ -61,17 +61,22 @@ ReputationManager::ReputationManager()
void ReputationManager::noteRude(Session const& _s, std::string const& _sub) void ReputationManager::noteRude(Session const& _s, std::string const& _sub)
{ {
m_nodes[make_pair(_s.id(), _s.info().clientVersion)].subs[_sub].isRude = true; DEV_WRITE_GUARDED(x_nodes)
m_nodes[make_pair(_s.id(), _s.info().clientVersion)].subs[_sub].isRude = true;
} }
bool ReputationManager::isRude(Session const& _s, std::string const& _sub) const bool ReputationManager::isRude(Session const& _s, std::string const& _sub) const
{ {
auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion)); DEV_READ_GUARDED(x_nodes)
if (nit == m_nodes.end()) {
return false; auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion));
auto sit = nit->second.subs.find(_sub); if (nit == m_nodes.end())
bool ret = sit == nit->second.subs.end() ? false : sit->second.isRude; return false;
return _sub.empty() ? ret : (ret || isRude(_s)); auto sit = nit->second.subs.find(_sub);
bool ret = sit == nit->second.subs.end() ? false : sit->second.isRude;
return _sub.empty() ? ret : (ret || isRude(_s));
}
return false;
} }
Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork): Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork):

1
libp2p/Host.h

@ -99,6 +99,7 @@ public:
private: private:
std::unordered_map<std::pair<p2p::NodeId, std::string>, Reputation> m_nodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible. std::unordered_map<std::pair<p2p::NodeId, std::string>, Reputation> m_nodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible.
SharedMutex mutable x_nodes;
}; };
/** /**

Loading…
Cancel
Save