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_needSyncBlocks = true;
m_needSyncHashes = true;
m_syncingNewHashes = false;
m_syncingLatestHash = h256();
m_syncingTotalDifficulty = 0;
m_latestBlockSent = h256();
@ -88,6 +89,14 @@ void EthereumHost::reset()
m_hashes.clear();
}
void EthereumHost::resetSyncTo(h256 const& _h)
{
m_needSyncHashes = true;
m_needSyncBlocks = true;
m_syncingLatestHash = _h;
m_syncingNewHashes = false;
}
void EthereumHost::doWork()
{
bool netChange = ensureInitialised();
@ -366,8 +375,13 @@ void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes, bool
}
if (_complete)
{
clog(NetMessageSummary) << "Start new blocks download...";
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())
{
@ -425,6 +439,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
unsigned unknown = 0;
unsigned got = 0;
unsigned repeated = 0;
h256 lastUnknown;
for (unsigned i = 0; i < itemCount; ++i)
{
@ -453,6 +468,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
break;
case ImportResult::UnknownParent:
lastUnknown = h;
unknown++;
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.";
if (m_syncingNewHashes && unknown > 0)
{
_peer->m_latestHash = lastUnknown;
resetSyncTo(lastUnknown);
}
continueSync(_peer);
}
@ -486,7 +509,7 @@ void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
{
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.";
return;
@ -526,9 +549,7 @@ void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
clog(NetMessageSummary) << "Received block with no known parent. Resyncing...";
_peer->m_latestHash = h;
_peer->m_totalDifficulty = difficulty;
m_needSyncHashes = true;
m_needSyncBlocks = true;
m_syncingLatestHash = h;
resetSyncTo(h);;
sync = true;
}
}
@ -646,7 +667,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
{
_peer->requestHashes(m_syncingLatestHash);
m_syncingV61 = false;
m_estimatedHashes = _peer->m_expectedHashes;
m_estimatedHashes = _peer->m_expectedHashes - (_peer->m_protocolVersion == protocolVersion() ? 0 : c_chainReorgSize);
}
else
_peer->setIdle();
@ -658,6 +679,7 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
{
// Done our chain-get.
m_needSyncBlocks = false;
m_syncingNewHashes = false;
clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash.
_peer->addRating(m_man.chainSize() / 100); //TODO: what about other peers?
@ -742,6 +764,6 @@ HashChainStatus EthereumHost::status()
RecursiveGuard l(x_sync);
if (m_syncingV61)
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 foreachPeer(std::function<void(EthereumPeer*)> const& _f) 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.
void doWork();
@ -151,6 +152,7 @@ private:
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.
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
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.

19
libp2p/Host.cpp

@ -61,17 +61,22 @@ ReputationManager::ReputationManager()
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
{
auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion));
if (nit == m_nodes.end())
return false;
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));
DEV_READ_GUARDED(x_nodes)
{
auto nit = m_nodes.find(make_pair(_s.id(), _s.info().clientVersion));
if (nit == m_nodes.end())
return false;
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):

1
libp2p/Host.h

@ -99,6 +99,7 @@ public:
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.
SharedMutex mutable x_nodes;
};
/**

Loading…
Cancel
Save