Browse Source

Prevent sync from downloading unknown blocks that are already in the queue

cl-refactor
arkpar 10 years ago
parent
commit
7a10f55f13
  1. 40
      libethereum/BlockChainSync.cpp
  2. 17
      libethereum/BlockChainSync.h

40
libethereum/BlockChainSync.cpp

@ -916,26 +916,23 @@ void PV61Sync::requestSubchain(std::shared_ptr<EthereumPeer> _peer)
if (syncPeer != m_chainSyncPeers.end()) if (syncPeer != m_chainSyncPeers.end())
{ {
// Already downoading, request next batch // Already downoading, request next batch
h256s& d = m_downloadingChainMap.at(syncPeer->second); SubChain const& s = m_downloadingChainMap.at(syncPeer->second);
_peer->requestHashes(d.back()); _peer->requestHashes(s.lastHash);
} }
else if (needsSyncing(_peer)) else if (needsSyncing(_peer))
{ {
if (!m_readyChainMap.empty()) if (!m_readyChainMap.empty())
{ {
clog(NetAllDetail) << "Helping with hashchin download"; clog(NetAllDetail) << "Helping with hashchin download";
h256s& d = m_readyChainMap.begin()->second; SubChain& s = m_readyChainMap.begin()->second;
_peer->requestHashes(d.back()); _peer->requestHashes(s.lastHash);
m_downloadingChainMap[m_readyChainMap.begin()->first] = move(d); m_downloadingChainMap[m_readyChainMap.begin()->first] = move(s);
m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first; m_chainSyncPeers[_peer] = m_readyChainMap.begin()->first;
m_readyChainMap.erase(m_readyChainMap.begin()); m_readyChainMap.erase(m_readyChainMap.begin());
} }
else if (!m_downloadingChainMap.empty() && m_hashScanComplete) else if (!m_downloadingChainMap.empty() && m_hashScanComplete)
{
// Lead syncer is done, just grab whatever we can // Lead syncer is done, just grab whatever we can
h256s& d = m_downloadingChainMap.begin()->second; _peer->requestHashes(m_downloadingChainMap.begin()->second.lastHash);
_peer->requestHashes(d.back());
}
} }
} }
@ -974,7 +971,7 @@ void PV61Sync::completeSubchain(std::shared_ptr<EthereumPeer> _peer, unsigned _n
//Done chain-get //Done chain-get
m_syncingNeededBlocks.clear(); m_syncingNeededBlocks.clear();
for (auto h = m_completeChainMap.rbegin(); h != m_completeChainMap.rend(); ++h) for (auto h = m_completeChainMap.rbegin(); h != m_completeChainMap.rend(); ++h)
m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), h->second.begin(), h->second.end()); m_syncingNeededBlocks.insert(m_syncingNeededBlocks.end(), h->second.hashes.begin(), h->second.hashes.end());
m_completeChainMap.clear(); m_completeChainMap.clear();
m_knownHashes.clear(); m_knownHashes.clear();
m_syncingBlockNumber = 0; m_syncingBlockNumber = 0;
@ -1010,7 +1007,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber) if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber)
{ {
// End of hash chain, add last chunk to download // End of hash chain, add last chunk to download
m_readyChainMap.insert(make_pair(m_syncingBlockNumber, h256s { _peer->m_latestHash })); m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _peer->m_latestHash }, _peer->m_latestHash }));
m_hashScanComplete = true; m_hashScanComplete = true;
_peer->m_syncHashNumber = 0; _peer->m_syncHashNumber = 0;
requestSubchain(_peer); requestSubchain(_peer);
@ -1038,7 +1035,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
// Got new subchain marker // Got new subchain marker
assert(_hashes.size() == 1); assert(_hashes.size() == 1);
m_knownHashes.insert(_hashes[0]); m_knownHashes.insert(_hashes[0]);
m_readyChainMap.insert(make_pair(m_syncingBlockNumber, h256s { _hashes[0] })); m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _hashes[0] }, _hashes[0] }));
if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes) if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes)
{ {
_peer->disable("Too many hashes from lead peer"); _peer->disable("Too many hashes from lead peer");
@ -1056,7 +1053,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
{ {
//check downlading peers //check downlading peers
for (auto const& downloader: m_downloadingChainMap) for (auto const& downloader: m_downloadingChainMap)
if (downloader.second.back() == _peer->m_syncHash) if (downloader.second.lastHash == _peer->m_syncHash)
{ {
number = downloader.first; number = downloader.first;
break; break;
@ -1071,7 +1068,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
} }
auto downloadingPeer = m_downloadingChainMap.find(number); auto downloadingPeer = m_downloadingChainMap.find(number);
if (downloadingPeer == m_downloadingChainMap.end() || downloadingPeer->second.back() != _peer->m_syncHash) if (downloadingPeer == m_downloadingChainMap.end() || downloadingPeer->second.lastHash != _peer->m_syncHash)
{ {
// Too late, other peer has already downloaded our hashes // Too late, other peer has already downloaded our hashes
m_chainSyncPeers.erase(_peer); m_chainSyncPeers.erase(_peer);
@ -1079,7 +1076,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
return; return;
} }
h256s& hashes = downloadingPeer->second; SubChain& subChain = downloadingPeer->second;
unsigned knowns = 0; unsigned knowns = 0;
unsigned unknowns = 0; unsigned unknowns = 0;
for (unsigned i = 0; i < _hashes.size(); ++i) for (unsigned i = 0; i < _hashes.size(); ++i)
@ -1111,13 +1108,14 @@ void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _h
else if (status == QueueStatus::Unknown) else if (status == QueueStatus::Unknown)
{ {
unknowns++; unknowns++;
hashes.push_back(h); subChain.hashes.push_back(h);
} }
else else
knowns++; knowns++;
subChain.lastHash = h;
} }
clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << hashes.back(); clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << subChain.lastHash;
if (hashes.size() > c_hashSubchainSize) if (subChain.hashes.size() > c_hashSubchainSize)
{ {
_peer->disable("Too many subchain hashes"); _peer->disable("Too many subchain hashes");
restartSync(); restartSync();
@ -1175,11 +1173,11 @@ SyncStatus PV61Sync::status() const
{ {
res.hashesReceived = 0; res.hashesReceived = 0;
for (auto const& d : m_readyChainMap) for (auto const& d : m_readyChainMap)
res.hashesReceived += d.second.size(); res.hashesReceived += d.second.hashes.size();
for (auto const& d : m_downloadingChainMap) for (auto const& d : m_downloadingChainMap)
res.hashesReceived += d.second.size(); res.hashesReceived += d.second.hashes.size();
for (auto const& d : m_completeChainMap) for (auto const& d : m_completeChainMap)
res.hashesReceived += d.second.size(); res.hashesReceived += d.second.hashes.size();
} }
return res; return res;
} }

17
libethereum/BlockChainSync.h

@ -126,7 +126,6 @@ private:
void logNewBlock(h256 const& _h); void logNewBlock(h256 const& _h);
EthereumHost& m_host; EthereumHost& m_host;
HashDownloadMan m_hashMan;
}; };
@ -308,12 +307,18 @@ private:
/// Check if downloading hashes in parallel /// Check if downloading hashes in parallel
bool isPV61Syncing() const; bool isPV61Syncing() const;
std::map<unsigned, h256s> m_completeChainMap; ///< Fully downloaded subchains struct SubChain
std::map<unsigned, h256s> m_readyChainMap; ///< Subchains ready for download {
std::map<unsigned, h256s> m_downloadingChainMap; ///< Subchains currently being downloading. In sync with m_chainSyncPeers h256s hashes; ///< List of subchain hashes
h256 lastHash; ///< Last requested subchain hash
};
std::map<unsigned, SubChain> m_completeChainMap; ///< Fully downloaded subchains
std::map<unsigned, SubChain> m_readyChainMap; ///< Subchains ready for download
std::map<unsigned, SubChain> m_downloadingChainMap; ///< Subchains currently being downloading. In sync with m_chainSyncPeers
std::map<std::weak_ptr<EthereumPeer>, unsigned, std::owner_less<std::weak_ptr<EthereumPeer>>> m_chainSyncPeers; ///< Peers to m_downloadingSubchain number map std::map<std::weak_ptr<EthereumPeer>, unsigned, std::owner_less<std::weak_ptr<EthereumPeer>>> m_chainSyncPeers; ///< Peers to m_downloadingSubchain number map
h256Hash m_knownHashes; ///< Subchain start markers. Used to track suchain completion h256Hash m_knownHashes; ///< Subchain start markers. Used to track suchain completion
unsigned m_syncingBlockNumber = 0; ///< Current subchain marker unsigned m_syncingBlockNumber = 0; ///< Current subchain marker
bool m_hashScanComplete = false; ///< True if leading peer completed hashchain scan and we have a list of subchains ready bool m_hashScanComplete = false; ///< True if leading peer completed hashchain scan and we have a list of subchains ready
}; };

Loading…
Cancel
Save