Skip to content

Commit 29893ec

Browse files
author
MarcoFalke
committed
Merge #18454: net: Make addr relay mockable, add test
fa1da3d test: Add basic addr relay test (MarcoFalke) fa1793c net: Pass connman const when relaying address (MarcoFalke) fa47a0b net: Make addr relay mockable (MarcoFalke) Pull request description: As usual: * Switch to std::chrono time to be type-safe and mockable * Add basic test that relies on mocktime to add code coverage ACKs for top commit: naumenkogs: utACK fa1da3d promag: ACK fa1da3d (fabe56e44b6f683e24e37246a7a8851190947cb3 before bitcoin/bitcoin#18454 (comment)), fa5bf23d527a450e72c2bf13d013e5393b664ca3 was dropped since last review. Tree-SHA512: 0552bf8fcbe375baa3cab62acd8c23b2994efa47daff818ad1116d0ffaa0b9e520dc1bca2bbc68369b25584e85e54861fe6fd0968de4f503b95439c099df9bd7
2 parents 2b9a4a1 + fa1da3d commit 29893ec

File tree

4 files changed

+86
-14
lines changed

4 files changed

+86
-14
lines changed

src/net.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,8 +797,8 @@ class CNode
797797
std::vector<CAddress> vAddrToSend;
798798
const std::unique_ptr<CRollingBloomFilter> m_addr_known;
799799
bool fGetAddr{false};
800-
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
801-
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
800+
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
801+
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
802802

803803
bool IsAddrRelayPeer() const { return m_addr_known != nullptr; }
804804

src/net_processing.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ void EraseOrphansFor(NodeId peer);
9797
/** Increase a node's misbehavior score. */
9898
void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="") EXCLUSIVE_LOCKS_REQUIRED(cs_main);
9999

100-
/** Average delay between local address broadcasts in seconds. */
101-
static constexpr unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60;
102-
/** Average delay between peer address broadcasts in seconds. */
103-
static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
100+
/** Average delay between local address broadcasts */
101+
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24};
102+
/** Average delay between peer address broadcasts */
103+
static constexpr std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30};
104104
/** Average delay between trickled inventory transmissions in seconds.
105105
* Blocks and whitelisted receivers bypass this, outbound peers get half this delay. */
106106
static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5;
@@ -1365,15 +1365,15 @@ void RelayTransaction(const uint256& txid, const CConnman& connman)
13651365
});
13661366
}
13671367

1368-
static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
1368+
static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
13691369
{
13701370
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
13711371

13721372
// Relay to a limited number of other nodes
13731373
// Use deterministic randomness to send to the same nodes for 24 hours
13741374
// at a time so the m_addr_knowns of the chosen nodes prevent repeats
13751375
uint64_t hashAddr = addr.GetHash();
1376-
const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
1376+
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24 * 60 * 60));
13771377
FastRandomContext insecure_rand;
13781378

13791379
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
@@ -1398,7 +1398,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
13981398
}
13991399
};
14001400

1401-
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
1401+
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
14021402
}
14031403

14041404
void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman)
@@ -2192,7 +2192,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
21922192
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
21932193
{
21942194
// Relay to a limited number of other nodes
2195-
RelayAddress(addr, fReachable, connman);
2195+
RelayAddress(addr, fReachable, *connman);
21962196
}
21972197
// Do not store addresses outside our network
21982198
if (fReachable)
@@ -3583,16 +3583,16 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
35833583
int64_t nNow = GetTimeMicros();
35843584
auto current_time = GetTime<std::chrono::microseconds>();
35853585

3586-
if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
3586+
if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
35873587
AdvertiseLocal(pto);
3588-
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
3588+
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
35893589
}
35903590

35913591
//
35923592
// Message: addr
35933593
//
3594-
if (pto->IsAddrRelayPeer() && pto->nNextAddrSend < nNow) {
3595-
pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
3594+
if (pto->IsAddrRelayPeer() && pto->m_next_addr_send < current_time) {
3595+
pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
35963596
std::vector<CAddress> vAddr;
35973597
vAddr.reserve(pto->vAddrToSend.size());
35983598
assert(pto->m_addr_known);

test/functional/p2p_addr_relay.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2020 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""
6+
Test addr relay
7+
"""
8+
9+
from test_framework.messages import (
10+
CAddress,
11+
NODE_NETWORK,
12+
NODE_WITNESS,
13+
msg_addr,
14+
)
15+
from test_framework.mininode import (
16+
P2PInterface,
17+
)
18+
from test_framework.test_framework import BitcoinTestFramework
19+
from test_framework.util import (
20+
assert_equal,
21+
)
22+
import time
23+
24+
ADDRS = []
25+
for i in range(10):
26+
addr = CAddress()
27+
addr.time = int(time.time()) + i
28+
addr.nServices = NODE_NETWORK | NODE_WITNESS
29+
addr.ip = "123.123.123.{}".format(i % 256)
30+
addr.port = 8333 + i
31+
ADDRS.append(addr)
32+
33+
34+
class AddrReceiver(P2PInterface):
35+
def on_addr(self, message):
36+
for addr in message.addrs:
37+
assert_equal(addr.nServices, 9)
38+
assert addr.ip.startswith('123.123.123.')
39+
assert (8333 <= addr.port < 8343)
40+
41+
42+
class AddrTest(BitcoinTestFramework):
43+
def set_test_params(self):
44+
self.setup_clean_chain = False
45+
self.num_nodes = 1
46+
47+
def run_test(self):
48+
self.log.info('Create connection that sends addr messages')
49+
addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
50+
msg = msg_addr()
51+
52+
self.log.info('Send too large addr message')
53+
msg.addrs = ADDRS * 101
54+
with self.nodes[0].assert_debug_log(['message addr size() = 1010']):
55+
addr_source.send_and_ping(msg)
56+
57+
self.log.info('Check that addr message content is relayed and added to addrman')
58+
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
59+
msg.addrs = ADDRS
60+
with self.nodes[0].assert_debug_log([
61+
'Added 10 addresses from 127.0.0.1: 0 tried',
62+
'received: addr (301 bytes) peer=0',
63+
'sending addr (301 bytes) peer=1',
64+
]):
65+
addr_source.send_and_ping(msg)
66+
self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
67+
addr_receiver.sync_with_ping()
68+
69+
70+
if __name__ == '__main__':
71+
AddrTest().main()

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
'rpc_blockchain.py',
145145
'rpc_deprecated.py',
146146
'wallet_disable.py',
147+
'p2p_addr_relay.py',
147148
'rpc_net.py',
148149
'wallet_keypool.py',
149150
'p2p_mempool.py',

0 commit comments

Comments
 (0)