aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init.cpp2
-rw-r--r--src/qt/qvalidatedlineedit.cpp9
-rw-r--r--src/qt/qvalidatedlineedit.h1
-rw-r--r--src/random.cpp20
-rw-r--r--src/script/script.h4
-rw-r--r--src/streams.h67
-rw-r--r--src/test/coins_tests.cpp6
-rw-r--r--src/test/fuzz/coins_view.cpp2
-rw-r--r--src/test/fuzz/string.cpp3
-rw-r--r--src/test/getarg_tests.cpp92
-rw-r--r--src/test/serialize_tests.cpp45
-rw-r--r--src/test/streams_tests.cpp43
-rw-r--r--src/util/strencodings.cpp3
-rw-r--r--src/util/system.cpp54
-rw-r--r--src/util/system.h16
-rw-r--r--src/validation.cpp8
-rw-r--r--src/validation.h17
-rw-r--r--src/wallet/load.cpp2
-rw-r--r--src/wallet/rpc/wallet.cpp2
-rw-r--r--src/wallet/test/init_tests.cpp8
-rw-r--r--src/wallet/walletutil.cpp2
21 files changed, 203 insertions, 203 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 330aab5184..6aef1f8149 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1150,7 +1150,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
// Warn about relative -datadir path.
- if (args.IsArgSet("-datadir") && !fs::PathFromString(args.GetArg("-datadir", "")).is_absolute()) {
+ if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {
LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
"current working directory '%s'. This is fragile, because if bitcoin is started in the future "
"from a different location, it will be unable to locate the current data files. There could "
diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp
index aa936d6b7c..bd4df75d23 100644
--- a/src/qt/qvalidatedlineedit.cpp
+++ b/src/qt/qvalidatedlineedit.cpp
@@ -15,6 +15,12 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}
+void QValidatedLineEdit::setText(const QString& text)
+{
+ QLineEdit::setText(text);
+ checkValidity();
+}
+
void QValidatedLineEdit::setValid(bool _valid)
{
if(_valid == this->valid)
@@ -28,7 +34,7 @@ void QValidatedLineEdit::setValid(bool _valid)
}
else
{
- setStyleSheet(STYLE_INVALID);
+ setStyleSheet("QValidatedLineEdit { " STYLE_INVALID "}");
}
this->valid = _valid;
}
@@ -106,6 +112,7 @@ void QValidatedLineEdit::checkValidity()
void QValidatedLineEdit::setCheckValidator(const QValidator *v)
{
checkValidator = v;
+ checkValidity();
}
bool QValidatedLineEdit::isValid()
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index b32305f5e1..12d35aa264 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -29,6 +29,7 @@ private:
const QValidator *checkValidator;
public Q_SLOTS:
+ void setText(const QString&);
void setValid(bool valid);
void setEnabled(bool enabled);
diff --git a/src/random.cpp b/src/random.cpp
index 5dae80fe31..b862510524 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -32,10 +32,8 @@
#include <sys/syscall.h>
#include <linux/random.h>
#endif
-#if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX))
-#include <unistd.h>
-#endif
#if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
+#include <unistd.h>
#include <sys/random.h>
#endif
#ifdef HAVE_SYSCTL_ARND
@@ -305,16 +303,14 @@ void GetOSRand(unsigned char *ent32)
RandFailure();
}
}
-#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
- /* On OpenBSD this can return up to 256 bytes of entropy, will return an
- * error if more are requested.
- * The call cannot return less than the requested number of bytes.
- getentropy is explicitly limited to openbsd here, as a similar (but not
- the same) function may exist on other platforms via glibc.
+#elif defined(__OpenBSD__)
+ /* OpenBSD. From the arc4random(3) man page:
+ "Use of these functions is encouraged for almost all random number
+ consumption because the other interfaces are deficient in either
+ quality, portability, standardization, or availability."
+ The function call is always successful.
*/
- if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
- RandFailure();
- }
+ arc4random_buf(ent32, NUM_OS_RANDOM_BYTES);
// Silence a compiler warning about unused function.
(void)GetDevURandom;
#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
diff --git a/src/script/script.h b/src/script/script.h
index 3425bf8102..8b7a7bb7b3 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -51,10 +51,10 @@ static const uint32_t LOCKTIME_MAX = 0xFFFFFFFFU;
static constexpr unsigned int ANNEX_TAG = 0x50;
// Validation weight per passing signature (Tapscript only, see BIP 342).
-static constexpr uint64_t VALIDATION_WEIGHT_PER_SIGOP_PASSED = 50;
+static constexpr int64_t VALIDATION_WEIGHT_PER_SIGOP_PASSED{50};
// How much weight budget is added to the witness size (Tapscript only, see BIP 342).
-static constexpr uint64_t VALIDATION_WEIGHT_OFFSET = 50;
+static constexpr int64_t VALIDATION_WEIGHT_OFFSET{50};
template <typename T>
std::vector<unsigned char> ToByteVector(const T& in)
diff --git a/src/streams.h b/src/streams.h
index 2f26be6dd8..cf8b4eb96f 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -240,76 +240,9 @@ public:
const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
reference operator[](size_type pos) { return vch[pos + nReadPos]; }
void clear() { vch.clear(); nReadPos = 0; }
- iterator insert(iterator it, const value_type x) { return vch.insert(it, x); }
- void insert(iterator it, size_type n, const value_type x) { vch.insert(it, n, x); }
value_type* data() { return vch.data() + nReadPos; }
const value_type* data() const { return vch.data() + nReadPos; }
- void insert(iterator it, std::vector<value_type>::const_iterator first, std::vector<value_type>::const_iterator last)
- {
- if (last == first) return;
- assert(last - first > 0);
- if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
- {
- // special case for inserting at the front when there's room
- nReadPos -= (last - first);
- memcpy(&vch[nReadPos], &first[0], last - first);
- }
- else
- vch.insert(it, first, last);
- }
-
- void insert(iterator it, const value_type* first, const value_type* last)
- {
- if (last == first) return;
- assert(last - first > 0);
- if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
- {
- // special case for inserting at the front when there's room
- nReadPos -= (last - first);
- memcpy(&vch[nReadPos], &first[0], last - first);
- }
- else
- vch.insert(it, first, last);
- }
-
- iterator erase(iterator it)
- {
- if (it == vch.begin() + nReadPos)
- {
- // special case for erasing from the front
- if (++nReadPos >= vch.size())
- {
- // whenever we reach the end, we take the opportunity to clear the buffer
- nReadPos = 0;
- return vch.erase(vch.begin(), vch.end());
- }
- return vch.begin() + nReadPos;
- }
- else
- return vch.erase(it);
- }
-
- iterator erase(iterator first, iterator last)
- {
- if (first == vch.begin() + nReadPos)
- {
- // special case for erasing from the front
- if (last == vch.end())
- {
- nReadPos = 0;
- return vch.erase(vch.begin(), vch.end());
- }
- else
- {
- nReadPos = (last - vch.begin());
- return last;
- }
- }
- else
- return vch.erase(first, last);
- }
-
inline void Compact()
{
vch.erase(vch.begin(), vch.begin() + nReadPos);
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 922fd8e513..82e4e1c90f 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
tx.vout.resize(1);
tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate
tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting
- unsigned int height = InsecureRand32();
+ const int height{int(InsecureRand32() >> 1)};
Coin old_coin;
// 2/20 times create a new coinbase
@@ -393,11 +393,11 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Update the expected result to know about the new output coins
assert(tx.vout.size() == 1);
const COutPoint outpoint(tx.GetHash(), 0);
- result[outpoint] = Coin{tx.vout[0], int(height), CTransaction(tx).IsCoinBase()};
+ result[outpoint] = Coin{tx.vout[0], height, CTransaction{tx}.IsCoinBase()};
// Call UpdateCoins on the top cache
CTxUndo undo;
- UpdateCoins(CTransaction(tx), *(stack.back()), undo, int(height));
+ UpdateCoins(CTransaction{tx}, *(stack.back()), undo, height);
// Update the utxo set for future spends
utxoset.insert(outpoint);
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index 994b4b9e49..360dc00307 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -211,7 +211,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
return;
}
bool expected_code_path = false;
- const int height = fuzzed_data_provider.ConsumeIntegral<int>();
+ const int height{int(fuzzed_data_provider.ConsumeIntegral<uint32_t>() >> 1)};
const bool possible_overwrite = fuzzed_data_provider.ConsumeBool();
try {
AddCoins(coins_view_cache, transaction, height, possible_overwrite);
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 8f071b71fe..ca57af25c4 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -145,7 +145,8 @@ FUZZ_TARGET(string)
(void)CopyrightHolders(random_string_1);
FeeEstimateMode fee_estimate_mode;
(void)FeeModeFromString(random_string_1, fee_estimate_mode);
- (void)FormatParagraph(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 1000));
+ const auto width{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 1000)};
+ (void)FormatParagraph(random_string_1, width, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, width));
(void)FormatSubVersion(random_string_1, fuzzed_data_provider.ConsumeIntegral<int>(), random_string_vector);
(void)GetDescriptorChecksum(random_string_1);
(void)HelpExampleCli(random_string_1, random_string_2);
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index d5142c8d74..597d774673 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -159,6 +159,98 @@ BOOST_AUTO_TEST_CASE(intarg)
BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0);
}
+BOOST_AUTO_TEST_CASE(patharg)
+{
+ const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY);
+ SetupArgs({dir});
+ ResetArgs("");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{});
+
+ const fs::path root_path{"/"};
+ ResetArgs("-dir=/");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+
+ ResetArgs("-dir=/.");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+
+ ResetArgs("-dir=/./");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+
+ ResetArgs("-dir=/.//");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+
+#ifdef WIN32
+ const fs::path win_root_path{"C:\\"};
+ ResetArgs("-dir=C:\\");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+
+ ResetArgs("-dir=C:/");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+
+ ResetArgs("-dir=C:\\\\");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+
+ ResetArgs("-dir=C:\\.");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+
+ ResetArgs("-dir=C:\\.\\");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+
+ ResetArgs("-dir=C:\\.\\\\");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+#endif
+
+ const fs::path absolute_path{"/home/user/.bitcoin"};
+ ResetArgs("-dir=/home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/root/../home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/./user/.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/user/.bitcoin/");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/user/.bitcoin//");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ ResetArgs("-dir=/home/user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+
+ const fs::path relative_path{"user/.bitcoin"};
+ ResetArgs("-dir=user/.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=somewhere/../user/.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/./.bitcoin");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/.bitcoin/");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/.bitcoin//");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs("-dir=user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+}
+
BOOST_AUTO_TEST_CASE(doubledash)
{
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 8b8133b689..2441847f99 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -215,51 +215,6 @@ BOOST_AUTO_TEST_CASE(noncanonical)
BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
}
-BOOST_AUTO_TEST_CASE(insert_delete)
-{
- constexpr auto B2I{[](std::byte b) { return std::to_integer<uint8_t>(b); }};
-
- // Test inserting/deleting bytes.
- CDataStream ss(SER_DISK, 0);
- BOOST_CHECK_EQUAL(ss.size(), 0U);
-
- ss.write(MakeByteSpan("\x00\x01\x02\xff").first(4));
- BOOST_CHECK_EQUAL(ss.size(), 4U);
-
- uint8_t c{11};
-
- // Inserting at beginning/end/middle:
- ss.insert(ss.begin(), std::byte{c});
- BOOST_CHECK_EQUAL(ss.size(), 5U);
- BOOST_CHECK_EQUAL(B2I(ss[0]), c);
- BOOST_CHECK_EQUAL(B2I(ss[1]), 0);
-
- ss.insert(ss.end(), std::byte{c});
- BOOST_CHECK_EQUAL(ss.size(), 6U);
- BOOST_CHECK_EQUAL(B2I(ss[4]), 0xff);
- BOOST_CHECK_EQUAL(B2I(ss[5]), c);
-
- ss.insert(ss.begin() + 2, std::byte{c});
- BOOST_CHECK_EQUAL(ss.size(), 7U);
- BOOST_CHECK_EQUAL(B2I(ss[2]), c);
-
- // Delete at beginning/end/middle
- ss.erase(ss.begin());
- BOOST_CHECK_EQUAL(ss.size(), 6U);
- BOOST_CHECK_EQUAL(B2I(ss[0]), 0);
-
- ss.erase(ss.begin()+ss.size()-1);
- BOOST_CHECK_EQUAL(ss.size(), 5U);
- BOOST_CHECK_EQUAL(B2I(ss[4]), 0xff);
-
- ss.erase(ss.begin()+1);
- BOOST_CHECK_EQUAL(ss.size(), 4U);
- BOOST_CHECK_EQUAL(B2I(ss[0]), 0);
- BOOST_CHECK_EQUAL(B2I(ss[1]), 1);
- BOOST_CHECK_EQUAL(B2I(ss[2]), 2);
- BOOST_CHECK_EQUAL(B2I(ss[3]), 0xff);
-}
-
BOOST_AUTO_TEST_CASE(class_methods)
{
int intval(100);
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 6a69fe9840..0925e2e9ee 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -8,6 +8,8 @@
#include <boost/test/unit_test.hpp>
+using namespace std::string_literals;
+
BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(streams_vector_writer)
@@ -162,46 +164,35 @@ BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
{
std::vector<std::byte> in;
- std::vector<char> expected_xor;
- CDataStream ds(in, 0, 0);
// Degenerate case
- ds.Xor({0x00, 0x00});
- BOOST_CHECK_EQUAL(
- std::string(expected_xor.begin(), expected_xor.end()),
- ds.str());
+ {
+ CDataStream ds{in, 0, 0};
+ ds.Xor({0x00, 0x00});
+ BOOST_CHECK_EQUAL(""s, ds.str());
+ }
in.push_back(std::byte{0x0f});
in.push_back(std::byte{0xf0});
- expected_xor.push_back('\xf0');
- expected_xor.push_back('\x0f');
// Single character key
-
- ds.clear();
- ds.insert(ds.begin(), in.begin(), in.end());
-
- ds.Xor({0xff});
- BOOST_CHECK_EQUAL(
- std::string(expected_xor.begin(), expected_xor.end()),
- ds.str());
+ {
+ CDataStream ds{in, 0, 0};
+ ds.Xor({0xff});
+ BOOST_CHECK_EQUAL("\xf0\x0f"s, ds.str());
+ }
// Multi character key
in.clear();
- expected_xor.clear();
in.push_back(std::byte{0xf0});
in.push_back(std::byte{0x0f});
- expected_xor.push_back('\x0f');
- expected_xor.push_back('\x00');
-
- ds.clear();
- ds.insert(ds.begin(), in.begin(), in.end());
- ds.Xor({0xff, 0x0f});
- BOOST_CHECK_EQUAL(
- std::string(expected_xor.begin(), expected_xor.end()),
- ds.str());
+ {
+ CDataStream ds{in, 0, 0};
+ ds.Xor({0xff, 0x0f});
+ BOOST_CHECK_EQUAL("\x0f\x00"s, ds.str());
+ }
}
BOOST_AUTO_TEST_CASE(streams_buffered_file)
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index a386f2b7b3..940fa90da2 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -113,7 +113,7 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut)
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
bool fHaveColon = colon != in.npos;
bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
- bool fMultiColon = fHaveColon && (in.find_last_of(':', colon - 1) != in.npos);
+ bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)};
if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
uint16_t n;
if (ParseUInt16(in.substr(colon + 1), &n)) {
@@ -328,6 +328,7 @@ bool ParseUInt64(const std::string& str, uint64_t* out)
std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
{
+ assert(width >= indent);
std::stringstream out;
size_t ptr = 0;
size_t indented = 0;
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 8d0cec249d..5cef2be07a 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -74,6 +74,7 @@
#include <memory>
#include <optional>
#include <string>
+#include <system_error>
#include <thread>
#include <typeinfo>
@@ -245,19 +246,6 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con
return value;
}
-namespace {
-fs::path StripRedundantLastElementsOfPath(const fs::path& path)
-{
- auto result = path;
- while (result.filename().empty() || fs::PathToString(result.filename()) == ".") {
- result = result.parent_path();
- }
-
- assert(fs::equivalent(result, path.lexically_normal()));
- return result;
-}
-} // namespace
-
// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
// #include class definitions for all members.
// For example, m_settings has an internal dependency on univalue.
@@ -399,6 +387,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
return std::nullopt;
}
+fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const
+{
+ auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal();
+ // Remove trailing slash, if present.
+ return result.has_filename() ? result : result.parent_path();
+}
+
const fs::path& ArgsManager::GetBlocksDirPath() const
{
LOCK(cs_args);
@@ -409,7 +404,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
if (!path.empty()) return path;
if (IsArgSet("-blocksdir")) {
- path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", "")));
+ path = fs::absolute(GetPathArg("-blocksdir"));
if (!fs::is_directory(path)) {
path = "";
return path;
@@ -433,9 +428,9 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
// this function
if (!path.empty()) return path;
- std::string datadir = GetArg("-datadir", "");
+ const fs::path datadir{GetPathArg("-datadir")};
if (!datadir.empty()) {
- path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir)));
+ path = fs::absolute(datadir);
if (!fs::is_directory(path)) {
path = "";
return path;
@@ -443,15 +438,18 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
} else {
path = GetDefaultDataDir();
}
- if (net_specific)
- path /= fs::PathFromString(BaseParams().DataDir());
- if (fs::create_directories(path)) {
- // This is the first run, create wallets subdirectory too
+ if (!fs::exists(path)) {
fs::create_directories(path / "wallets");
}
- path = StripRedundantLastElementsOfPath(path);
+ if (net_specific && !BaseParams().DataDir().empty()) {
+ path /= fs::PathFromString(BaseParams().DataDir());
+ if (!fs::exists(path)) {
+ fs::create_directories(path / "wallets");
+ }
+ }
+
return path;
}
@@ -812,8 +810,8 @@ fs::path GetDefaultDataDir()
bool CheckDataDirOption()
{
- std::string datadir = gArgs.GetArg("-datadir", "");
- return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir)));
+ const fs::path datadir{gArgs.GetPathArg("-datadir")};
+ return datadir.empty() || fs::is_directory(fs::absolute(datadir));
}
fs::path GetConfigFile(const std::string& confPath)
@@ -1064,13 +1062,9 @@ void ArgsManager::LogArgs() const
bool RenameOver(fs::path src, fs::path dest)
{
-#ifdef WIN32
- return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
- MOVEFILE_REPLACE_EXISTING) != 0;
-#else
- int rc = std::rename(src.c_str(), dest.c_str());
- return (rc == 0);
-#endif /* WIN32 */
+ std::error_code error;
+ fs::rename(src, dest, error);
+ return !error;
}
/**
diff --git a/src/util/system.h b/src/util/system.h
index a8fd21fcaa..a72ba3f3ed 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -69,7 +69,13 @@ void DirectoryCommit(const fs::path &dirname);
bool TruncateFile(FILE *file, unsigned int length);
int RaiseFileDescriptorLimit(int nMinFD);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
+
+/**
+ * Rename src to dest.
+ * @return true if the rename was successful.
+ */
[[nodiscard]] bool RenameOver(fs::path src, fs::path dest);
+
bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name);
bool DirIsWritable(const fs::path& directory);
@@ -265,6 +271,16 @@ protected:
std::optional<const Command> GetCommand() const;
/**
+ * Get a normalized path from a specified pathlike argument
+ *
+ * It is guaranteed that the returned path has no trailing slashes.
+ *
+ * @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
+ * @return Normalized path which is get from a specified pathlike argument
+ */
+ fs::path GetPathArg(std::string pathlike_arg) const;
+
+ /**
* Get blocks directory path
*
* @return Blocks path which is network specific
diff --git a/src/validation.cpp b/src/validation.cpp
index c12dc9e8b6..e20e2fe523 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1787,8 +1787,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
error("DisconnectBlock(): transaction and undo data inconsistent");
return DISCONNECT_FAILED;
}
- for (unsigned int j = tx.vin.size(); j-- > 0;) {
- const COutPoint &out = tx.vin[j].prevout;
+ for (unsigned int j = tx.vin.size(); j > 0;) {
+ --j;
+ const COutPoint& out = tx.vin[j].prevout;
int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out);
if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
fClean = fClean && res != DISCONNECT_UNCLEAN;
@@ -4493,7 +4494,8 @@ bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mocka
}
uint64_t num;
file >> num;
- while (num--) {
+ while (num) {
+ --num;
CTransactionRef tx;
int64_t nTime;
int64_t nFeeDelta;
diff --git a/src/validation.h b/src/validation.h
index fb258005f1..fdfd29d1f8 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -597,7 +597,8 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Import blocks from an external file */
- void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr);
+ void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
+ EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);
/**
* Update the on-disk chain state.
@@ -639,7 +640,9 @@ public:
*/
bool ActivateBestChain(
BlockValidationState& state,
- std::shared_ptr<const CBlock> pblock = nullptr) LOCKS_EXCLUDED(m_chainstate_mutex, cs_main);
+ std::shared_ptr<const CBlock> pblock = nullptr)
+ EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
+ LOCKS_EXCLUDED(::cs_main);
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -657,9 +660,15 @@ public:
*
* May not be called in a validationinterface callback.
*/
- bool PreciousBlock(BlockValidationState& state, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
+ bool PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
+ EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
+ LOCKS_EXCLUDED(::cs_main);
+
/** Mark a block as invalid. */
- bool InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex) LOCKS_EXCLUDED(m_chainstate_mutex, cs_main);
+ bool InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
+ EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
+ LOCKS_EXCLUDED(::cs_main);
+
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 6a74f2eb84..633d8c5450 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -28,7 +28,7 @@ bool VerifyWallets(WalletContext& context)
ArgsManager& args = *Assert(context.args);
if (args.IsArgSet("-walletdir")) {
- fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", ""));
+ const fs::path wallet_dir{args.GetPathArg("-walletdir")};
std::error_code error;
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
// It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 33ec715b51..883a3c102b 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -57,6 +57,7 @@ static RPCHelpMan getwalletinfo()
{RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
}},
{RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
+ {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
}},
},
RPCExamples{
@@ -117,6 +118,7 @@ static RPCHelpMan getwalletinfo()
obj.pushKV("scanning", false);
}
obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
+ obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
return obj;
},
};
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
index c1cae5c5f6..7fdecc5642 100644
--- a/src/wallet/test/init_tests.cpp
+++ b/src/wallet/test/init_tests.cpp
@@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
SetWalletDir(m_walletdir_path_cases["default"]);
bool result = m_wallet_loader->verify();
BOOST_CHECK(result == true);
- fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
+ fs::path walletdir = gArgs.GetPathArg("-walletdir");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
SetWalletDir(m_walletdir_path_cases["custom"]);
bool result = m_wallet_loader->verify();
BOOST_CHECK(result == true);
- fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
+ fs::path walletdir = gArgs.GetPathArg("-walletdir");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}
@@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
SetWalletDir(m_walletdir_path_cases["trailing"]);
bool result = m_wallet_loader->verify();
BOOST_CHECK(result == true);
- fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
+ fs::path walletdir = gArgs.GetPathArg("-walletdir");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
SetWalletDir(m_walletdir_path_cases["trailing2"]);
bool result = m_wallet_loader->verify();
BOOST_CHECK(result == true);
- fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
+ fs::path walletdir = gArgs.GetPathArg("-walletdir");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
BOOST_CHECK_EQUAL(walletdir, expected_path);
}
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index ce276451c3..df1b10a634 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -13,7 +13,7 @@ fs::path GetWalletDir()
fs::path path;
if (gArgs.IsArgSet("-walletdir")) {
- path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
+ path = gArgs.GetPathArg("-walletdir");
if (!fs::is_directory(path)) {
// If the path specified doesn't exist, we return the deliberately
// invalid empty string.