mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Convert mapBlocksInFlight to a multimap
Github-Pull: #27626
Rebased-From: cce96182ba
This commit is contained in:
parent
a45159b8e2
commit
38e3af9fad
1 changed files with 74 additions and 40 deletions
|
@ -900,7 +900,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
void FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|
||||||
typedef std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
|
/* Multimap used to preserve insertion order */
|
||||||
|
typedef std::multimap<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
|
||||||
BlockDownloadMap mapBlocksInFlight GUARDED_BY(cs_main);
|
BlockDownloadMap mapBlocksInFlight GUARDED_BY(cs_main);
|
||||||
|
|
||||||
/** When our tip was last updated. */
|
/** When our tip was last updated. */
|
||||||
|
@ -1124,34 +1125,40 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
|
||||||
|
|
||||||
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
|
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
|
||||||
{
|
{
|
||||||
auto it = mapBlocksInFlight.find(hash);
|
auto range = mapBlocksInFlight.equal_range(hash);
|
||||||
if (it == mapBlocksInFlight.end()) {
|
if (range.first == range.second) {
|
||||||
// Block was not requested
|
// Block was not requested from any peer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [node_id, list_it] = it->second;
|
// Currently we don't request more than one peer for same block
|
||||||
|
Assume(mapBlocksInFlight.count(hash) == 1);
|
||||||
|
|
||||||
if (from_peer && node_id != *from_peer) {
|
while (range.first != range.second) {
|
||||||
// Block was requested by another peer
|
auto [node_id, list_it] = range.first->second;
|
||||||
return;
|
|
||||||
|
if (from_peer && *from_peer != node_id) {
|
||||||
|
range.first++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CNodeState *state = State(node_id);
|
||||||
|
assert(state != nullptr);
|
||||||
|
|
||||||
|
if (state->vBlocksInFlight.begin() == list_it) {
|
||||||
|
// First block on the queue was received, update the start download time for the next one
|
||||||
|
state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
|
||||||
|
}
|
||||||
|
state->vBlocksInFlight.erase(list_it);
|
||||||
|
|
||||||
|
if (state->vBlocksInFlight.empty()) {
|
||||||
|
// Last validated block on the queue for this peer was received.
|
||||||
|
m_peers_downloading_from--;
|
||||||
|
}
|
||||||
|
state->m_stalling_since = 0us;
|
||||||
|
|
||||||
|
range.first = mapBlocksInFlight.erase(range.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
CNodeState *state = State(node_id);
|
|
||||||
assert(state != nullptr);
|
|
||||||
|
|
||||||
if (state->vBlocksInFlight.begin() == list_it) {
|
|
||||||
// First block on the queue was received, update the start download time for the next one
|
|
||||||
state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
|
|
||||||
}
|
|
||||||
state->vBlocksInFlight.erase(list_it);
|
|
||||||
|
|
||||||
if (state->vBlocksInFlight.empty()) {
|
|
||||||
// Last validated block on the queue was received.
|
|
||||||
m_peers_downloading_from--;
|
|
||||||
}
|
|
||||||
state->m_stalling_since = 0us;
|
|
||||||
mapBlocksInFlight.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
|
bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
|
||||||
|
@ -1162,12 +1169,13 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
|
||||||
assert(state != nullptr);
|
assert(state != nullptr);
|
||||||
|
|
||||||
// Short-circuit most stuff in case it is from the same node
|
// Short-circuit most stuff in case it is from the same node
|
||||||
BlockDownloadMap::iterator itInFlight = mapBlocksInFlight.find(hash);
|
for (auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
|
||||||
if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
|
if (range.first->second.first == nodeid) {
|
||||||
if (pit) {
|
if (pit) {
|
||||||
*pit = &itInFlight->second.second;
|
*pit = &range.first->second.second;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it's not listed somewhere already.
|
// Make sure it's not listed somewhere already.
|
||||||
|
@ -1180,7 +1188,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
|
||||||
state->m_downloading_since = GetTime<std::chrono::microseconds>();
|
state->m_downloading_since = GetTime<std::chrono::microseconds>();
|
||||||
m_peers_downloading_from++;
|
m_peers_downloading_from++;
|
||||||
}
|
}
|
||||||
itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
|
auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
|
||||||
if (pit) {
|
if (pit) {
|
||||||
*pit = &itInFlight->second.second;
|
*pit = &itInFlight->second.second;
|
||||||
}
|
}
|
||||||
|
@ -1383,7 +1391,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int co
|
||||||
}
|
}
|
||||||
} else if (waitingfor == -1) {
|
} else if (waitingfor == -1) {
|
||||||
// This is the first already-in-flight block.
|
// This is the first already-in-flight block.
|
||||||
waitingfor = mapBlocksInFlight[pindex->GetBlockHash()].first;
|
waitingfor = mapBlocksInFlight.lower_bound(pindex->GetBlockHash())->second.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1513,7 +1521,15 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
|
||||||
nSyncStarted--;
|
nSyncStarted--;
|
||||||
|
|
||||||
for (const QueuedBlock& entry : state->vBlocksInFlight) {
|
for (const QueuedBlock& entry : state->vBlocksInFlight) {
|
||||||
mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
|
auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
|
||||||
|
while (range.first != range.second) {
|
||||||
|
auto [node_id, list_it] = range.first->second;
|
||||||
|
if (node_id != nodeid) {
|
||||||
|
range.first++;
|
||||||
|
} else {
|
||||||
|
range.first = mapBlocksInFlight.erase(range.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_orphanage.EraseForPeer(nodeid);
|
m_orphanage.EraseForPeer(nodeid);
|
||||||
m_txrequest.DisconnectedPeer(nodeid);
|
m_txrequest.DisconnectedPeer(nodeid);
|
||||||
|
@ -4271,12 +4287,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
||||||
nodestate->m_last_block_announcement = GetTime();
|
nodestate->m_last_block_announcement = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockDownloadMap::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->GetBlockHash());
|
|
||||||
bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
|
|
||||||
|
|
||||||
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
|
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto range_flight = mapBlocksInFlight.equal_range(pindex->GetBlockHash());
|
||||||
|
bool fAlreadyInFlight = range_flight.first != range_flight.second;
|
||||||
|
bool in_flight_same_peer{false};
|
||||||
|
|
||||||
|
while (range_flight.first != range_flight.second) {
|
||||||
|
if (range_flight.first->second.first == pfrom.GetId()) {
|
||||||
|
in_flight_same_peer = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
range_flight.first++;
|
||||||
|
}
|
||||||
|
|
||||||
if (pindex->nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork || // We know something better
|
if (pindex->nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork || // We know something better
|
||||||
pindex->nTx != 0) { // We had this block at some point, but pruned it
|
pindex->nTx != 0) { // We had this block at some point, but pruned it
|
||||||
if (fAlreadyInFlight) {
|
if (fAlreadyInFlight) {
|
||||||
|
@ -4298,7 +4323,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
||||||
// possibilities in compact block processing...
|
// possibilities in compact block processing...
|
||||||
if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
|
if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
|
||||||
if ((!fAlreadyInFlight && nodestate->vBlocksInFlight.size() < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
|
if ((!fAlreadyInFlight && nodestate->vBlocksInFlight.size() < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
|
||||||
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom.GetId())) {
|
in_flight_same_peer) {
|
||||||
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
|
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
|
||||||
if (!BlockRequested(pfrom.GetId(), *pindex, &queuedBlockIt)) {
|
if (!BlockRequested(pfrom.GetId(), *pindex, &queuedBlockIt)) {
|
||||||
if (!(*queuedBlockIt)->partialBlock)
|
if (!(*queuedBlockIt)->partialBlock)
|
||||||
|
@ -4430,14 +4455,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
BlockDownloadMap::iterator it = mapBlocksInFlight.find(resp.blockhash);
|
bool expected_blocktxn = false;
|
||||||
if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
|
auto range_flight = mapBlocksInFlight.equal_range(resp.blockhash);
|
||||||
it->second.first != pfrom.GetId()) {
|
while (range_flight.first != range_flight.second) {
|
||||||
|
auto [node_id, block_it] = range_flight.first->second;
|
||||||
|
if (node_id == pfrom.GetId() && block_it->partialBlock) {
|
||||||
|
expected_blocktxn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
range_flight.first++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expected_blocktxn) {
|
||||||
LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom.GetId());
|
LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom.GetId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
|
PartiallyDownloadedBlock& partialBlock = *range_flight.first->second.second->partialBlock;
|
||||||
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
|
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
|
||||||
if (status == READ_STATUS_INVALID) {
|
if (status == READ_STATUS_INVALID) {
|
||||||
RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
|
RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
|
||||||
|
|
Loading…
Add table
Reference in a new issue