Skip to content

Commit 5783743

Browse files
Merge pull request dashpay#5677 from vijaydasmp/bp23_3
backport: Merge bitcoin#22530,(partial)21562,22322,22517
2 parents cefa2eb + 1231278 commit 5783743

File tree

6 files changed

+85
-53
lines changed

6 files changed

+85
-53
lines changed

src/logging.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <util/threadnames.h>
99
#include <util/time.h>
1010

11+
#include <algorithm>
12+
#include <array>
13+
1114
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
1215

1316
BCLog::Logger& LogInstance()
@@ -130,8 +133,7 @@ bool BCLog::Logger::DefaultShrinkDebugFile() const
130133
return m_categories == BCLog::NONE;
131134
}
132135

133-
struct CLogCategoryDesc
134-
{
136+
struct CLogCategoryDesc {
135137
BCLog::LogFlags flag;
136138
std::string category;
137139
};
@@ -201,16 +203,19 @@ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
201203

202204
std::vector<LogCategory> BCLog::Logger::LogCategoriesList(bool enabled_only) const
203205
{
206+
// Sort log categories by alphabetical order.
207+
std::array<CLogCategoryDesc, std::size(LogCategories)> categories;
208+
std::copy(std::begin(LogCategories), std::end(LogCategories), categories.begin());
209+
std::sort(categories.begin(), categories.end(), [](auto a, auto b) { return a.category < b.category; });
210+
204211
std::vector<LogCategory> ret;
205-
for (const CLogCategoryDesc& category_desc : LogCategories) {
206-
// Omit the special cases.
207-
if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL && category_desc.flag != BCLog::DASH) {
208-
LogCategory catActive;
209-
catActive.category = category_desc.category;
210-
catActive.active = WillLogCategory(category_desc.flag);
211-
if (!enabled_only || catActive.active) {
212-
ret.push_back(catActive);
213-
}
212+
for (const CLogCategoryDesc& category_desc : categories) {
213+
if (category_desc.flag == BCLog::NONE || category_desc.flag == BCLog::ALL || category_desc.flag == BCLog::DASH) continue;
214+
LogCategory catActive;
215+
catActive.category = category_desc.category;
216+
catActive.active = WillLogCategory(category_desc.flag);
217+
if (!enabled_only || catActive.active) {
218+
ret.push_back(catActive);
214219
}
215220
}
216221
return ret;
@@ -261,7 +266,7 @@ namespace BCLog {
261266
}
262267
return ret;
263268
}
264-
}
269+
} // namespace BCLog
265270

266271
void BCLog::Logger::LogPrintStr(const std::string& str)
267272
{

src/logging.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ namespace BCLog {
160160
bool DisableCategory(const std::string& str);
161161

162162
bool WillLogCategory(LogFlags category) const;
163-
/** Returns a vector of the log categories */
163+
/** Returns a vector of the log categories in alphabetical order. */
164164
std::vector<LogCategory> LogCategoriesList(bool enabled_only = false) const;
165-
/** Returns a string with the log categories */
165+
/** Returns a string with the log categories in alphabetical order. */
166166
std::string LogCategoriesString(bool enabled_only = false) const
167167
{
168168
return Join(LogCategoriesList(enabled_only), ", ", [&](const LogCategory& i) { return i.category; });

src/net_processing.cpp

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class PeerManagerImpl final : public PeerManager
318318
/** The height of the best chain */
319319
std::atomic<int> m_best_height{-1};
320320

321-
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
321+
/** Next time to check for stale tip */
322+
int64_t m_stale_tip_check_time{0};
322323

323324
/** Whether this node is running in blocks only mode */
324325
const bool m_ignore_incoming_txs;
@@ -443,16 +444,26 @@ class PeerManagerImpl final : public PeerManager
443444
*
444445
* Memory used: 1.3MB
445446
*/
446-
std::unique_ptr<CRollingBloomFilter> recentRejects GUARDED_BY(cs_main);
447+
CRollingBloomFilter m_recent_rejects GUARDED_BY(::cs_main){120'000, 0.000'001};
447448
uint256 hashRecentRejectsChainTip GUARDED_BY(cs_main);
448449

449450
/*
450451
* Filter for transactions that have been recently confirmed.
451452
* We use this to avoid requesting transactions that have already been
452453
* confirnmed.
454+
*
455+
* Blocks don't typically have more than 4000 transactions, so this should
456+
* be at least six blocks (~1 hr) worth of transactions that we can store,
457+
* inserting both a txid and wtxid for every observed transaction.
458+
* If the number of transactions appearing in a block goes up, or if we are
459+
* seeing getdata requests more than an hour after initial announcement, we
460+
* can increase this number.
461+
* The false positive rate of 1/1M should come out to less than 1
462+
* transaction per day that would be inadvertently ignored (which is the
463+
* same probability that we have in the reject filter).
453464
*/
454465
Mutex m_recent_confirmed_transactions_mutex;
455-
std::unique_ptr<CRollingBloomFilter> m_recent_confirmed_transactions GUARDED_BY(m_recent_confirmed_transactions_mutex);
466+
CRollingBloomFilter m_recent_confirmed_transactions GUARDED_BY(m_recent_confirmed_transactions_mutex){48'000, 0.000'001};
456467

457468
/* Returns a bool indicating whether we requested this block.
458469
* Also used if a block was /not/ received and timed out or started with another peer
@@ -1567,23 +1578,9 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
15671578
m_cj_ctx(cj_ctx),
15681579
m_llmq_ctx(llmq_ctx),
15691580
m_govman(govman),
1570-
m_stale_tip_check_time(0),
15711581
m_ignore_incoming_txs(ignore_incoming_txs)
15721582
{
15731583
assert(std::addressof(g_chainman) == std::addressof(m_chainman));
1574-
// Initialize global variables that cannot be constructed at startup.
1575-
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
1576-
1577-
// Blocks don't typically have more than 4000 transactions, so this should
1578-
// be at least six blocks (~1 hr) worth of transactions that we can store.
1579-
// If the number of transactions appearing in a block goes up, or if we are
1580-
// seeing getdata requests more than an hour after initial announcement, we
1581-
// can increase this number.
1582-
// The false positive rate of 1/1M should come out to less than 1
1583-
// transaction per day that would be inadvertently ignored (which is the
1584-
// same probability that we have in the reject filter).
1585-
m_recent_confirmed_transactions.reset(new CRollingBloomFilter(24000, 0.000001));
1586-
15871584
const Consensus::Params& consensusParams = Params().GetConsensus();
15881585
// Stale tip checking and peer eviction are on two different timers, but we
15891586
// don't want them to get out of sync due to drift in the scheduler, so we
@@ -1652,7 +1649,7 @@ void PeerManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock
16521649
{
16531650
LOCK(m_recent_confirmed_transactions_mutex);
16541651
for (const auto& ptx : pblock->vtx) {
1655-
m_recent_confirmed_transactions->insert(ptx->GetHash());
1652+
m_recent_confirmed_transactions.insert(ptx->GetHash());
16561653
}
16571654
}
16581655
}
@@ -1668,7 +1665,7 @@ void PeerManagerImpl::BlockDisconnected(const std::shared_ptr<const CBlock> &blo
16681665
// presumably the most common case of relaying a confirmed transaction
16691666
// should be just after a new block containing it is found.
16701667
LOCK(m_recent_confirmed_transactions_mutex);
1671-
m_recent_confirmed_transactions->reset();
1668+
m_recent_confirmed_transactions.reset();
16721669
}
16731670

16741671
// All of the following cache a recent block, and are protected by cs_most_recent_block
@@ -1805,15 +1802,14 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv)
18051802
case MSG_TX:
18061803
case MSG_DSTX:
18071804
{
1808-
assert(recentRejects);
18091805
if (m_chainman.ActiveChain().Tip()->GetBlockHash() != hashRecentRejectsChainTip)
18101806
{
18111807
// If the chain tip has changed previously rejected transactions
18121808
// might be now valid, e.g. due to a nLockTime'd tx becoming valid,
18131809
// or a double-spend. Reset the rejects filter and give those
18141810
// txs a second chance.
18151811
hashRecentRejectsChainTip = m_chainman.ActiveChain().Tip()->GetBlockHash();
1816-
recentRejects->reset();
1812+
m_recent_rejects.reset();
18171813
}
18181814

18191815
{
@@ -1823,15 +1819,15 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv)
18231819

18241820
{
18251821
LOCK(m_recent_confirmed_transactions_mutex);
1826-
if (m_recent_confirmed_transactions->contains(inv.hash)) return true;
1822+
if (m_recent_confirmed_transactions.contains(inv.hash)) return true;
18271823
}
18281824

18291825
// When we receive an islock for a previously rejected transaction, we have to
18301826
// drop the first-seen tx (which such a locked transaction was conflicting with)
18311827
// and re-request the locked transaction (which did not make it into the mempool
18321828
// previously due to txn-mempool-conflict rule). This means that we must ignore
1833-
// recentRejects filter for such locked txes here.
1834-
// We also ignore recentRejects filter for DSTX-es because a malicious peer might
1829+
// m_recent_rejects filter for such locked txes here.
1830+
// We also ignore m_recent_rejects filter for DSTX-es because a malicious peer might
18351831
// relay a valid DSTX as a regular TX first which would skip all the specific checks
18361832
// but would cause such tx to be rejected by ATMP due to 0 fee. Ignoring it here
18371833
// should let DSTX to be propagated by honest peer later. Note, that a malicious
@@ -1842,7 +1838,7 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv)
18421838
m_llmq_ctx->isman->IsWaitingForTx(inv.hash) ||
18431839
m_llmq_ctx->isman->IsLocked(inv.hash);
18441840

1845-
return (!fIgnoreRecentRejects && recentRejects->contains(inv.hash)) ||
1841+
return (!fIgnoreRecentRejects && m_recent_rejects.contains(inv.hash)) ||
18461842
(inv.type == MSG_DSTX && static_cast<bool>(CCoinJoin::GetDSTX(inv.hash))) ||
18471843
m_mempool.exists(inv.hash) ||
18481844
(g_txindex != nullptr && g_txindex->HasTx(inv.hash));
@@ -2553,8 +2549,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
25532549
// Has inputs but not accepted to mempool
25542550
// Probably non-standard or insufficient fee
25552551
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
2556-
assert(recentRejects);
2557-
recentRejects->insert(orphanHash);
2552+
m_recent_rejects.insert(orphanHash);
25582553
EraseOrphanTx(orphanHash);
25592554
done = true;
25602555
}
@@ -3608,7 +3603,7 @@ void PeerManagerImpl::ProcessMessage(
36083603
{
36093604
bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
36103605
for (const CTxIn& txin : tx.vin) {
3611-
if (recentRejects->contains(txin.prevout.hash)) {
3606+
if (m_recent_rejects.contains(txin.prevout.hash)) {
36123607
fRejectedParents = true;
36133608
break;
36143609
}
@@ -3637,12 +3632,11 @@ void PeerManagerImpl::ProcessMessage(
36373632
LogPrint(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
36383633
// We will continue to reject this tx since it has rejected
36393634
// parents so avoid re-requesting it from other peers.
3640-
recentRejects->insert(tx.GetHash());
3635+
m_recent_rejects.insert(tx.GetHash());
36413636
m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx);
36423637
}
36433638
} else {
3644-
assert(recentRejects);
3645-
recentRejects->insert(tx.GetHash());
3639+
m_recent_rejects.insert(tx.GetHash());
36463640
if (RecursiveDynamicUsage(*ptx) < 100000) {
36473641
AddToCompactExtraTransactions(ptx);
36483642
}
@@ -3661,21 +3655,21 @@ void PeerManagerImpl::ProcessMessage(
36613655
}
36623656
}
36633657

3664-
// If a tx has been detected by recentRejects, we will have reached
3658+
// If a tx has been detected by m_recent_rejects, we will have reached
36653659
// this point and the tx will have been ignored. Because we haven't run
36663660
// the tx through AcceptToMemoryPool, we won't have computed a DoS
36673661
// score for it or determined exactly why we consider it invalid.
36683662
//
36693663
// This means we won't penalize any peer subsequently relaying a DoSy
36703664
// tx (even if we penalized the first peer who gave it to us) because
3671-
// we have to account for recentRejects showing false positives. In
3665+
// we have to account for m_recent_rejects showing false positives. In
36723666
// other words, we shouldn't penalize a peer if we aren't *sure* they
36733667
// submitted a DoSy tx.
36743668
//
3675-
// Note that recentRejects doesn't just record DoSy or invalid
3669+
// Note that m_recent_rejects doesn't just record DoSy or invalid
36763670
// transactions, but any tx not accepted by the m_mempool, which may be
36773671
// due to node policy (vs. consensus). So we can't blanket penalize a
3678-
// peer simply for relaying a tx that our recentRejects has caught,
3672+
// peer simply for relaying a tx that our m_recent_rejects has caught,
36793673
// regardless of false positives.
36803674

36813675
if (state.IsInvalid())

src/test/fuzz/banman.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ void initialize_banman()
3131
static const auto testing_setup = MakeNoLogFileContext<>();
3232
}
3333

34+
static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs)
35+
{
36+
return lhs.nVersion == rhs.nVersion &&
37+
lhs.nCreateTime == rhs.nCreateTime &&
38+
lhs.nBanUntil == rhs.nBanUntil;
39+
}
40+
3441
FUZZ_TARGET_INIT(banman, initialize_banman)
3542
{
3643
// The complexity is O(N^2), where N is the input size, because each call
@@ -42,18 +49,19 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
4249
fs::path banlist_file = GetDataDir() / "fuzzed_banlist";
4350

4451
const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
52+
bool force_read_and_write_to_err{false};
4553
if (start_with_corrupted_banlist) {
4654
assert(WriteBinaryFile(banlist_file.string() + ".json",
4755
fuzzed_data_provider.ConsumeRandomLengthString()));
4856
} else {
49-
const bool force_read_and_write_to_err{fuzzed_data_provider.ConsumeBool()};
57+
force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
5058
if (force_read_and_write_to_err) {
5159
banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist";
5260
}
5361
}
5462

5563
{
56-
BanMan ban_man{banlist_file, nullptr, ConsumeBanTimeOffset(fuzzed_data_provider)};
64+
BanMan ban_man{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ ConsumeBanTimeOffset(fuzzed_data_provider)};
5765
while (--limit_max_ops >= 0 && fuzzed_data_provider.ConsumeBool()) {
5866
CallOneOf(
5967
fuzzed_data_provider,
@@ -91,6 +99,17 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
9199
ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
92100
});
93101
}
102+
if (!force_read_and_write_to_err) {
103+
ban_man.DumpBanlist();
104+
SetMockTime(ConsumeTime(fuzzed_data_provider));
105+
banmap_t banmap;
106+
ban_man.GetBanned(banmap);
107+
BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0};
108+
banmap_t banmap_read;
109+
ban_man_read.GetBanned(banmap_read);
110+
// Temporarily disabled to allow the remainder of the fuzz test to run while a fix is being worked on:
111+
// assert(banmap == banmap_read);
112+
}
94113
}
95114
fs::remove(banlist_file.string() + ".json");
96115
}

test/functional/mempool_reorg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def run_test(self):
8181
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
8282
last_block = self.nodes[0].generate(1)
8383
# Sync blocks, so that peer 1 gets the block before timelock_tx
84-
# Otherwise, peer 1 would put the timelock_tx in recentRejects
84+
# Otherwise, peer 1 would put the timelock_tx in m_recent_rejects
8585
self.sync_all()
8686

8787
# Time-locked transaction can now be spent

test/functional/rpc_misc.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,27 @@ def run_test(self):
5555

5656
assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar")
5757

58-
self.log.info("test logging")
58+
self.log.info("test logging rpc and help")
59+
60+
# Test logging RPC returns the expected number of logging categories.
61+
assert_equal(len(node.logging()), 36)
62+
63+
# Test toggling a logging category on/off/on with the logging RPC.
5964
assert_equal(node.logging()['qt'], True)
6065
node.logging(exclude=['qt'])
6166
assert_equal(node.logging()['qt'], False)
6267
node.logging(include=['qt'])
6368
assert_equal(node.logging()['qt'], True)
6469

70+
# Test logging RPC returns the logging categories in alphabetical order.
71+
sorted_logging_categories = sorted(node.logging())
72+
assert_equal(list(node.logging()), sorted_logging_categories)
73+
74+
# Test logging help returns the logging categories string in alphabetical order.
75+
categories = ', '.join(sorted_logging_categories)
76+
logging_help = self.nodes[0].help('logging')
77+
assert f"valid logging categories are: {categories}" in logging_help
78+
6579
self.log.info("test getindexinfo")
6680
self.restart_node(0, ["-txindex=0"])
6781
# Without any indices running the RPC returns an empty object

0 commit comments

Comments
 (0)