Skip to content

Commit 11a36d5

Browse files
b84939e Merge bitcoin#29495: fuzz: add target for local address stuff (fanquake) 39baa23 Merge bitcoin#29467: test: Fix intermittent issue in interface_rest.py (fanquake) 0fac60f Merge bitcoin#29230: doc: update -loglevel help to add `info` to the always logged levels (fanquake) 7a3df4e Merge bitcoin#29064: fuzz: Improve fuzzing stability for minisketch harness (fanquake) 59bb099 Merge bitcoin#27852: test: add coverage to rpc_blockchain.py (Andrew Chow) 40f0888 Merge bitcoin#28544: wallet: Add TxStateString function for debugging and logging (Andrew Chow) 404230c Merge bitcoin#28396: test: p2p: check that `getaddr` msgs are only responded once per connection (fanquake) 0029e6f Merge bitcoin#28350: Log explicit error message when coindb is found in inconsistent state (Andrew Chow) 5ee733e Merge bitcoin#28147: suppressions: note that `type:ClassName::MethodName` should be used (fanquake) be7f51a Merge bitcoin#27717: test: Make `util/test_runner.py` honor `BITCOINUTIL` and `BITCOINTX` (fanquake) Pull request description: ## What was done? Trivial backports from Bitcoin Core v26, v27 ## How Has This Been Tested? Run unit & functional tests ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: kwvg: utACK b84939e UdjinM6: utACK b84939e Tree-SHA512: 5f26d0dc186dee88ec203b7e1cad03265b4c6c6eeddaecab82991a4aab61d4c27352c2139a6a43155b76728fbd5c97a7161ca360d4a1129d24797b073b577a2f
2 parents 3195187 + b84939e commit 11a36d5

File tree

11 files changed

+104
-13
lines changed

11 files changed

+104
-13
lines changed

src/init/common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void AddLoggingArgs(ArgsManager& argsman)
6565
ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
6666
argsman.AddArg("-debugexclude=<category>", "Exclude debug and trace logging for a category. Can be used in conjunction with -debug=1 to output debug and trace logging for all categories except the specified category. This option can be specified multiple times to exclude multiple categories.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
6767
argsman.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
68-
argsman.AddArg("-loglevel=<level>|<category>:<level>", strprintf("Set the global or per-category severity level for logging categories enabled with the -debug configuration option or the logging RPC: %s (default=%s); warning and error levels are always logged. If <category>:<level> is supplied, the setting will override the global one and may be specified multiple times to set multiple category-specific levels. <category> can be: %s.", LogInstance().LogLevelsString(), LogInstance().LogLevelToStr(BCLog::DEFAULT_LOG_LEVEL), LogInstance().LogCategoriesString()), ArgsManager::DISALLOW_NEGATION | ArgsManager::DISALLOW_ELISION | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
68+
argsman.AddArg("-loglevel=<level>|<category>:<level>", strprintf("Set the global or per-category severity level for logging categories enabled with the -debug configuration option or the logging RPC. Possible values are %s (default=%s). The following levels are always logged: error, warning, info. If <category>:<level> is supplied, the setting will override the global one and may be specified multiple times to set multiple category-specific levels. <category> can be: %s.", LogInstance().LogLevelsString(), LogInstance().LogLevelToStr(BCLog::DEFAULT_LOG_LEVEL), LogInstance().LogCategoriesString()), ArgsManager::DISALLOW_NEGATION | ArgsManager::DISALLOW_ELISION | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
6969
argsman.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
7070
argsman.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
7171
argsman.AddArg("-logsourcelocations", strprintf("Prepend debug output with name of the originating source location (source file, line number and function name) (default: %u)", DEFAULT_LOGSOURCELOCATIONS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);

src/test/fuzz/minisketch.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,27 @@
1212
#include <map>
1313
#include <numeric>
1414

15-
using node::MakeMinisketch32;
15+
namespace {
16+
17+
Minisketch MakeFuzzMinisketch32(size_t capacity, uint32_t impl)
18+
{
19+
return Assert(Minisketch(32, impl, capacity));
20+
}
21+
22+
} // namespace
1623

1724
FUZZ_TARGET(minisketch)
1825
{
1926
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
27+
2028
const auto capacity{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 200)};
21-
Minisketch sketch_a{Assert(MakeMinisketch32(capacity))};
22-
Minisketch sketch_b{Assert(MakeMinisketch32(capacity))};
29+
const uint32_t impl{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, Minisketch::MaxImplementation())};
30+
if (!Minisketch::ImplementationSupported(32, impl)) return;
31+
32+
Minisketch sketch_a{MakeFuzzMinisketch32(capacity, impl)};
33+
Minisketch sketch_b{MakeFuzzMinisketch32(capacity, impl)};
34+
sketch_a.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
35+
sketch_b.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
2336

2437
// Fill two sets and keep the difference in a map
2538
std::map<uint32_t, bool> diff;
@@ -47,8 +60,11 @@ FUZZ_TARGET(minisketch)
4760
}
4861
const auto num_diff{std::accumulate(diff.begin(), diff.end(), size_t{0}, [](auto n, const auto& e) { return n + e.second; })};
4962

50-
Minisketch sketch_ar{MakeMinisketch32(capacity)};
51-
Minisketch sketch_br{MakeMinisketch32(capacity)};
63+
Minisketch sketch_ar{MakeFuzzMinisketch32(capacity, impl)};
64+
Minisketch sketch_br{MakeFuzzMinisketch32(capacity, impl)};
65+
sketch_ar.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
66+
sketch_br.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
67+
5268
sketch_ar.Deserialize(sketch_a.Serialize());
5369
sketch_br.Deserialize(sketch_b.Serialize());
5470

src/test/fuzz/net.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,40 @@ FUZZ_TARGET(net, .init = initialize_net)
9494
(void)node.HasPermission(net_permission_flags);
9595
(void)node.ConnectedThroughNetwork();
9696
}
97+
98+
FUZZ_TARGET(local_address, .init = initialize_net)
99+
{
100+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
101+
CService service{ConsumeService(fuzzed_data_provider)};
102+
CNode node{ConsumeNode(fuzzed_data_provider)};
103+
{
104+
LOCK(g_maplocalhost_mutex);
105+
mapLocalHost.clear();
106+
}
107+
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
108+
CallOneOf(
109+
fuzzed_data_provider,
110+
[&] {
111+
service = ConsumeService(fuzzed_data_provider);
112+
},
113+
[&] {
114+
const bool added{AddLocal(service, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, LOCAL_MAX - 1))};
115+
if (!added) return;
116+
assert(service.IsRoutable());
117+
assert(IsLocal(service));
118+
assert(SeenLocal(service));
119+
},
120+
[&] {
121+
(void)RemoveLocal(service);
122+
},
123+
[&] {
124+
(void)SeenLocal(service);
125+
},
126+
[&] {
127+
(void)IsLocal(service);
128+
},
129+
[&] {
130+
(void)GetLocalAddress(node);
131+
});
132+
}
133+
}

src/txdb.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo
114114
// We may be in the middle of replaying.
115115
std::vector<uint256> old_heads = GetHeadBlocks();
116116
if (old_heads.size() == 2) {
117+
if (old_heads[0] != hashBlock) {
118+
LogPrintLevel(BCLog::COINDB, BCLog::Level::Error, "The coins database detected an inconsistent state, likely due to a previous crash or shutdown. You will need to restart bitcoind with the -reindex-chainstate or -reindex configuration option.\n");
119+
}
117120
assert(old_heads[0] == hashBlock);
118121
old_tip = old_heads[1];
119122
}

src/wallet/transaction.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ struct TxStateConfirmed {
2828
int position_in_block;
2929

3030
explicit TxStateConfirmed(const uint256& block_hash, int height, int index) : confirmed_block_hash(block_hash), confirmed_block_height(height), position_in_block(index) {}
31+
std::string toString() const { return strprintf("Confirmed (block=%s, height=%i, index=%i)", confirmed_block_hash.ToString(), confirmed_block_height, position_in_block); }
3132
};
3233

3334
//! State of transaction added to mempool.
3435
struct TxStateInMempool {
36+
std::string toString() const { return strprintf("InMempool"); }
3537
};
3638

3739
//! State of rejected transaction that conflicts with a confirmed block.
@@ -40,6 +42,7 @@ struct TxStateConflicted {
4042
int conflicting_block_height;
4143

4244
explicit TxStateConflicted(const uint256& block_hash, int height) : conflicting_block_hash(block_hash), conflicting_block_height(height) {}
45+
std::string toString() const { return strprintf("Conflicted (block=%s, height=%i)", conflicting_block_hash.ToString(), conflicting_block_height); }
4346
};
4447

4548
//! State of transaction not confirmed or conflicting with a known block and
@@ -50,6 +53,7 @@ struct TxStateInactive {
5053
bool abandoned;
5154

5255
explicit TxStateInactive(bool abandoned = false) : abandoned(abandoned) {}
56+
std::string toString() const { return strprintf("Inactive (abandoned=%i)", abandoned); }
5357
};
5458

5559
//! State of transaction loaded in an unrecognized state with unexpected hash or
@@ -61,6 +65,7 @@ struct TxStateUnrecognized {
6165
int index;
6266

6367
TxStateUnrecognized(const uint256& block_hash, int index) : block_hash(block_hash), index(index) {}
68+
std::string toString() const { return strprintf("Unrecognized (block=%s, index=%i)", block_hash.ToString(), index); }
6469
};
6570

6671
//! All possible CWalletTx states
@@ -108,6 +113,12 @@ static inline int TxStateSerializedIndex(const TxState& state)
108113
}, state);
109114
}
110115

116+
//! Return TxState or SyncTxState as a string for logging or debugging.
117+
template<typename T>
118+
std::string TxStateString(const T& state)
119+
{
120+
return std::visit([](const auto& s) { return s.toString(); }, state);
121+
}
111122

112123
typedef std::map<std::string, std::string> mapValue_t;
113124

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const
965965
LockProTxCoins(candidates, &batch);
966966

967967
//// debug print
968-
WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
968+
WalletLogPrintf("AddToWallet %s %s%s %s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""), TxStateString(state));
969969

970970
// Write to disk
971971
if (fInsertedNew || fUpdated)

test/functional/interface_rest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ def run_test(self):
336336
assert_greater_than(json_obj['bytes'], 240)
337337

338338
mempool_info = self.nodes[0].getmempoolinfo()
339+
# pop unstable unbroadcastcount before check
340+
for obj in [json_obj, mempool_info]:
341+
obj.pop("unbroadcastcount")
339342
assert_equal(json_obj, mempool_info)
340343

341344
# Check that there are our submitted transactions in the TX memory pool

test/functional/p2p_addr_relay.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,15 @@ def getaddr_tests(self):
296296
assert_equal(block_relay_peer.num_ipv4_received, 0)
297297
assert inbound_peer.num_ipv4_received > 100
298298

299+
self.log.info('Check that we answer getaddr messages only once per connection')
300+
received_addrs_before = inbound_peer.num_ipv4_received
301+
with self.nodes[0].assert_debug_log(['Ignoring repeated "getaddr".']):
302+
inbound_peer.send_and_ping(msg_getaddr())
303+
self.bump_mocktime(10 * 60)
304+
inbound_peer.sync_with_ping()
305+
received_addrs_after = inbound_peer.num_ipv4_received
306+
assert_equal(received_addrs_before, received_addrs_after)
307+
299308
self.nodes[0].disconnect_p2ps()
300309

301310
def blocksonly_mode_tests(self):

test/functional/rpc_blockchain.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
TIME_RANGE_MTP = TIME_GENESIS_BLOCK + (HEIGHT - 6) * TIME_RANGE_STEP
6060
TIME_RANGE_TIP = TIME_GENESIS_BLOCK + (HEIGHT - 1) * TIME_RANGE_STEP
6161
TIME_RANGE_END = TIME_GENESIS_BLOCK + HEIGHT * TIME_RANGE_STEP
62+
DIFFICULTY_ADJUSTMENT_INTERVAL = 2016
6263

6364

6465
class BlockchainTest(BitcoinTestFramework):
@@ -431,6 +432,15 @@ def _test_getnetworkhashps(self):
431432
# This should be 2 hashes every 2.6 minutes (156 seconds) or 1/78
432433
assert abs(hashes_per_second * 78 - 1) < 0.0001
433434

435+
# Test setting the first param of getnetworkhashps to negative value returns the average network
436+
# hashes per second from the last difficulty change.
437+
current_block_height = self.nodes[0].getmininginfo()['blocks']
438+
blocks_since_last_diff_change = current_block_height % DIFFICULTY_ADJUSTMENT_INTERVAL + 1
439+
expected_hashes_per_second_since_diff_change = self.nodes[0].getnetworkhashps(blocks_since_last_diff_change)
440+
441+
assert_equal(self.nodes[0].getnetworkhashps(-1), expected_hashes_per_second_since_diff_change)
442+
assert_equal(self.nodes[0].getnetworkhashps(-2), expected_hashes_per_second_since_diff_change)
443+
434444
def _test_stopatheight(self):
435445
assert_equal(self.nodes[0].getblockcount(), HEIGHT)
436446
self.generate(self.wallet, 6)

test/sanitizer_suppressions/ubsan

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1+
# Suppressions should use `sanitize-type:ClassName::MethodName`.
2+
13
# -fsanitize=undefined suppressions
24
# =================================
3-
# The suppressions would be `sanitize-type:ClassName::MethodName`,
4-
# however due to a bug in clang the symbolizer is disabled and thus no symbol
5-
# names can be used.
6-
# See https://github.com/google/sanitizers/issues/1364
75

86
# -fsanitize=integer suppressions
97
# ===============================
108
# Dependencies
119
# ------------
1210
# Suppressions in dependencies that are developed outside this repository.
1311
unsigned-integer-overflow:*/include/c++/
14-
# unsigned-integer-overflow in FuzzedDataProvider's ConsumeIntegralInRange
15-
unsigned-integer-overflow:FuzzedDataProvider.h
12+
unsigned-integer-overflow:FuzzedDataProvider::ConsumeIntegralInRange
1613
unsigned-integer-overflow:leveldb/
1714
unsigned-integer-overflow:minisketch/
1815
unsigned-integer-overflow:secp256k1/

0 commit comments

Comments
 (0)