mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
Merge 06788c6705 into merged_master (Bitcoin PR bitcoin/bitcoin#21528)
This commit is contained in:
commit
05f9a1a7c2
5 changed files with 144 additions and 24 deletions
|
|
@ -225,9 +225,31 @@ struct Peer {
|
|||
|
||||
/** A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
|
||||
std::vector<CAddress> m_addrs_to_send;
|
||||
/** Probabilistic filter of addresses that this peer already knows.
|
||||
* Used to avoid relaying addresses to this peer more than once. */
|
||||
const std::unique_ptr<CRollingBloomFilter> m_addr_known;
|
||||
/** Probabilistic filter to track recent addr messages relayed with this
|
||||
* peer. Used to avoid relaying redundant addresses to this peer.
|
||||
*
|
||||
* We initialize this filter for outbound peers (other than
|
||||
* block-relay-only connections) or when an inbound peer sends us an
|
||||
* address related message (ADDR, ADDRV2, GETADDR).
|
||||
*
|
||||
* Presence of this filter must correlate with m_addr_relay_enabled.
|
||||
**/
|
||||
std::unique_ptr<CRollingBloomFilter> m_addr_known;
|
||||
/** Whether we are participating in address relay with this connection.
|
||||
*
|
||||
* We set this bool to true for outbound peers (other than
|
||||
* block-relay-only connections), or when an inbound peer sends us an
|
||||
* address related message (ADDR, ADDRV2, GETADDR).
|
||||
*
|
||||
* We use this bool to decide whether a peer is eligible for gossiping
|
||||
* addr messages. This avoids relaying to peers that are unlikely to
|
||||
* forward them, effectively blackholing self announcements. Reasons
|
||||
* peers might support addr relay on the link include that they connected
|
||||
* to us as a block-relay-only peer or they are a light client.
|
||||
*
|
||||
* This field must correlate with whether m_addr_known has been
|
||||
* initialized.*/
|
||||
std::atomic_bool m_addr_relay_enabled{false};
|
||||
/** Whether a getaddr request to this peer is outstanding. */
|
||||
bool m_getaddr_sent{false};
|
||||
/** Guards address sending timers. */
|
||||
|
|
@ -259,9 +281,8 @@ struct Peer {
|
|||
/** Work queue of items requested by this peer **/
|
||||
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
|
||||
|
||||
explicit Peer(NodeId id, bool addr_relay)
|
||||
explicit Peer(NodeId id)
|
||||
: m_id(id)
|
||||
, m_addr_known{addr_relay ? std::make_unique<CRollingBloomFilter>(5000, 0.001) : nullptr}
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
@ -624,6 +645,14 @@ private:
|
|||
* @param[in] vRecv The raw message received
|
||||
*/
|
||||
void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv);
|
||||
|
||||
/** Checks if address relay is permitted with peer. If needed, initializes
|
||||
* the m_addr_known bloom filter and sets m_addr_relay_enabled to true.
|
||||
*
|
||||
* @return True if address relay is enabled with peer
|
||||
* False if address relay is disallowed
|
||||
*/
|
||||
bool SetupAddressRelay(CNode& node, Peer& peer);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
|
@ -744,11 +773,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
static bool RelayAddrsWithPeer(const Peer& peer)
|
||||
{
|
||||
return peer.m_addr_known != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the peer supports the address. For example, a peer that does not
|
||||
* implement BIP155 cannot receive Tor v3 addresses because it requires
|
||||
|
|
@ -1133,9 +1157,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
|
|||
assert(m_txrequest.Count(nodeid) == 0);
|
||||
}
|
||||
{
|
||||
// Addr relay is disabled for outbound block-relay-only peers to
|
||||
// prevent adversaries from inferring these links from addr traffic.
|
||||
PeerRef peer = std::make_shared<Peer>(nodeid, /* addr_relay = */ !pnode->IsBlockOnlyConn());
|
||||
PeerRef peer = std::make_shared<Peer>(nodeid);
|
||||
LOCK(m_peer_mutex);
|
||||
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
|
||||
}
|
||||
|
|
@ -1274,6 +1296,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
|
|||
stats.m_ping_wait = ping_wait;
|
||||
stats.m_addr_processed = peer->m_addr_processed.load();
|
||||
stats.m_addr_rate_limited = peer->m_addr_rate_limited.load();
|
||||
stats.m_addr_relay_enabled = peer->m_addr_relay_enabled.load();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1688,7 +1711,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
|
|||
LOCK(m_peer_mutex);
|
||||
|
||||
for (auto& [id, peer] : m_peer_map) {
|
||||
if (RelayAddrsWithPeer(*peer) && id != originator && IsAddrCompatible(*peer, addr)) {
|
||||
if (peer->m_addr_relay_enabled && id != originator && IsAddrCompatible(*peer, addr)) {
|
||||
uint64_t hashKey = CSipHasher(hasher).Write(id).Finalize();
|
||||
for (unsigned int i = 0; i < nRelayNodes; i++) {
|
||||
if (hashKey > best[i].first) {
|
||||
|
|
@ -2625,7 +2648,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
UpdatePreferredDownload(pfrom, State(pfrom.GetId()));
|
||||
}
|
||||
|
||||
if (!pfrom.IsInboundConn() && !pfrom.IsBlockOnlyConn()) {
|
||||
// Self advertisement & GETADDR logic
|
||||
if (!pfrom.IsInboundConn() && SetupAddressRelay(pfrom, *peer)) {
|
||||
// For outbound peers, we try to relay our address (so that other
|
||||
// nodes can try to find us more quickly, as we have no guarantee
|
||||
// that an outbound peer is even aware of how to reach us) and do a
|
||||
|
|
@ -2634,8 +2658,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
// empty and no one will know who we are, so these mechanisms are
|
||||
// important to help us connect to the network.
|
||||
//
|
||||
// We skip this for block-relay-only peers to avoid potentially leaking
|
||||
// information about our block-relay-only connections via address relay.
|
||||
// We skip this for block-relay-only peers. We want to avoid
|
||||
// potentially leaking addr information and we do not want to
|
||||
// indicate to the peer that we will participate in addr relay.
|
||||
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
|
||||
{
|
||||
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
|
||||
|
|
@ -2833,10 +2858,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
|
||||
s >> vAddr;
|
||||
|
||||
if (!RelayAddrsWithPeer(*peer)) {
|
||||
if (!SetupAddressRelay(pfrom, *peer)) {
|
||||
LogPrint(BCLog::NET, "ignoring %s message from %s peer=%d\n", msg_type, pfrom.ConnectionTypeAsString(), pfrom.GetId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (vAddr.size() > MAX_ADDR_TO_SEND)
|
||||
{
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
|
||||
|
|
@ -3782,6 +3808,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
return;
|
||||
}
|
||||
|
||||
SetupAddressRelay(pfrom, *peer);
|
||||
|
||||
// Only send one GetAddr response per connection to reduce resource waste
|
||||
// and discourage addr stamping of INV announcements.
|
||||
if (peer->m_getaddr_recvd) {
|
||||
|
|
@ -4369,7 +4397,7 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic
|
|||
void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
|
||||
{
|
||||
// Nothing to do for non-address-relay peers
|
||||
if (!RelayAddrsWithPeer(peer)) return;
|
||||
if (!peer.m_addr_relay_enabled) return;
|
||||
|
||||
LOCK(peer.m_addr_send_times_mutex);
|
||||
// Periodically advertise our local address to the peer.
|
||||
|
|
@ -4497,6 +4525,22 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
bool PeerManagerImpl::SetupAddressRelay(CNode& node, Peer& peer)
|
||||
{
|
||||
// We don't participate in addr relay with outbound block-relay-only
|
||||
// connections to prevent providing adversaries with the additional
|
||||
// information of addr traffic to infer the link.
|
||||
if (node.IsBlockOnlyConn()) return false;
|
||||
|
||||
if (!peer.m_addr_relay_enabled.exchange(true)) {
|
||||
// First addr message we have received from the peer, initialize
|
||||
// m_addr_known
|
||||
peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||
{
|
||||
PeerRef peer = GetPeerRef(pto->GetId());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue