net: don't relay to the address' originator

For each address to be relayed we "randomly" pick 2 nodes to send the
address to (in `RelayAddress()`). However we do not take into
consideration that it does not make sense to relay the address back to
its originator (`CNode::PushAddress()` will do nothing in that case).

This means that if the originator is among the "randomly" picked nodes,
then we will relay to one node less than intended.

Fix this by skipping the originating node when choosing candidates to
relay to.
This commit is contained in:
Vasil Dimov
2020-08-18 21:30:12 +02:00
parent bd60a9a8ed
commit 7fabe0f359
2 changed files with 48 additions and 13 deletions

View File

@@ -1517,7 +1517,23 @@ void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman&
});
}
static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
/**
* Relay (gossip) an address to a few randomly chosen nodes.
* We choose the same nodes within a given 24h window (if the list of connected
* nodes does not change) and we don't relay to nodes that already know an
* address. So within 24h we will likely relay a given address once. This is to
* prevent a peer from unjustly giving their address better propagation by sending
* it to us repeatedly.
* @param[in] originator The peer that sent us the address. We don't want to relay it back.
* @param[in] addr Address to relay.
* @param[in] fReachable Whether the address' network is reachable. We relay unreachable
* addresses less.
* @param[in] connman Connection manager to choose nodes to relay to.
*/
static void RelayAddress(const CNode& originator,
const CAddress& addr,
bool fReachable,
const CConnman& connman)
{
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
@@ -1531,8 +1547,8 @@ static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman&
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
assert(nRelayNodes <= best.size());
auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
if (pnode->RelayAddrsWithConn()) {
auto sortfunc = [&best, &hasher, nRelayNodes, &originator](CNode* pnode) {
if (pnode->RelayAddrsWithConn() && pnode != &originator) {
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
@@ -2637,7 +2653,7 @@ void PeerLogicValidation::ProcessMessage(CNode& pfrom, const std::string& msg_ty
if (addr.nTime > nSince && !pfrom.fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
// Relay to a limited number of other nodes
RelayAddress(addr, fReachable, m_connman);
RelayAddress(pfrom, addr, fReachable, m_connman);
}
// Do not store addresses outside our network
if (fReachable)