mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 23:07:59 +01:00
Merge #21236: net processing: Extract addr
send functionality into MaybeSendAddr()
935d488922
[net processing] Refactor MaybeSendAddr() (John Newbery)01a79ff924
[net processing] Fix overindentation in MaybeSendAddr() (John Newbery)38c0be5da3
[net processing] Refactor MaybeSendAddr() - early exits (John Newbery)c87423c58b
[net processing] Change MaybeSendAddr() to take a reference (John Newbery)ad719297f2
[net processing] Extract `addr` send functionality into MaybeSendAddr() (John Newbery)4ad4abcf07
[net] Change addr send times fields to be guarded by new mutex (John Newbery)c02fa47baa
[net processing] Only call GetTime() once in SendMessages() (John Newbery) Pull request description: This continues the work of moving application layer data into net_processing. It refactors `addr` send functionality into its own function `MaybeSendAddr()` and flattens/simplifies the code. Isolating and simplifying the addr handling code makes subsequent changes (which will move addr data and logic into net processing) easier to review. This is a pure refactor. There are no functional changes. For motivation of the project, see #19398. ACKs for top commit: sipa: utACK935d488922
hebasto: ACK935d488922
, I have reviewed the code and it looks OK, I agree it can be merged. MarcoFalke: review ACK935d488922
🐑 Tree-SHA512: 4e9dc84603147e74f479a211b42bcf315bdf5d14c21c08cf0b17d6c252775b90b012f0e0d834f1a607ed63c7ed5c63d5cf49b134344e7b64a1695bfcff111c92
This commit is contained in:
commit
539e4eec63
2 changed files with 87 additions and 75 deletions
|
@ -549,8 +549,9 @@ public:
|
||||||
std::vector<CAddress> vAddrToSend;
|
std::vector<CAddress> vAddrToSend;
|
||||||
std::unique_ptr<CRollingBloomFilter> m_addr_known{nullptr};
|
std::unique_ptr<CRollingBloomFilter> m_addr_known{nullptr};
|
||||||
bool fGetAddr{false};
|
bool fGetAddr{false};
|
||||||
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
|
Mutex m_addr_send_times_mutex;
|
||||||
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
|
std::chrono::microseconds m_next_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
|
||||||
|
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(m_addr_send_times_mutex){0};
|
||||||
|
|
||||||
struct TxRelay {
|
struct TxRelay {
|
||||||
mutable RecursiveMutex cs_filter;
|
mutable RecursiveMutex cs_filter;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
@ -317,8 +318,13 @@ private:
|
||||||
void PushNodeVersion(CNode& pnode, int64_t nTime);
|
void PushNodeVersion(CNode& pnode, int64_t nTime);
|
||||||
|
|
||||||
/** Send a ping message every PING_INTERVAL or if requested via RPC. May
|
/** Send a ping message every PING_INTERVAL or if requested via RPC. May
|
||||||
* mark the peer to be disconnected if a ping has timed out. */
|
* mark the peer to be disconnected if a ping has timed out.
|
||||||
void MaybeSendPing(CNode& node_to, Peer& peer);
|
* We use mockable time for ping timeouts, so setmocktime may cause pings
|
||||||
|
* to time out. */
|
||||||
|
void MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now);
|
||||||
|
|
||||||
|
/** Send `addr` messages on a regular schedule. */
|
||||||
|
void MaybeSendAddr(CNode& node, std::chrono::microseconds current_time);
|
||||||
|
|
||||||
const CChainParams& m_chainparams;
|
const CChainParams& m_chainparams;
|
||||||
CConnman& m_connman;
|
CConnman& m_connman;
|
||||||
|
@ -4100,12 +4106,8 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer)
|
void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now)
|
||||||
{
|
{
|
||||||
// Use mockable time for ping timeouts.
|
|
||||||
// This means that setmocktime may cause pings to time out.
|
|
||||||
auto now = GetTime<std::chrono::microseconds>();
|
|
||||||
|
|
||||||
if (m_connman.RunInactivityChecks(node_to) && peer.m_ping_nonce_sent &&
|
if (m_connman.RunInactivityChecks(node_to) && peer.m_ping_nonce_sent &&
|
||||||
now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) {
|
now > peer.m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL}) {
|
||||||
LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n", 0.000001 * count_microseconds(now - peer.m_ping_start.load()), peer.m_id);
|
LogPrint(BCLog::NET, "ping timeout: %fs peer=%d\n", 0.000001 * count_microseconds(now - peer.m_ping_start.load()), peer.m_id);
|
||||||
|
@ -4144,6 +4146,75 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PeerManagerImpl::MaybeSendAddr(CNode& node, std::chrono::microseconds current_time)
|
||||||
|
{
|
||||||
|
// Nothing to do for non-address-relay peers
|
||||||
|
if (!node.RelayAddrsWithConn()) return;
|
||||||
|
|
||||||
|
assert(node.m_addr_known);
|
||||||
|
|
||||||
|
LOCK(node.m_addr_send_times_mutex);
|
||||||
|
// Periodically advertise our local address to the peer.
|
||||||
|
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
|
||||||
|
node.m_next_local_addr_send < current_time) {
|
||||||
|
// If we've sent before, clear the bloom filter for the peer, so that our
|
||||||
|
// self-announcement will actually go out.
|
||||||
|
// This might be unnecessary if the bloom filter has already rolled
|
||||||
|
// over since our last self-announcement, but there is only a small
|
||||||
|
// bandwidth cost that we can incur by doing this (which happens
|
||||||
|
// once a day on average).
|
||||||
|
if (node.m_next_local_addr_send != 0us) {
|
||||||
|
node.m_addr_known->reset();
|
||||||
|
}
|
||||||
|
if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(&node)) {
|
||||||
|
FastRandomContext insecure_rand;
|
||||||
|
node.PushAddress(*local_addr, insecure_rand);
|
||||||
|
}
|
||||||
|
node.m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We sent an `addr` message to this peer recently. Nothing more to do.
|
||||||
|
if (current_time <= node.m_next_addr_send) return;
|
||||||
|
|
||||||
|
node.m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
|
||||||
|
|
||||||
|
if (!Assume(node.vAddrToSend.size() <= MAX_ADDR_TO_SEND)) {
|
||||||
|
// Should be impossible since we always check size before adding to
|
||||||
|
// vAddrToSend. Recover by trimming the vector.
|
||||||
|
node.vAddrToSend.resize(MAX_ADDR_TO_SEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove addr records that the peer already knows about, and add new
|
||||||
|
// addrs to the m_addr_known filter on the same pass.
|
||||||
|
auto addr_already_known = [&node](const CAddress& addr) {
|
||||||
|
bool ret = node.m_addr_known->contains(addr.GetKey());
|
||||||
|
if (!ret) node.m_addr_known->insert(addr.GetKey());
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
node.vAddrToSend.erase(std::remove_if(node.vAddrToSend.begin(), node.vAddrToSend.end(), addr_already_known),
|
||||||
|
node.vAddrToSend.end());
|
||||||
|
|
||||||
|
// No addr messages to send
|
||||||
|
if (node.vAddrToSend.empty()) return;
|
||||||
|
|
||||||
|
const char* msg_type;
|
||||||
|
int make_flags;
|
||||||
|
if (node.m_wants_addrv2) {
|
||||||
|
msg_type = NetMsgType::ADDRV2;
|
||||||
|
make_flags = ADDRV2_FORMAT;
|
||||||
|
} else {
|
||||||
|
msg_type = NetMsgType::ADDR;
|
||||||
|
make_flags = 0;
|
||||||
|
}
|
||||||
|
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(make_flags, msg_type, node.vAddrToSend));
|
||||||
|
node.vAddrToSend.clear();
|
||||||
|
|
||||||
|
// we only send the big addr message once
|
||||||
|
if (node.vAddrToSend.capacity() > 40) {
|
||||||
|
node.vAddrToSend.shrink_to_fit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class CompareInvMempoolOrder
|
class CompareInvMempoolOrder
|
||||||
{
|
{
|
||||||
|
@ -4182,79 +4253,20 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||||
// If we get here, the outgoing message serialization version is set and can't change.
|
// If we get here, the outgoing message serialization version is set and can't change.
|
||||||
const CNetMsgMaker msgMaker(pto->GetCommonVersion());
|
const CNetMsgMaker msgMaker(pto->GetCommonVersion());
|
||||||
|
|
||||||
MaybeSendPing(*pto, *peer);
|
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||||
|
|
||||||
|
MaybeSendPing(*pto, *peer, current_time);
|
||||||
|
|
||||||
// MaybeSendPing may have marked peer for disconnection
|
// MaybeSendPing may have marked peer for disconnection
|
||||||
if (pto->fDisconnect) return true;
|
if (pto->fDisconnect) return true;
|
||||||
|
|
||||||
|
MaybeSendAddr(*pto, current_time);
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
CNodeState &state = *State(pto->GetId());
|
CNodeState &state = *State(pto->GetId());
|
||||||
|
|
||||||
// Address refresh broadcast
|
|
||||||
auto current_time = GetTime<std::chrono::microseconds>();
|
|
||||||
|
|
||||||
if (fListen && pto->RelayAddrsWithConn() &&
|
|
||||||
!m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
|
|
||||||
pto->m_next_local_addr_send < current_time) {
|
|
||||||
// If we've sent before, clear the bloom filter for the peer, so that our
|
|
||||||
// self-announcement will actually go out.
|
|
||||||
// This might be unnecessary if the bloom filter has already rolled
|
|
||||||
// over since our last self-announcement, but there is only a small
|
|
||||||
// bandwidth cost that we can incur by doing this (which happens
|
|
||||||
// once a day on average).
|
|
||||||
if (pto->m_next_local_addr_send != 0us) {
|
|
||||||
pto->m_addr_known->reset();
|
|
||||||
}
|
|
||||||
if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(pto)) {
|
|
||||||
FastRandomContext insecure_rand;
|
|
||||||
pto->PushAddress(*local_addr, insecure_rand);
|
|
||||||
}
|
|
||||||
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Message: addr
|
|
||||||
//
|
|
||||||
if (pto->RelayAddrsWithConn() && pto->m_next_addr_send < current_time) {
|
|
||||||
pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
|
|
||||||
std::vector<CAddress> vAddr;
|
|
||||||
vAddr.reserve(pto->vAddrToSend.size());
|
|
||||||
assert(pto->m_addr_known);
|
|
||||||
|
|
||||||
const char* msg_type;
|
|
||||||
int make_flags;
|
|
||||||
if (pto->m_wants_addrv2) {
|
|
||||||
msg_type = NetMsgType::ADDRV2;
|
|
||||||
make_flags = ADDRV2_FORMAT;
|
|
||||||
} else {
|
|
||||||
msg_type = NetMsgType::ADDR;
|
|
||||||
make_flags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const CAddress& addr : pto->vAddrToSend)
|
|
||||||
{
|
|
||||||
if (!pto->m_addr_known->contains(addr.GetKey()))
|
|
||||||
{
|
|
||||||
pto->m_addr_known->insert(addr.GetKey());
|
|
||||||
vAddr.push_back(addr);
|
|
||||||
// receiver rejects addr messages larger than MAX_ADDR_TO_SEND
|
|
||||||
if (vAddr.size() >= MAX_ADDR_TO_SEND)
|
|
||||||
{
|
|
||||||
m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
|
|
||||||
vAddr.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pto->vAddrToSend.clear();
|
|
||||||
if (!vAddr.empty())
|
|
||||||
m_connman.PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
|
|
||||||
// we only send the big addr message once
|
|
||||||
if (pto->vAddrToSend.capacity() > 40)
|
|
||||||
pto->vAddrToSend.shrink_to_fit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start block sync
|
// Start block sync
|
||||||
if (pindexBestHeader == nullptr)
|
if (pindexBestHeader == nullptr)
|
||||||
pindexBestHeader = m_chainman.ActiveChain().Tip();
|
pindexBestHeader = m_chainman.ActiveChain().Tip();
|
||||||
|
@ -4489,7 +4501,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||||
vInv.clear();
|
vInv.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pto->m_tx_relay->m_last_mempool_req = GetTime<std::chrono::seconds>();
|
pto->m_tx_relay->m_last_mempool_req = std::chrono::duration_cast<std::chrono::seconds>(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine transactions to relay
|
// Determine transactions to relay
|
||||||
|
@ -4577,7 +4589,6 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||||
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
||||||
|
|
||||||
// Detect whether we're stalling
|
// Detect whether we're stalling
|
||||||
current_time = GetTime<std::chrono::microseconds>();
|
|
||||||
if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
|
if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
|
||||||
// Stalling only triggers when the block download window cannot move. During normal steady state,
|
// Stalling only triggers when the block download window cannot move. During normal steady state,
|
||||||
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
|
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
|
||||||
|
|
Loading…
Add table
Reference in a new issue