mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-19 20:25:18 +01:00
Merge #18454: net: Make addr relay mockable, add test
fa1da3d4bftest: Add basic addr relay test (MarcoFalke)fa1793c1c4net: Pass connman const when relaying address (MarcoFalke)fa47a0b003net: 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: utACKfa1da3dpromag: ACKfa1da3d4bf(fabe56e44b6f683e24e37246a7a8851190947cb3 before https://github.com/bitcoin/bitcoin/pull/18454#issuecomment-607866453), fa5bf23d527a450e72c2bf13d013e5393b664ca3 was dropped since last review. Tree-SHA512: 0552bf8fcbe375baa3cab62acd8c23b2994efa47daff818ad1116d0ffaa0b9e520dc1bca2bbc68369b25584e85e54861fe6fd0968de4f503b95439c099df9bd7
This commit is contained in:
@@ -797,8 +797,8 @@ public:
|
||||
std::vector<CAddress> vAddrToSend;
|
||||
const std::unique_ptr<CRollingBloomFilter> m_addr_known;
|
||||
bool fGetAddr{false};
|
||||
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
|
||||
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
|
||||
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
|
||||
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
|
||||
|
||||
bool IsAddrRelayPeer() const { return m_addr_known != nullptr; }
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ void EraseOrphansFor(NodeId peer);
|
||||
/** Increase a node's misbehavior score. */
|
||||
void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="") EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/** Average delay between local address broadcasts in seconds. */
|
||||
static constexpr unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60;
|
||||
/** Average delay between peer address broadcasts in seconds. */
|
||||
static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
|
||||
/** Average delay between local address broadcasts */
|
||||
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24};
|
||||
/** Average delay between peer address broadcasts */
|
||||
static constexpr std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30};
|
||||
/** Average delay between trickled inventory transmissions in seconds.
|
||||
* Blocks and whitelisted receivers bypass this, outbound peers get half this delay. */
|
||||
static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5;
|
||||
@@ -1365,7 +1365,7 @@ void RelayTransaction(const uint256& txid, const CConnman& connman)
|
||||
});
|
||||
}
|
||||
|
||||
static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
|
||||
static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
|
||||
{
|
||||
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
|
||||
|
||||
@@ -1373,7 +1373,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
|
||||
// Use deterministic randomness to send to the same nodes for 24 hours
|
||||
// at a time so the m_addr_knowns of the chosen nodes prevent repeats
|
||||
uint64_t hashAddr = addr.GetHash();
|
||||
const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
|
||||
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24 * 60 * 60));
|
||||
FastRandomContext insecure_rand;
|
||||
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
||||
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
||||
}
|
||||
|
||||
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
|
||||
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||
{
|
||||
// Relay to a limited number of other nodes
|
||||
RelayAddress(addr, fReachable, connman);
|
||||
RelayAddress(addr, fReachable, *connman);
|
||||
}
|
||||
// Do not store addresses outside our network
|
||||
if (fReachable)
|
||||
@@ -3583,16 +3583,16 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||
int64_t nNow = GetTimeMicros();
|
||||
auto current_time = GetTime<std::chrono::microseconds>();
|
||||
|
||||
if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
|
||||
if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
|
||||
AdvertiseLocal(pto);
|
||||
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
||||
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
||||
}
|
||||
|
||||
//
|
||||
// Message: addr
|
||||
//
|
||||
if (pto->IsAddrRelayPeer() && pto->nNextAddrSend < nNow) {
|
||||
pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
|
||||
if (pto->IsAddrRelayPeer() && 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);
|
||||
|
||||
71
test/functional/p2p_addr_relay.py
Executable file
71
test/functional/p2p_addr_relay.py
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2020 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""
|
||||
Test addr relay
|
||||
"""
|
||||
|
||||
from test_framework.messages import (
|
||||
CAddress,
|
||||
NODE_NETWORK,
|
||||
NODE_WITNESS,
|
||||
msg_addr,
|
||||
)
|
||||
from test_framework.mininode import (
|
||||
P2PInterface,
|
||||
)
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
)
|
||||
import time
|
||||
|
||||
ADDRS = []
|
||||
for i in range(10):
|
||||
addr = CAddress()
|
||||
addr.time = int(time.time()) + i
|
||||
addr.nServices = NODE_NETWORK | NODE_WITNESS
|
||||
addr.ip = "123.123.123.{}".format(i % 256)
|
||||
addr.port = 8333 + i
|
||||
ADDRS.append(addr)
|
||||
|
||||
|
||||
class AddrReceiver(P2PInterface):
|
||||
def on_addr(self, message):
|
||||
for addr in message.addrs:
|
||||
assert_equal(addr.nServices, 9)
|
||||
assert addr.ip.startswith('123.123.123.')
|
||||
assert (8333 <= addr.port < 8343)
|
||||
|
||||
|
||||
class AddrTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = False
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
self.log.info('Create connection that sends addr messages')
|
||||
addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
|
||||
msg = msg_addr()
|
||||
|
||||
self.log.info('Send too large addr message')
|
||||
msg.addrs = ADDRS * 101
|
||||
with self.nodes[0].assert_debug_log(['message addr size() = 1010']):
|
||||
addr_source.send_and_ping(msg)
|
||||
|
||||
self.log.info('Check that addr message content is relayed and added to addrman')
|
||||
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
|
||||
msg.addrs = ADDRS
|
||||
with self.nodes[0].assert_debug_log([
|
||||
'Added 10 addresses from 127.0.0.1: 0 tried',
|
||||
'received: addr (301 bytes) peer=0',
|
||||
'sending addr (301 bytes) peer=1',
|
||||
]):
|
||||
addr_source.send_and_ping(msg)
|
||||
self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
|
||||
addr_receiver.sync_with_ping()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
AddrTest().main()
|
||||
@@ -144,6 +144,7 @@ BASE_SCRIPTS = [
|
||||
'rpc_blockchain.py',
|
||||
'rpc_deprecated.py',
|
||||
'wallet_disable.py',
|
||||
'p2p_addr_relay.py',
|
||||
'rpc_net.py',
|
||||
'wallet_keypool.py',
|
||||
'p2p_mempool.py',
|
||||
|
||||
Reference in New Issue
Block a user