Skip to content

Commit 52c6904

Browse files
committed
Merge bitcoin/bitcoin#28558: Make PeerManager own a FastRandomContext
4cafe9f [test] Make PeerManager's rng deterministic in tests (dergoegge) fecec3e [net processing] FeeFilterRounder doesn't own a FastRandomContext (dergoegge) 47520ed [net processing] Make fee filter rounder non-global (dergoegge) 77506f4 [net processing] Addr shuffle uses PeerManager's rng (dergoegge) a648dd7 [net processing] PushAddress uses PeerManager's rng (dergoegge) 87c7067 [net processing] PeerManager holds a FastRandomContext (dergoegge) Pull request description: This lets us avoid some non-determinism in tests (also see #28537). ACKs for top commit: MarcoFalke: re-ACK 4cafe9f 🕗 glozow: concept && light code review ACK 4cafe9f Tree-SHA512: 3c18700773d0bc547ccb6442c41567e6f26b0b50fab5b79620da417ec91b9c0ae1395d15258da3aa4a91447b8ce560145dd135e39fbbd0610749e528e665b111
2 parents 78fd3c2 + 4cafe9f commit 52c6904

File tree

7 files changed

+29
-20
lines changed

7 files changed

+29
-20
lines changed

src/net_processing.cpp

+16-14
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,10 @@ class PeerManagerImpl final : public PeerManager
696696
/** Send `feefilter` message. */
697697
void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
698698

699+
FastRandomContext m_rng GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
700+
701+
FeeFilterRounder m_fee_filter_rounder GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
702+
699703
const CChainParams& m_chainparams;
700704
CConnman& m_connman;
701705
AddrMan& m_addrman;
@@ -1053,7 +1057,7 @@ class PeerManagerImpl final : public PeerManager
10531057
bool SetupAddressRelay(const CNode& node, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
10541058

10551059
void AddAddressKnown(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1056-
void PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1060+
void PushAddress(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
10571061
};
10581062

10591063
const CNodeState* PeerManagerImpl::State(NodeId pnode) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -1085,15 +1089,15 @@ void PeerManagerImpl::AddAddressKnown(Peer& peer, const CAddress& addr)
10851089
peer.m_addr_known->insert(addr.GetKey());
10861090
}
10871091

1088-
void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand)
1092+
void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr)
10891093
{
10901094
// Known checking here is only to save space from duplicates.
10911095
// Before sending, we'll filter it again for known addresses that were
10921096
// added after addresses were pushed.
10931097
assert(peer.m_addr_known);
10941098
if (addr.IsValid() && !peer.m_addr_known->contains(addr.GetKey()) && IsAddrCompatible(peer, addr)) {
10951099
if (peer.m_addrs_to_send.size() >= MAX_ADDR_TO_SEND) {
1096-
peer.m_addrs_to_send[insecure_rand.randrange(peer.m_addrs_to_send.size())] = addr;
1100+
peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
10971101
} else {
10981102
peer.m_addrs_to_send.push_back(addr);
10991103
}
@@ -1877,7 +1881,9 @@ std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrm
18771881
PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
18781882
BanMan* banman, ChainstateManager& chainman,
18791883
CTxMemPool& pool, Options opts)
1880-
: m_chainparams(chainman.GetParams()),
1884+
: m_rng{opts.deterministic_rng},
1885+
m_fee_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}, m_rng},
1886+
m_chainparams(chainman.GetParams()),
18811887
m_connman(connman),
18821888
m_addrman(addrman),
18831889
m_banman(banman),
@@ -2183,7 +2189,6 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
21832189
const CSipHasher hasher{m_connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY)
21842190
.Write(hash_addr)
21852191
.Write(time_addr)};
2186-
FastRandomContext insecure_rand;
21872192

21882193
// Relay reachable addresses to 2 peers. Unreachable addresses are relayed randomly to 1 or 2 peers.
21892194
unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
@@ -2207,7 +2212,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
22072212
};
22082213

22092214
for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2210-
PushAddress(*best[i].second, addr, insecure_rand);
2215+
PushAddress(*best[i].second, addr);
22112216
}
22122217
}
22132218

@@ -3793,7 +3798,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
37933798
const bool rate_limited = !pfrom.HasPermission(NetPermissionFlags::Addr);
37943799
uint64_t num_proc = 0;
37953800
uint64_t num_rate_limit = 0;
3796-
Shuffle(vAddr.begin(), vAddr.end(), FastRandomContext());
3801+
Shuffle(vAddr.begin(), vAddr.end(), m_rng);
37973802
for (CAddress& addr : vAddr)
37983803
{
37993804
if (interruptMsgProc)
@@ -4735,9 +4740,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
47354740
} else {
47364741
vAddr = m_connman.GetAddresses(pfrom, MAX_ADDR_TO_SEND, MAX_PCT_ADDR_TO_SEND);
47374742
}
4738-
FastRandomContext insecure_rand;
47394743
for (const CAddress &addr : vAddr) {
4740-
PushAddress(*peer, addr, insecure_rand);
4744+
PushAddress(*peer, addr);
47414745
}
47424746
return;
47434747
}
@@ -5339,8 +5343,7 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
53395343
}
53405344
if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
53415345
CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5342-
FastRandomContext insecure_rand;
5343-
PushAddress(peer, local_addr, insecure_rand);
5346+
PushAddress(peer, local_addr);
53445347
}
53455348
peer.m_next_local_addr_send = GetExponentialRand(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
53465349
}
@@ -5419,22 +5422,21 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
54195422
if (pto.IsBlockOnlyConn()) return;
54205423

54215424
CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();
5422-
static FeeFilterRounder g_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}};
54235425

54245426
if (m_chainman.IsInitialBlockDownload()) {
54255427
// Received tx-inv messages are discarded when the active
54265428
// chainstate is in IBD, so tell the peer to not send them.
54275429
currentFilter = MAX_MONEY;
54285430
} else {
5429-
static const CAmount MAX_FILTER{g_filter_rounder.round(MAX_MONEY)};
5431+
static const CAmount MAX_FILTER{m_fee_filter_rounder.round(MAX_MONEY)};
54305432
if (peer.m_fee_filter_sent == MAX_FILTER) {
54315433
// Send the current filter if we sent MAX_FILTER previously
54325434
// and made it out of IBD.
54335435
peer.m_next_send_feefilter = 0us;
54345436
}
54355437
}
54365438
if (current_time > peer.m_next_send_feefilter) {
5437-
CAmount filterToSend = g_filter_rounder.round(currentFilter);
5439+
CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
54385440
// We always have a fee filter of at least the min relay fee
54395441
filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
54405442
if (filterToSend != peer.m_fee_filter_sent) {

src/net_processing.h

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
5858
uint32_t max_extra_txs{DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN};
5959
//! Whether all P2P messages are captured to disk
6060
bool capture_messages{false};
61+
//! Whether or not the internal RNG behaves deterministically (this is
62+
//! a test-only option).
63+
bool deterministic_rng{false};
6164
};
6265

6366
static std::unique_ptr<PeerManager> make(CConnman& connman, AddrMan& addrman,

src/policy/fees.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1054,8 +1054,9 @@ static std::set<double> MakeFeeSet(const CFeeRate& min_incremental_fee,
10541054
return fee_set;
10551055
}
10561056

1057-
FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
1058-
: m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)}
1057+
FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee, FastRandomContext& rng)
1058+
: m_fee_set{MakeFeeSet(minIncrementalFee, MAX_FILTER_FEERATE, FEE_FILTER_SPACING)},
1059+
insecure_rand{rng}
10591060
{
10601061
}
10611062

src/policy/fees.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,15 @@ class FeeFilterRounder
320320

321321
public:
322322
/** Create new FeeFilterRounder */
323-
explicit FeeFilterRounder(const CFeeRate& min_incremental_fee);
323+
explicit FeeFilterRounder(const CFeeRate& min_incremental_fee, FastRandomContext& rng);
324324

325325
/** Quantize a minimum fee for privacy purpose before broadcast. */
326326
CAmount round(CAmount currentMinFee) EXCLUSIVE_LOCKS_REQUIRED(!m_insecure_rand_mutex);
327327

328328
private:
329329
const std::set<double> m_fee_set;
330330
Mutex m_insecure_rand_mutex;
331-
FastRandomContext insecure_rand GUARDED_BY(m_insecure_rand_mutex);
331+
FastRandomContext& insecure_rand GUARDED_BY(m_insecure_rand_mutex);
332332
};
333333

334334
#endif // BITCOIN_POLICY_FEES_H

src/test/fuzz/fees.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ FUZZ_TARGET(fees)
1717
{
1818
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
1919
const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
20-
FeeFilterRounder fee_filter_rounder{minimal_incremental_fee};
20+
FastRandomContext rng{/*fDeterministic=*/true};
21+
FeeFilterRounder fee_filter_rounder{minimal_incremental_fee, rng};
2122
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
2223
const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider);
2324
const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee);

src/test/policy_fee_tests.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ BOOST_AUTO_TEST_SUITE(policy_fee_tests)
1313

1414
BOOST_AUTO_TEST_CASE(FeeRounder)
1515
{
16-
FeeFilterRounder fee_rounder{CFeeRate{1000}};
16+
FastRandomContext rng{/*fDeterministic=*/true};
17+
FeeFilterRounder fee_rounder{CFeeRate{1000}, rng};
1718

1819
// check that 1000 rounds to 974 or 1071
1920
std::set<CAmount> results;

src/test/util/setup_common.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ TestingSetup::TestingSetup(
256256
m_node.connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params()); // Deterministic randomness for tests.
257257
PeerManager::Options peerman_opts;
258258
ApplyArgsManOptions(*m_node.args, peerman_opts);
259+
peerman_opts.deterministic_rng = true;
259260
m_node.peerman = PeerManager::make(*m_node.connman, *m_node.addrman,
260261
m_node.banman.get(), *m_node.chainman,
261262
*m_node.mempool, peerman_opts);

0 commit comments

Comments
 (0)