mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge pull request #5789 from PastaPastaPasta/develop-trivial-2023-12-27
backport: trivial 2023 12 27
This commit is contained in:
commit
74c7f20088
@ -82,10 +82,8 @@ fi
|
||||
AC_PROG_OBJCXX
|
||||
])
|
||||
|
||||
dnl Since libtool 1.5.2 (released 2004-01-25), on Linux libtool no longer
|
||||
dnl sets RPATH for any directories in the dynamic linker search path.
|
||||
dnl See more: https://wiki.debian.org/RpathIssue
|
||||
LT_PREREQ([1.5.2])
|
||||
dnl OpenBSD ships with 2.4.2
|
||||
LT_PREREQ([2.4.2])
|
||||
dnl Libtool init checks.
|
||||
LT_INIT([pic-only win32-dll])
|
||||
|
||||
@ -1243,7 +1241,7 @@ dnl Do not change "-I/usr/include" to "-isystem /usr/include" because that
|
||||
dnl is not necessary (/usr/include is already a system directory) and because
|
||||
dnl it would break GCC's #include_next.
|
||||
AC_DEFUN([SUPPRESS_WARNINGS],
|
||||
[$(echo $1 |${SED} -E -e 's/(^| )-I/\1-isystem /g' -e 's;-isystem /usr/include([/ ]|$);-I/usr/include\1;g')])
|
||||
[[$(echo $1 |${SED} -E -e 's/(^| )-I/\1-isystem /g' -e 's;-isystem /usr/include/*( |$);-I/usr/include\1;g')]])
|
||||
|
||||
dnl enable-fuzz should disable all other targets
|
||||
if test "x$enable_fuzz" = "xyes"; then
|
||||
|
@ -167,7 +167,7 @@ class TestSymbolChecks(unittest.TestCase):
|
||||
executable = 'test3.exe'
|
||||
with open(source, 'w', encoding="utf8") as f:
|
||||
f.write('''
|
||||
#include <windows.h>
|
||||
#include <combaseapi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
openbsd_CFLAGS=-pipe
|
||||
openbsd_CFLAGS_CXXFLAGS=$(openbsd_CFLAGS)
|
||||
openbsd_CXXFLAGS=$(openbsd_CFLAGS)
|
||||
|
||||
openbsd_CFLAGS_release_CFLAGS=-O2
|
||||
openbsd_CFLAGS_release_CXXFLAGS=$(openbsd_release_CFLAGS)
|
||||
openbsd_release_CFLAGS=-O2
|
||||
openbsd_release_CXXFLAGS=$(openbsd_release_CFLAGS)
|
||||
|
||||
openbsd_CFLAGS_debug_CFLAGS=-O1
|
||||
openbsd_CFLAGS_debug_CXXFLAGS=$(openbsd_debug_CFLAGS)
|
||||
openbsd_debug_CFLAGS=-O1
|
||||
openbsd_debug_CXXFLAGS=$(openbsd_debug_CFLAGS)
|
||||
|
||||
ifeq (86,$(findstring 86,$(build_arch)))
|
||||
i686_openbsd_CC=clang -m32
|
||||
|
@ -36,5 +36,6 @@ define $(package)_stage_cmds
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm lib/*.la
|
||||
rm lib/*.la && \
|
||||
rm include/ev*.h
|
||||
endef
|
||||
|
@ -19,6 +19,4 @@ QMAKE_MAC_SDK.macosx.PlatformPath = /phony
|
||||
!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET}
|
||||
QMAKE_AR = $${CROSS_COMPILE}ar cq
|
||||
QMAKE_RANLIB=$${CROSS_COMPILE}ranlib
|
||||
QMAKE_LIBTOOL=$${CROSS_COMPILE}libtool
|
||||
QMAKE_INSTALL_NAME_TOOL=$${CROSS_COMPILE}install_name_tool
|
||||
load(qt_config)
|
||||
|
@ -37,7 +37,7 @@ The following dependencies are **optional**:
|
||||
## Preparation
|
||||
|
||||
### 1. Install Required Dependencies
|
||||
Install the required dependencies the usual way you [install software on FreeBSD](https://www.freebsd.org/doc/en/books/handbook/ports.html) - either with `pkg` or via the Ports collection. The example commands below use `pkg` which is usually run as `root` or via `sudo`. If you want to use `sudo`, and you haven't set it up: [use this guide](http://www.freebsdwiki.net/index.php/Sudo%2C_configuring) to setup `sudo` access on FreeBSD.
|
||||
Run the following as root to install the base dependencies for building.
|
||||
|
||||
```bash
|
||||
pkg install autoconf automake boost-libs git gmake libevent libtool pkgconf
|
||||
|
@ -398,8 +398,19 @@ all-local: $(FUZZ_BINARY)
|
||||
endif
|
||||
|
||||
%.cpp.test: %.cpp
|
||||
@echo Running tests: `cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
|
||||
$(AM_V_at)$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" -- DEBUG_LOG_OUT > $<.log 2>&1 || (cat $<.log && false)
|
||||
@echo Running tests: $$(\
|
||||
cat $< | \
|
||||
grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | \
|
||||
cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1\
|
||||
) from $<
|
||||
$(AM_V_at)export TEST_LOGFILE=$(abs_builddir)/$$(\
|
||||
echo $< | grep -E -o "(wallet/test/.*\.cpp|test/.*\.cpp)" | $(SED) -e s/\.cpp/.log/ \
|
||||
) && \
|
||||
$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "$$(\
|
||||
cat $< | \
|
||||
grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | \
|
||||
cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1\
|
||||
)" -- DEBUG_LOG_OUT > "$$TEST_LOGFILE" 2>&1 || (cat "$$TEST_LOGFILE" && false)
|
||||
|
||||
test/data/%.json.h: test/data/%.json
|
||||
@$(MKDIR_P) $(@D)
|
||||
|
@ -58,6 +58,7 @@ private:
|
||||
mutable int nRandomPos{-1};
|
||||
|
||||
friend class CAddrMan;
|
||||
friend class CAddrManDeterministic;
|
||||
|
||||
public:
|
||||
|
||||
@ -808,6 +809,7 @@ private:
|
||||
void ResetI2PPorts() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
friend class CAddrManTest;
|
||||
friend class CAddrManDeterministic;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ADDRMAN_H
|
||||
|
@ -334,6 +334,17 @@ void BitcoinApplication::requestShutdown()
|
||||
window->setClientModel(nullptr);
|
||||
pollShutdownTimer->stop();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// Delete wallet controller here manually, instead of relying on Qt object
|
||||
// tracking (https://doc.qt.io/qt-5/objecttrees.html). This makes sure
|
||||
// walletmodel m_handle_* notification handlers are deleted before wallets
|
||||
// are unloaded, which can simplify wallet implementations. It also avoids
|
||||
// these notifications having to be handled while GUI objects are being
|
||||
// destroyed, making GUI code less fragile as well.
|
||||
delete m_wallet_controller;
|
||||
m_wallet_controller = nullptr;
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
delete clientModel;
|
||||
clientModel = nullptr;
|
||||
|
||||
@ -414,6 +425,16 @@ WId BitcoinApplication::getMainWinId() const
|
||||
return window->winId();
|
||||
}
|
||||
|
||||
bool BitcoinApplication::event(QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::Quit) {
|
||||
requestShutdown();
|
||||
return true;
|
||||
}
|
||||
|
||||
return QApplication::event(e);
|
||||
}
|
||||
|
||||
static void SetupUIArgs(ArgsManager& argsman)
|
||||
{
|
||||
argsman.AddArg("-choosedatadir", strprintf(QObject::tr("Choose data directory on startup (default: %u)").toStdString(), DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
|
@ -98,6 +98,9 @@ Q_SIGNALS:
|
||||
void splashFinished();
|
||||
void windowShown(BitcoinGUI* window);
|
||||
|
||||
protected:
|
||||
bool event(QEvent* e) override;
|
||||
|
||||
private:
|
||||
QThread *coreThread;
|
||||
interfaces::Node& m_node;
|
||||
|
@ -213,6 +213,9 @@
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2_Main">
|
||||
<item>
|
||||
<widget class="QLabel" name="databaseCacheLabel">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.">Maximum database cache size. A larger cache can contribute to faster sync, after which the benefit is less pronounced for most use cases. Lowering the cache size will reduce memory usage. Unused mempool memory is shared for this cache.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Size of &database cache</string>
|
||||
</property>
|
||||
@ -256,6 +259,9 @@
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_Main_VerifyLabel">
|
||||
<item>
|
||||
<widget class="QLabel" name="threadsScriptVerifLabel">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Tooltip text for Options window setting that sets the number of script verification threads. Explains that negative values mean to leave these many cores free to the system.">Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of script &verification threads</string>
|
||||
</property>
|
||||
|
@ -114,7 +114,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri
|
||||
if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
|
||||
progressDelta = blockProcessTime[0].second - sample.second;
|
||||
timeDelta = blockProcessTime[0].first - sample.first;
|
||||
progressPerHour = progressDelta / (double) timeDelta * 1000 * 3600;
|
||||
progressPerHour = (progressDelta > 0) ? progressDelta / (double)timeDelta * 1000 * 3600 : 0;
|
||||
remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
|
||||
break;
|
||||
}
|
||||
|
@ -225,10 +225,11 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
|
||||
UniValue subelement;
|
||||
if (lastResult.isArray())
|
||||
{
|
||||
for(char argch: curarg)
|
||||
if (!IsDigit(argch))
|
||||
throw std::runtime_error("Invalid result query");
|
||||
subelement = lastResult[LocaleIndependentAtoi<int>(curarg)];
|
||||
const auto parsed{ToIntegral<size_t>(curarg)};
|
||||
if (!parsed) {
|
||||
throw std::runtime_error("Invalid result query");
|
||||
}
|
||||
subelement = lastResult[parsed.value()];
|
||||
}
|
||||
else if (lastResult.isObject())
|
||||
subelement = find_value(lastResult, curarg);
|
||||
|
@ -26,6 +26,12 @@ void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
|
||||
const T i = fuzzed_data_provider.ConsumeIntegral<T>();
|
||||
const T j = fuzzed_data_provider.ConsumeIntegral<T>();
|
||||
const bool is_addition_overflow_custom = AdditionOverflow(i, j);
|
||||
const auto maybe_add{CheckedAdd(i, j)};
|
||||
const auto sat_add{SaturatingAdd(i, j)};
|
||||
assert(is_addition_overflow_custom == !maybe_add.has_value());
|
||||
assert(is_addition_overflow_custom == AdditionOverflow(j, i));
|
||||
assert(maybe_add == CheckedAdd(j, i));
|
||||
assert(sat_add == SaturatingAdd(j, i));
|
||||
#if defined(HAVE_BUILTIN_ADD_OVERFLOW)
|
||||
T result_builtin;
|
||||
const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin);
|
||||
@ -33,11 +39,14 @@ void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
|
||||
if (!is_addition_overflow_custom) {
|
||||
assert(i + j == result_builtin);
|
||||
}
|
||||
#else
|
||||
if (!is_addition_overflow_custom) {
|
||||
(void)(i + j);
|
||||
}
|
||||
#endif
|
||||
if (is_addition_overflow_custom) {
|
||||
assert(sat_add == std::numeric_limits<T>::min() || sat_add == std::numeric_limits<T>::max());
|
||||
} else {
|
||||
const auto add{i + j};
|
||||
assert(add == maybe_add.value());
|
||||
assert(add == sat_add);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <time.h>
|
||||
#include <util/asmap.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@ -25,10 +26,200 @@ void initialize_addrman()
|
||||
class CAddrManDeterministic : public CAddrMan
|
||||
{
|
||||
public:
|
||||
void MakeDeterministic(const uint256& random_seed)
|
||||
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||
|
||||
explicit CAddrManDeterministic(FuzzedDataProvider& fuzzed_data_provider)
|
||||
: m_fuzzed_data_provider(fuzzed_data_provider)
|
||||
{
|
||||
WITH_LOCK(cs, insecure_rand = FastRandomContext{random_seed});
|
||||
Clear();
|
||||
WITH_LOCK(cs, insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
|
||||
if (!SanityCheckASMap(m_asmap)) {
|
||||
m_asmap.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random address. Always returns a valid address.
|
||||
*/
|
||||
CNetAddr RandAddr() EXCLUSIVE_LOCKS_REQUIRED(cs)
|
||||
{
|
||||
CNetAddr addr;
|
||||
if (m_fuzzed_data_provider.remaining_bytes() > 1 && m_fuzzed_data_provider.ConsumeBool()) {
|
||||
addr = ConsumeNetAddr(m_fuzzed_data_provider);
|
||||
} else {
|
||||
// The networks [1..6] correspond to CNetAddr::BIP155Network (private).
|
||||
static const std::map<uint8_t, uint8_t> net_len_map = {{1, ADDR_IPV4_SIZE},
|
||||
{2, ADDR_IPV6_SIZE},
|
||||
{4, ADDR_TORV3_SIZE},
|
||||
{5, ADDR_I2P_SIZE},
|
||||
{6, ADDR_CJDNS_SIZE}};
|
||||
uint8_t net = insecure_rand.randrange(5) + 1; // [1..5]
|
||||
if (net == 3) {
|
||||
net = 6;
|
||||
}
|
||||
|
||||
CDataStream s(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
|
||||
|
||||
s << net;
|
||||
s << insecure_rand.randbytes(net_len_map.at(net));
|
||||
|
||||
s >> addr;
|
||||
}
|
||||
|
||||
// Return a dummy IPv4 5.5.5.5 if we generated an invalid address.
|
||||
if (!addr.IsValid()) {
|
||||
in_addr v4_addr = {};
|
||||
v4_addr.s_addr = 0x05050505;
|
||||
addr = CNetAddr{v4_addr};
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill this addrman with lots of addresses from lots of sources.
|
||||
*/
|
||||
void Fill()
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
// Add some of the addresses directly to the "tried" table.
|
||||
|
||||
// 0, 1, 2, 3 corresponding to 0%, 100%, 50%, 33%
|
||||
const size_t n = m_fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3);
|
||||
|
||||
const size_t num_sources = m_fuzzed_data_provider.ConsumeIntegralInRange<size_t>(10, 50);
|
||||
CNetAddr prev_source;
|
||||
// Use insecure_rand inside the loops instead of m_fuzzed_data_provider because when
|
||||
// the latter is exhausted it just returns 0.
|
||||
for (size_t i = 0; i < num_sources; ++i) {
|
||||
const auto source = RandAddr();
|
||||
const size_t num_addresses = insecure_rand.randrange(500) + 1; // [1..500]
|
||||
|
||||
for (size_t j = 0; j < num_addresses; ++j) {
|
||||
const auto addr = CAddress{CService{RandAddr(), 8333}, NODE_NETWORK};
|
||||
const auto time_penalty = insecure_rand.randrange(100000001);
|
||||
#if 1
|
||||
// 2.83 sec to fill.
|
||||
if (n > 0 && mapInfo.size() % n == 0 && mapAddr.find(addr) == mapAddr.end()) {
|
||||
// Add to the "tried" table (if the bucket slot is free).
|
||||
const CAddrInfo dummy{addr, source};
|
||||
const int bucket = dummy.GetTriedBucket(nKey, m_asmap);
|
||||
const int bucket_pos = dummy.GetBucketPosition(nKey, false, bucket);
|
||||
if (vvTried[bucket][bucket_pos] == -1) {
|
||||
int id;
|
||||
CAddrInfo* addr_info = Create(addr, source, &id);
|
||||
vvTried[bucket][bucket_pos] = id;
|
||||
addr_info->fInTried = true;
|
||||
++nTried;
|
||||
}
|
||||
} else {
|
||||
// Add to the "new" table.
|
||||
Add_(addr, source, time_penalty);
|
||||
}
|
||||
#else
|
||||
// 261.91 sec to fill.
|
||||
Add_(addr, source, time_penalty);
|
||||
if (n > 0 && mapInfo.size() % n == 0) {
|
||||
Good_(addr, false, GetTime());
|
||||
}
|
||||
#endif
|
||||
// Add 10% of the addresses from more than one source.
|
||||
if (insecure_rand.randrange(10) == 0 && prev_source.IsValid()) {
|
||||
Add_(addr, prev_source, time_penalty);
|
||||
}
|
||||
}
|
||||
prev_source = source;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare with another AddrMan.
|
||||
* This compares:
|
||||
* - the values in `mapInfo` (the keys aka ids are ignored)
|
||||
* - vvNew entries refer to the same addresses
|
||||
* - vvTried entries refer to the same addresses
|
||||
*/
|
||||
bool operator==(const CAddrManDeterministic& other)
|
||||
{
|
||||
LOCK2(cs, other.cs);
|
||||
|
||||
if (mapInfo.size() != other.mapInfo.size() || nNew != other.nNew ||
|
||||
nTried != other.nTried) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
|
||||
// Keys may be different.
|
||||
|
||||
using CAddrInfoHasher = std::function<size_t(const CAddrInfo&)>;
|
||||
using CAddrInfoEq = std::function<bool(const CAddrInfo&, const CAddrInfo&)>;
|
||||
|
||||
CNetAddrHash netaddr_hasher;
|
||||
|
||||
CAddrInfoHasher addrinfo_hasher = [&netaddr_hasher](const CAddrInfo& a) {
|
||||
return netaddr_hasher(static_cast<CNetAddr>(a)) ^ netaddr_hasher(a.source) ^
|
||||
a.nLastSuccess ^ a.nAttempts ^ a.nRefCount ^ a.fInTried;
|
||||
};
|
||||
|
||||
CAddrInfoEq addrinfo_eq = [](const CAddrInfo& lhs, const CAddrInfo& rhs) {
|
||||
return static_cast<CNetAddr>(lhs) == static_cast<CNetAddr>(rhs) &&
|
||||
lhs.source == rhs.source && lhs.nLastSuccess == rhs.nLastSuccess &&
|
||||
lhs.nAttempts == rhs.nAttempts && lhs.nRefCount == rhs.nRefCount &&
|
||||
lhs.fInTried == rhs.fInTried;
|
||||
};
|
||||
|
||||
using Addresses = std::unordered_set<CAddrInfo, CAddrInfoHasher, CAddrInfoEq>;
|
||||
|
||||
const size_t num_addresses{mapInfo.size()};
|
||||
|
||||
Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
||||
for (const auto& [id, addr] : mapInfo) {
|
||||
addresses.insert(addr);
|
||||
}
|
||||
|
||||
Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
||||
for (const auto& [id, addr] : other.mapInfo) {
|
||||
other_addresses.insert(addr);
|
||||
}
|
||||
|
||||
if (addresses != other_addresses) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto IdsReferToSameAddress = [&](int id, int other_id) EXCLUSIVE_LOCKS_REQUIRED(cs, other.cs) {
|
||||
if (id == -1 && other_id == -1) {
|
||||
return true;
|
||||
}
|
||||
if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
|
||||
return false;
|
||||
}
|
||||
return mapInfo.at(id) == other.mapInfo.at(other_id);
|
||||
};
|
||||
|
||||
// Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
|
||||
// contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
|
||||
// themselves may differ between `vvNew` and `other.vvNew`.
|
||||
for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
|
||||
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
||||
if (!IdsReferToSameAddress(vvNew[i][j], other.vvNew[i][j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same for `vvTried`.
|
||||
for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
|
||||
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
||||
if (!IdsReferToSameAddress(vvTried[i][j], other.vvTried[i][j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -36,14 +227,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
||||
CAddrManDeterministic addr_man;
|
||||
addr_man.MakeDeterministic(ConsumeUInt256(fuzzed_data_provider));
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
addr_man.m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
|
||||
if (!SanityCheckASMap(addr_man.m_asmap)) {
|
||||
addr_man.m_asmap.clear();
|
||||
}
|
||||
}
|
||||
CAddrManDeterministic addr_man{fuzzed_data_provider};
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
||||
CDataStream ds(serialized_data, SER_DISK, INIT_PROTO_VERSION);
|
||||
@ -126,3 +310,21 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
|
||||
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
data_stream << addr_man;
|
||||
}
|
||||
|
||||
// Check that serialize followed by unserialize produces the same addrman.
|
||||
FUZZ_TARGET_INIT(addrman_serdeser, initialize_addrman)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
||||
|
||||
CAddrManDeterministic addr_man1{fuzzed_data_provider};
|
||||
CAddrManDeterministic addr_man2{fuzzed_data_provider};
|
||||
addr_man2.m_asmap = addr_man1.m_asmap;
|
||||
|
||||
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
addr_man1.Fill();
|
||||
data_stream << addr_man1;
|
||||
data_stream >> addr_man2;
|
||||
assert(addr_man1 == addr_man2);
|
||||
}
|
||||
|
@ -1506,9 +1506,17 @@ static void TestAddMatrixOverflow()
|
||||
constexpr T MAXI{std::numeric_limits<T>::max()};
|
||||
BOOST_CHECK(!CheckedAdd(T{1}, MAXI));
|
||||
BOOST_CHECK(!CheckedAdd(MAXI, MAXI));
|
||||
BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI));
|
||||
BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(MAXI, MAXI));
|
||||
|
||||
BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value());
|
||||
BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value());
|
||||
BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value());
|
||||
BOOST_CHECK_EQUAL(MAXI - 1, CheckedAdd(T{1}, MAXI - 2).value());
|
||||
BOOST_CHECK_EQUAL(0, SaturatingAdd(T{0}, T{0}));
|
||||
BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{0}, MAXI));
|
||||
BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI - 1));
|
||||
BOOST_CHECK_EQUAL(MAXI - 1, SaturatingAdd(T{1}, MAXI - 2));
|
||||
}
|
||||
|
||||
/* Check for overflow or underflow */
|
||||
@ -1520,9 +1528,17 @@ static void TestAddMatrix()
|
||||
constexpr T MAXI{std::numeric_limits<T>::max()};
|
||||
BOOST_CHECK(!CheckedAdd(T{-1}, MINI));
|
||||
BOOST_CHECK(!CheckedAdd(MINI, MINI));
|
||||
BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI));
|
||||
BOOST_CHECK_EQUAL(MINI, SaturatingAdd(MINI, MINI));
|
||||
|
||||
BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value());
|
||||
BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value());
|
||||
BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value());
|
||||
BOOST_CHECK_EQUAL(MINI + 1, CheckedAdd(T{-1}, MINI + 2).value());
|
||||
BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{0}, MINI));
|
||||
BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI + 1));
|
||||
BOOST_CHECK_EQUAL(MINI + 1, SaturatingAdd(T{-1}, MINI + 2));
|
||||
BOOST_CHECK_EQUAL(-1, SaturatingAdd(MINI, MAXI));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_overflow)
|
||||
|
@ -13,7 +13,7 @@ template <class T>
|
||||
[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "Integral required.");
|
||||
if (std::numeric_limits<T>::is_signed) {
|
||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
||||
return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
|
||||
(i < 0 && j < std::numeric_limits<T>::min() - i);
|
||||
}
|
||||
@ -29,4 +29,22 @@ template <class T>
|
||||
return i + j;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
[[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept
|
||||
{
|
||||
if constexpr (std::numeric_limits<T>::is_signed) {
|
||||
if (i > 0 && j > std::numeric_limits<T>::max() - i) {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
if (i < 0 && j < std::numeric_limits<T>::min() - i) {
|
||||
return std::numeric_limits<T>::min();
|
||||
}
|
||||
} else {
|
||||
if (std::numeric_limits<T>::max() - i < j) {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
}
|
||||
return i + j;
|
||||
}
|
||||
|
||||
#endif // BITCOIN_UTIL_OVERFLOW_H
|
||||
|
Loading…
Reference in New Issue
Block a user