[net processing] Move block inventory data to Peer

This commit is contained in:
John Newbery 2020-06-19 13:29:05 -04:00
parent 78040f9168
commit 53b7ac1b7d
3 changed files with 34 additions and 28 deletions

View File

@ -1006,12 +1006,6 @@ public:
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0}; std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0}; std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
// List of block ids we still have announce.
// There is no final sorting before sending, as they are always sent immediately
// and in the order requested.
std::vector<uint256> vInventoryBlockToSend GUARDED_BY(cs_inventory);
Mutex cs_inventory;
struct TxRelay { struct TxRelay {
mutable RecursiveMutex cs_filter; mutable RecursiveMutex cs_filter;
// We use fRelayTxes for two purposes - // We use fRelayTxes for two purposes -
@ -1042,9 +1036,6 @@ public:
// m_tx_relay == nullptr if we're not relaying transactions with this peer // m_tx_relay == nullptr if we're not relaying transactions with this peer
std::unique_ptr<TxRelay> m_tx_relay; std::unique_ptr<TxRelay> m_tx_relay;
// Used for headers announcements - unfiltered blocks to relay
std::vector<uint256> vBlockHashesToAnnounce GUARDED_BY(cs_inventory);
/** UNIX epoch time of the last block received from this peer that we had /** UNIX epoch time of the last block received from this peer that we had
* not yet seen (e.g. not already received from another peer), that passed * not yet seen (e.g. not already received from another peer), that passed
* preliminary validity checks and was saved to disk, even if we don't * preliminary validity checks and was saved to disk, even if we don't

View File

@ -1315,13 +1315,17 @@ void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInde
} }
} }
// Relay to all peers {
m_connman.ForEachNode([&vHashes](CNode* pnode) { LOCK(m_peer_mutex);
LOCK(pnode->cs_inventory); for (auto& it : m_peer_map) {
for (const uint256& hash : reverse_iterate(vHashes)) { Peer& peer = *it.second;
pnode->vBlockHashesToAnnounce.push_back(hash); LOCK(peer.m_block_inv_mutex);
for (const uint256& hash : reverse_iterate(vHashes)) {
peer.vBlockHashesToAnnounce.push_back(hash);
}
} }
}); }
m_connman.WakeMessageHandler(); m_connman.WakeMessageHandler();
} }
@ -2795,7 +2799,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
break; break;
} }
WITH_LOCK(pfrom.cs_inventory, pfrom.vInventoryBlockToSend.push_back(pindex->GetBlockHash())); WITH_LOCK(peer->m_block_inv_mutex, peer->vInventoryBlockToSend.push_back(pindex->GetBlockHash()));
if (--nLimit <= 0) if (--nLimit <= 0)
{ {
// When this block is requested, we'll send an inv that'll // When this block is requested, we'll send an inv that'll
@ -4218,11 +4222,11 @@ bool PeerManager::SendMessages(CNode* pto)
// If no header would connect, or if we have too many // If no header would connect, or if we have too many
// blocks, or if the peer doesn't want headers, just // blocks, or if the peer doesn't want headers, just
// add all to the inv queue. // add all to the inv queue.
LOCK(pto->cs_inventory); LOCK(peer->m_block_inv_mutex);
std::vector<CBlock> vHeaders; std::vector<CBlock> vHeaders;
bool fRevertToInv = ((!state.fPreferHeaders && bool fRevertToInv = ((!state.fPreferHeaders &&
(!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) || (!state.fPreferHeaderAndIDs || peer->vBlockHashesToAnnounce.size() > 1)) ||
pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE); peer->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE);
const CBlockIndex *pBestIndex = nullptr; // last header queued for delivery const CBlockIndex *pBestIndex = nullptr; // last header queued for delivery
ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date
@ -4231,7 +4235,7 @@ bool PeerManager::SendMessages(CNode* pto)
// Try to find first header that our peer doesn't have, and // Try to find first header that our peer doesn't have, and
// then send all headers past that one. If we come across any // then send all headers past that one. If we come across any
// headers that aren't on ::ChainActive(), give up. // headers that aren't on ::ChainActive(), give up.
for (const uint256 &hash : pto->vBlockHashesToAnnounce) { for (const uint256& hash : peer->vBlockHashesToAnnounce) {
const CBlockIndex* pindex = LookupBlockIndex(hash); const CBlockIndex* pindex = LookupBlockIndex(hash);
assert(pindex); assert(pindex);
if (::ChainActive()[pindex->nHeight] != pindex) { if (::ChainActive()[pindex->nHeight] != pindex) {
@ -4322,8 +4326,8 @@ bool PeerManager::SendMessages(CNode* pto)
// If falling back to using an inv, just try to inv the tip. // If falling back to using an inv, just try to inv the tip.
// The last entry in vBlockHashesToAnnounce was our tip at some point // The last entry in vBlockHashesToAnnounce was our tip at some point
// in the past. // in the past.
if (!pto->vBlockHashesToAnnounce.empty()) { if (!peer->vBlockHashesToAnnounce.empty()) {
const uint256 &hashToAnnounce = pto->vBlockHashesToAnnounce.back(); const uint256& hashToAnnounce = peer->vBlockHashesToAnnounce.back();
const CBlockIndex* pindex = LookupBlockIndex(hashToAnnounce); const CBlockIndex* pindex = LookupBlockIndex(hashToAnnounce);
assert(pindex); assert(pindex);
@ -4337,13 +4341,13 @@ bool PeerManager::SendMessages(CNode* pto)
// If the peer's chain has this block, don't inv it back. // If the peer's chain has this block, don't inv it back.
if (!PeerHasHeader(&state, pindex)) { if (!PeerHasHeader(&state, pindex)) {
pto->vInventoryBlockToSend.push_back(hashToAnnounce); peer->vInventoryBlockToSend.push_back(hashToAnnounce);
LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__, LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__,
pto->GetId(), hashToAnnounce.ToString()); pto->GetId(), hashToAnnounce.ToString());
} }
} }
} }
pto->vBlockHashesToAnnounce.clear(); peer->vBlockHashesToAnnounce.clear();
} }
// //
@ -4351,18 +4355,18 @@ bool PeerManager::SendMessages(CNode* pto)
// //
std::vector<CInv> vInv; std::vector<CInv> vInv;
{ {
LOCK(pto->cs_inventory); LOCK(peer->m_block_inv_mutex);
vInv.reserve(std::max<size_t>(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX)); vInv.reserve(std::max<size_t>(peer->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX));
// Add blocks // Add blocks
for (const uint256& hash : pto->vInventoryBlockToSend) { for (const uint256& hash : peer->vInventoryBlockToSend) {
vInv.push_back(CInv(MSG_BLOCK, hash)); vInv.push_back(CInv(MSG_BLOCK, hash));
if (vInv.size() == MAX_INV_SZ) { if (vInv.size() == MAX_INV_SZ) {
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv)); m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear(); vInv.clear();
} }
} }
pto->vInventoryBlockToSend.clear(); peer->vInventoryBlockToSend.clear();
if (pto->m_tx_relay != nullptr) { if (pto->m_tx_relay != nullptr) {
LOCK(pto->m_tx_relay->cs_tx_inventory); LOCK(pto->m_tx_relay->cs_tx_inventory);

View File

@ -63,6 +63,17 @@ struct Peer {
/** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */ /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false}; bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
/** Protects block inventory data members */
Mutex m_block_inv_mutex;
/** List of blocks that we'll anounce via an `inv` message.
* There is no final sorting before sending, as they are always sent
* immediately and in the order requested. */
std::vector<uint256> vInventoryBlockToSend GUARDED_BY(m_block_inv_mutex);
/** Unfiltered list of blocks that we'd like to announce via a `headers`
* message. If we can't announce via a `headers` message, we'll fall back to
* announcing via `inv`. */
std::vector<uint256> vBlockHashesToAnnounce GUARDED_BY(m_block_inv_mutex);
/** This peer's reported block height when we connected */ /** This peer's reported block height when we connected */
std::atomic<int> m_starting_height{-1}; std::atomic<int> m_starting_height{-1};