Skip to content

Commit 481e08a

Browse files
MarcoFalkeknst
authored andcommitted
Merge bitcoin#18454: net: Make addr relay mockable, add test
NOTE: There is slight difference with original backport due to future changes in bitcoin#19272, bitcoin#19763 - otherwise functional test p2p_addr_relay.py fails 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 (fabe56e before bitcoin#18454 (comment)), fa5bf23 was dropped since last review. Tree-SHA512: 0552bf8fcbe375baa3cab62acd8c23b2994efa47daff818ad1116d0ffaa0b9e520dc1bca2bbc68369b25584e85e54861fe6fd0968de4f503b95439c099df9bd7 fixup - see bitcoin#19272, bitcoin#19763
1 parent 18eaddf commit 481e08a

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

src/net.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,8 +1134,8 @@ class CNode
11341134
std::vector<CAddress> vAddrToSend;
11351135
const std::unique_ptr<CRollingBloomFilter> m_addr_known;
11361136
bool fGetAddr{false};
1137-
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
1138-
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
1137+
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
1138+
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
11391139

11401140
// Don't relay addr messages to peers that we connect to as block-relay-only
11411141
// peers (to prevent adversaries from inferring these links from addr

src/net_processing.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ static const int MAX_UNCONNECTING_HEADERS = 10;
138138
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
139139

140140
/** Average delay between local address broadcasts in seconds. */
141-
static constexpr unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60;
141+
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24};
142142
/** Average delay between peer address broadcasts in seconds. */
143-
static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
143+
static constexpr std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30};
144144
/** Average delay between trickled inventory transmissions in seconds.
145145
* Blocks and peers with noban permission bypass this, regular outbound peers get half this delay,
146146
* Masternode outbound peers get quarter this delay. */
@@ -1889,13 +1889,13 @@ void RelayTransaction(const uint256& txid, const CConnman& connman)
18891889
});
18901890
}
18911891

1892-
static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connman)
1892+
static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
18931893
{
18941894
// Relay to a limited number of other nodes
18951895
// Use deterministic randomness to send to the same nodes for 24 hours
18961896
// at a time so the m_addr_knowns of the chosen nodes prevent repeats
18971897
uint64_t hashAddr = addr.GetHash();
1898-
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
1898+
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24 * 60 * 60));
18991899
FastRandomContext insecure_rand;
19001900

19011901
// Relay reachable addresses to 2 peers. Unreachable addresses are relayed randomly to 1 or 2 peers.
@@ -4678,16 +4678,16 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
46784678
int64_t nNow = GetTimeMicros();
46794679
auto current_time = GetTime<std::chrono::microseconds>();
46804680

4681-
if (pto->IsAddrRelayPeer() && !m_chainman.ActiveChainstate().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
4681+
if (pto->IsAddrRelayPeer() && !m_chainman.ActiveChainstate().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
46824682
AdvertiseLocal(pto);
4683-
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
4683+
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
46844684
}
46854685

46864686
//
46874687
// Message: addr
46884688
//
4689-
if (pto->IsAddrRelayPeer() && pto->nNextAddrSend < nNow) {
4690-
pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
4689+
if (pto->IsAddrRelayPeer() && pto->m_next_addr_send < current_time) {
4690+
pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
46914691
std::vector<CAddress> vAddr;
46924692
vAddr.reserve(pto->vAddrToSend.size());
46934693

test/functional/p2p_addr_relay.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
msg_addr,
13+
)
14+
from test_framework.mininode import (
15+
P2PInterface,
16+
)
17+
from test_framework.test_framework import BitcoinTestFramework
18+
from test_framework.util import (
19+
assert_equal,
20+
)
21+
import time
22+
23+
ADDRS = []
24+
for i in range(10):
25+
addr = CAddress()
26+
addr.time = int(time.time()) + i
27+
addr.nServices = NODE_NETWORK
28+
addr.ip = "123.123.123.{}".format(i % 256)
29+
addr.port = 8333 + i
30+
ADDRS.append(addr)
31+
32+
33+
class AddrReceiver(P2PInterface):
34+
def on_addr(self, message):
35+
for addr in message.addrs:
36+
assert_equal(addr.nServices, 9)
37+
assert addr.ip.startswith('123.123.123.')
38+
assert (8333 <= addr.port < 8343)
39+
40+
41+
class AddrTest(BitcoinTestFramework):
42+
def set_test_params(self):
43+
self.setup_clean_chain = False
44+
self.num_nodes = 1
45+
46+
def run_test(self):
47+
self.log.info('Create connection that sends addr messages')
48+
addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
49+
msg = msg_addr()
50+
51+
self.log.info('Send too large addr message')
52+
msg.addrs = ADDRS * 101
53+
with self.nodes[0].assert_debug_log(['addr message size = 1010']):
54+
addr_source.send_and_ping(msg)
55+
56+
self.log.info('Check that addr message content is relayed and added to addrman')
57+
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
58+
msg.addrs = ADDRS
59+
with self.nodes[0].assert_debug_log([
60+
'Added 10 addresses from 127.0.0.1: 0 tried',
61+
'received: addr (301 bytes) peer=0',
62+
]):
63+
addr_source.send_and_ping(msg)
64+
self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
65+
addr_receiver.sync_with_ping()
66+
67+
68+
if __name__ == '__main__':
69+
AddrTest().main()

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
'rpc_blockchain.py',
175175
'rpc_deprecated.py',
176176
'wallet_disable.py',
177+
'p2p_addr_relay.py',
177178
'p2p_getaddr_caching.py',
178179
'p2p_getdata.py',
179180
'rpc_net.py',

0 commit comments

Comments
 (0)