aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md16
-rw-r--r--configure.ac2
-rw-r--r--contrib/guix/libexec/prelude.bash2
-rw-r--r--src/addrdb.cpp3
-rw-r--r--src/bitcoin-cli.cpp14
-rw-r--r--src/blockencodings.cpp2
-rw-r--r--src/common/bloom.cpp2
-rw-r--r--src/index/base.cpp10
-rw-r--r--src/init.cpp4
-rw-r--r--src/net.cpp8
-rw-r--r--src/net.h6
-rw-r--r--src/net_processing.cpp8
-rw-r--r--src/netaddress.h4
-rw-r--r--src/qt/test/addressbooktests.cpp15
-rw-r--r--src/qt/walletmodel.cpp16
-rw-r--r--src/qt/walletmodel.h16
-rw-r--r--src/random.cpp7
-rw-r--r--src/random.h24
-rw-r--r--src/rpc/blockchain.cpp6
-rw-r--r--src/scheduler.cpp16
-rw-r--r--src/scheduler.h10
-rw-r--r--src/test/fuzz/fuzz.cpp6
-rw-r--r--src/test/random_tests.cpp18
-rw-r--r--src/test/scheduler_tests.cpp28
-rw-r--r--src/test/util_tests.cpp15
-rw-r--r--src/util/bytevectorhash.cpp6
-rw-r--r--src/util/hasher.cpp6
-rw-r--r--src/util/time.cpp5
-rw-r--r--src/util/time.h26
-rw-r--r--src/validation.cpp6
-rw-r--r--src/wallet/bdb.cpp4
-rw-r--r--src/wallet/bdb.h4
-rw-r--r--src/wallet/wallet.cpp13
-rwxr-xr-xtest/functional/interface_rest.py3
-rwxr-xr-xtest/functional/p2p_message_capture.py6
-rwxr-xr-xtest/functional/rpc_dumptxoutset.py6
-rwxr-xr-xtest/functional/test_runner.py10
37 files changed, 206 insertions, 147 deletions
diff --git a/README.md b/README.md
index 56132d7496..2eab2315eb 100644
--- a/README.md
+++ b/README.md
@@ -6,18 +6,14 @@ https://bitcoincore.org
For an immediately usable, binary version of the Bitcoin Core software, see
https://bitcoincore.org/en/download/.
-Further information about Bitcoin Core is available in the [doc folder](/doc).
-
-What is Bitcoin?
-----------------
+What is Bitcoin Core?
+---------------------
-Bitcoin is an experimental digital currency that enables instant payments to
-anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
-with no central authority: managing transactions and issuing money are carried
-out collectively by the network. Bitcoin Core is the name of open source
-software which enables the use of this currency.
+Bitcoin Core connects to the Bitcoin peer-to-peer network to download and fully
+validate blocks and transactions. It also includes a wallet and graphical user
+interface, which can be optionally built.
-For more information read the original Bitcoin whitepaper.
+Further information about Bitcoin Core is available in the [doc folder](/doc).
License
-------
diff --git a/configure.ac b/configure.ac
index 0539826edf..6dcc5183ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -470,6 +470,8 @@ fi
dnl Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review.
AX_CHECK_COMPILE_FLAG([-fno-extended-identifiers], [CORE_CXXFLAGS="$CORE_CXXFLAGS -fno-extended-identifiers"], [], [$CXXFLAG_WERROR])
+enable_arm_crc=no
+enable_arm_shani=no
enable_sse42=no
enable_sse41=no
enable_avx2=no
diff --git a/contrib/guix/libexec/prelude.bash b/contrib/guix/libexec/prelude.bash
index f24c120863..3eb8fc02da 100644
--- a/contrib/guix/libexec/prelude.bash
+++ b/contrib/guix/libexec/prelude.bash
@@ -51,7 +51,7 @@ fi
time-machine() {
# shellcheck disable=SC2086
guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \
- --commit=34e9eae68c9583acce5abc4100add3d88932a5ae \
+ --commit=998eda3067c7d21e0d9bb3310d2f5a14b8f1c681 \
--cores="$JOBS" \
--keep-failed \
--fallback \
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index b9eae292d7..31f8eadf98 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -49,8 +49,7 @@ template <typename Data>
bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data, int version)
{
// Generate random temporary filename
- uint16_t randv = 0;
- GetRandBytes({(unsigned char*)&randv, sizeof(randv)});
+ const uint16_t randv{GetRand<uint16_t>()};
std::string tmpfn = strprintf("%s.%04x", prefix, randv);
// open temp output file, and associate with CAutoFile
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index dea46693bc..88b0e86a36 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -9,23 +9,26 @@
#include <chainparamsbase.h>
#include <clientversion.h>
+#include <compat/stdin.h>
#include <policy/feerate.h>
#include <rpc/client.h>
#include <rpc/mining.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <tinyformat.h>
+#include <univalue.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <util/url.h>
#include <algorithm>
+#include <chrono>
#include <cmath>
+#include <cstdio>
#include <functional>
#include <memory>
#include <optional>
-#include <stdio.h>
#include <string>
#include <tuple>
@@ -37,8 +40,11 @@
#include <event2/keyvalq_struct.h>
#include <support/events.h>
-#include <univalue.h>
-#include <compat/stdin.h>
+// The server returns time values from a mockable system clock, but it is not
+// trivial to get the mocked time from the server, nor is it needed for now, so
+// just use a plain system_clock.
+using CliClock = std::chrono::system_clock;
+using CliSeconds = std::chrono::time_point<CliClock, std::chrono::seconds>;
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = urlDecode;
@@ -433,7 +439,7 @@ private:
if (conn_type == "addr-fetch") return "addr";
return "";
}
- const int64_t m_time_now{GetTimeSeconds()};
+ const int64_t m_time_now{count_seconds(Now<CliSeconds>())};
public:
static constexpr int ID_PEERINFO = 0;
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index aa111b5939..2a7bf9397c 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -17,7 +17,7 @@
#include <unordered_map>
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) :
- nonce(GetRand(std::numeric_limits<uint64_t>::max())),
+ nonce(GetRand<uint64_t>()),
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
FillShortTxIDSelector();
//TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
diff --git a/src/common/bloom.cpp b/src/common/bloom.cpp
index 8b32a6c94a..aa3fcf1ce2 100644
--- a/src/common/bloom.cpp
+++ b/src/common/bloom.cpp
@@ -239,7 +239,7 @@ bool CRollingBloomFilter::contains(Span<const unsigned char> vKey) const
void CRollingBloomFilter::reset()
{
- nTweak = GetRand(std::numeric_limits<unsigned int>::max());
+ nTweak = GetRand<unsigned int>();
nEntriesThisGeneration = 0;
nGeneration = 1;
std::fill(data.begin(), data.end(), 0);
diff --git a/src/index/base.cpp b/src/index/base.cpp
index f3c9395928..a00ae13e5c 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -18,8 +18,8 @@ using node::ReadBlockFromDisk;
constexpr uint8_t DB_BEST_BLOCK{'B'};
-constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds
-constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds
+constexpr auto SYNC_LOG_INTERVAL{30s};
+constexpr auto SYNC_LOCATOR_WRITE_INTERVAL{30s};
template <typename... Args>
static void FatalError(const char* fmt, const Args&... args)
@@ -130,8 +130,8 @@ void BaseIndex::ThreadSync()
if (!m_synced) {
auto& consensus_params = Params().GetConsensus();
- int64_t last_log_time = 0;
- int64_t last_locator_write_time = 0;
+ std::chrono::steady_clock::time_point last_log_time{0s};
+ std::chrono::steady_clock::time_point last_locator_write_time{0s};
while (true) {
if (m_interrupt) {
SetBestBlockIndex(pindex);
@@ -160,7 +160,7 @@ void BaseIndex::ThreadSync()
pindex = pindex_next;
}
- int64_t current_time = GetTime();
+ auto current_time{std::chrono::steady_clock::now()};
if (last_log_time + SYNC_LOG_INTERVAL < current_time) {
LogPrintf("Syncing %s with block chain from height %d\n",
GetName(), pindex->nHeight);
diff --git a/src/init.cpp b/src/init.cpp
index 1e16aee867..e180a2b5cd 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1280,8 +1280,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
assert(!node.banman);
node.banman = std::make_unique<BanMan>(gArgs.GetDataDirNet() / "banlist", &uiInterface, args.GetIntArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
- node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()),
- GetRand(std::numeric_limits<uint64_t>::max()),
+ node.connman = std::make_unique<CConnman>(GetRand<uint64_t>(),
+ GetRand<uint64_t>(),
*node.addrman, *node.netgroupman, args.GetBoolArg("-networkactive", true));
assert(!node.fee_estimator);
diff --git a/src/net.cpp b/src/net.cpp
index 46d7020c5e..1c775f9a3f 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1867,6 +1867,12 @@ void CConnman::SetTryNewOutboundPeer(bool flag)
LogPrint(BCLog::NET, "net: setting try another outbound peer=%s\n", flag ? "true" : "false");
}
+void CConnman::StartExtraBlockRelayPeers()
+{
+ LogPrint(BCLog::NET, "net: enabling extra block-relay-only peers\n");
+ m_start_extra_block_relay_peers = true;
+}
+
// Return the number of peers we have over our outbound connection limit
// Exclude peers that are marked for disconnect, or are going to be
// disconnected soon (eg ADDR_FETCH and FEELER)
@@ -2160,7 +2166,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
if (fFeeler) {
// Add small amount of random noise before connection to avoid synchronization.
- int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
+ int randsleep = GetRand<int>(FEELER_SLEEP_WINDOW * 1000);
if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep)))
return;
LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
diff --git a/src/net.h b/src/net.h
index 5cdddf1fee..c0081f2e56 100644
--- a/src/net.h
+++ b/src/net.h
@@ -13,7 +13,6 @@
#include <crypto/siphash.h>
#include <hash.h>
#include <i2p.h>
-#include <logging.h>
#include <net_permissions.h>
#include <netaddress.h>
#include <netbase.h>
@@ -857,10 +856,7 @@ public:
void SetTryNewOutboundPeer(bool flag);
bool GetTryNewOutboundPeer() const;
- void StartExtraBlockRelayPeers() {
- LogPrint(BCLog::NET, "net: enabling extra block-relay-only peers\n");
- m_start_extra_block_relay_peers = true;
- }
+ void StartExtraBlockRelayPeers();
// Return the number of outbound peers we have in excess of our target (eg,
// if we previously called SetTryNewOutboundPeer(true), and have since set
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 4b67704287..590ce8e839 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -4478,10 +4478,10 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic
}
if (pingSend) {
- uint64_t nonce = 0;
- while (nonce == 0) {
- GetRandBytes({(unsigned char*)&nonce, sizeof(nonce)});
- }
+ uint64_t nonce;
+ do {
+ nonce = GetRand<uint64_t>();
+ } while (nonce == 0);
peer.m_ping_queued = false;
peer.m_ping_start = now;
if (node_to.GetCommonVersion() > BIP0031_VERSION) {
diff --git a/src/netaddress.h b/src/netaddress.h
index b9a8dc589a..77e6171054 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -556,8 +556,8 @@ class CServiceHash
{
public:
CServiceHash()
- : m_salt_k0{GetRand(std::numeric_limits<uint64_t>::max())},
- m_salt_k1{GetRand(std::numeric_limits<uint64_t>::max())}
+ : m_salt_k0{GetRand<uint64_t>()},
+ m_salt_k1{GetRand<uint64_t>()}
{
}
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 66637a5dcf..ba0e4c686f 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <interfaces/node.h>
+#include <qt/addressbookpage.h>
#include <qt/clientmodel.h>
#include <qt/editaddressdialog.h>
#include <qt/optionsmodel.h>
@@ -23,8 +24,9 @@
#include <chrono>
#include <QApplication>
-#include <QTimer>
#include <QMessageBox>
+#include <QTableView>
+#include <QTimer>
using wallet::AddWallet;
using wallet::CWallet;
@@ -131,14 +133,19 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
+ AddressBookPage address_book{platformStyle.get(), AddressBookPage::ForEditing, AddressBookPage::SendingTab};
+ address_book.setModel(walletModel.getAddressTableModel());
+ auto table_view = address_book.findChild<QTableView*>("tableView");
+ QCOMPARE(table_view->model()->rowCount(), 1);
+
EditAddressAndSubmit(
&editAddressDialog, QString("uhoh"), preexisting_r_address,
QString(
"Address \"%1\" already exists as a receiving address with label "
"\"%2\" and so cannot be added as a sending address."
).arg(preexisting_r_address).arg(r_label));
-
check_addbook_size(2);
+ QCOMPARE(table_view->model()->rowCount(), 1);
EditAddressAndSubmit(
&editAddressDialog, QString("uhoh, different"), preexisting_s_address,
@@ -146,15 +153,15 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
"The entered address \"%1\" is already in the address book with "
"label \"%2\"."
).arg(preexisting_s_address).arg(s_label));
-
check_addbook_size(2);
+ QCOMPARE(table_view->model()->rowCount(), 1);
// Submit a new address which should add successfully - we expect the
// warning message to be blank.
EditAddressAndSubmit(
&editAddressDialog, QString("new"), new_address, QString(""));
-
check_addbook_size(3);
+ QCOMPARE(table_view->model()->rowCount(), 2);
}
} // namespace
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 5ee32e79d5..1f6c90af4a 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -145,7 +145,7 @@ void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
}
-bool WalletModel::validateAddress(const QString &address)
+bool WalletModel::validateAddress(const QString& address) const
{
return IsValidDestinationString(address.toStdString());
}
@@ -284,22 +284,22 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
return SendCoinsReturn(OK);
}
-OptionsModel *WalletModel::getOptionsModel()
+OptionsModel* WalletModel::getOptionsModel() const
{
return optionsModel;
}
-AddressTableModel *WalletModel::getAddressTableModel()
+AddressTableModel* WalletModel::getAddressTableModel() const
{
return addressTableModel;
}
-TransactionTableModel *WalletModel::getTransactionTableModel()
+TransactionTableModel* WalletModel::getTransactionTableModel() const
{
return transactionTableModel;
}
-RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel()
+RecentRequestsTableModel* WalletModel::getRecentRequestsTableModel() const
{
return recentRequestsTableModel;
}
@@ -369,7 +369,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel,
QString strPurpose = QString::fromStdString(purpose);
qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
- bool invoked = QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
+ bool invoked = QMetaObject::invokeMethod(walletmodel, "updateAddressBook",
Q_ARG(QString, strAddress),
Q_ARG(QString, strLabel),
Q_ARG(bool, isMine),
@@ -557,7 +557,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
return true;
}
-bool WalletModel::displayAddress(std::string sAddress)
+bool WalletModel::displayAddress(std::string sAddress) const
{
CTxDestination dest = DecodeDestination(sAddress);
bool res = false;
@@ -585,7 +585,7 @@ QString WalletModel::getDisplayName() const
return name.isEmpty() ? "["+tr("default wallet")+"]" : name;
}
-bool WalletModel::isMultiwallet()
+bool WalletModel::isMultiwallet() const
{
return m_node.walletLoader().getWallets().size() > 1;
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index ad1239ccdc..540fdaafe3 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -77,15 +77,15 @@ public:
Unlocked // wallet->IsCrypted() && !wallet->IsLocked()
};
- OptionsModel *getOptionsModel();
- AddressTableModel *getAddressTableModel();
- TransactionTableModel *getTransactionTableModel();
- RecentRequestsTableModel *getRecentRequestsTableModel();
+ OptionsModel* getOptionsModel() const;
+ AddressTableModel* getAddressTableModel() const;
+ TransactionTableModel* getTransactionTableModel() const;
+ RecentRequestsTableModel* getRecentRequestsTableModel() const;
EncryptionStatus getEncryptionStatus() const;
// Check address for validity
- bool validateAddress(const QString &address);
+ bool validateAddress(const QString& address) const;
// Return status record for SendCoins, contains error id + information
struct SendCoinsReturn
@@ -137,7 +137,7 @@ public:
UnlockContext requestUnlock();
bool bumpFee(uint256 hash, uint256& new_hash);
- bool displayAddress(std::string sAddress);
+ bool displayAddress(std::string sAddress) const;
static bool isWalletEnabled();
@@ -149,9 +149,7 @@ public:
QString getWalletName() const;
QString getDisplayName() const;
- bool isMultiwallet();
-
- AddressTableModel* getAddressTableModel() const { return addressTableModel; }
+ bool isMultiwallet() const;
void refresh(bool pk_hash_only = false);
diff --git a/src/random.cpp b/src/random.cpp
index 6ae08103b1..ad8568bef0 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -586,16 +586,11 @@ void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(e
bool g_mock_deterministic_tests{false};
-uint64_t GetRand(uint64_t nMax) noexcept
+uint64_t GetRandInternal(uint64_t nMax) noexcept
{
return FastRandomContext(g_mock_deterministic_tests).randrange(nMax);
}
-int GetRandInt(int nMax) noexcept
-{
- return GetRand(nMax);
-}
-
uint256 GetRandHash() noexcept
{
uint256 hash;
diff --git a/src/random.h b/src/random.h
index 285158b1c3..b92c29f0be 100644
--- a/src/random.h
+++ b/src/random.h
@@ -69,7 +69,17 @@
*/
void GetRandBytes(Span<unsigned char> bytes) noexcept;
/** Generate a uniform random integer in the range [0..range). Precondition: range > 0 */
-uint64_t GetRand(uint64_t nMax) noexcept;
+uint64_t GetRandInternal(uint64_t nMax) noexcept;
+/** Generate a uniform random integer of type T in the range [0..nMax)
+ * nMax defaults to std::numeric_limits<T>::max()
+ * Precondition: nMax > 0, T is an integral type, no larger than uint64_t
+ */
+template<typename T>
+T GetRand(T nMax=std::numeric_limits<T>::max()) noexcept {
+ static_assert(std::is_integral<T>(), "T must be integral");
+ static_assert(std::numeric_limits<T>::max() <= std::numeric_limits<uint64_t>::max(), "GetRand only supports up to uint64_t");
+ return T(GetRandInternal(nMax));
+}
/** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */
template <typename D>
D GetRandomDuration(typename std::common_type<D>::type max) noexcept
@@ -95,7 +105,6 @@ constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
* */
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval);
-int GetRandInt(int nMax) noexcept;
uint256 GetRandHash() noexcept;
/**
@@ -223,6 +232,17 @@ public:
/** Generate a random boolean. */
bool randbool() noexcept { return randbits(1); }
+ /** Return the time point advanced by a uniform random duration. */
+ template <typename Tp>
+ Tp rand_uniform_delay(const Tp& time, typename Tp::duration range)
+ {
+ using Dur = typename Tp::duration;
+ Dur dur{range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} :
+ range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} :
+ /* interval [0..0] */ Dur{0}};
+ return time + dur;
+ }
+
// Compatibility with the C++11 UniformRandomBitGenerator concept
typedef uint64_t result_type;
static constexpr uint64_t min() { return 0; }
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index dfc286b484..cd06a84930 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2278,6 +2278,12 @@ static RPCHelpMan dumptxoutset()
FILE* file{fsbridge::fopen(temppath, "wb")};
CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
+ if (afile.IsNull()) {
+ throw JSONRPCError(
+ RPC_INVALID_PARAMETER,
+ "Couldn't open file " + temppath.u8string() + " for writing.");
+ }
+
NodeContext& node = EnsureAnyNodeContext(request.context);
UniValue result = CreateUTXOSnapshot(
node, node.chainman->ActiveChainstate(), afile, path, temppath);
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index 3e7ee7d370..570b417ff5 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -4,11 +4,11 @@
#include <scheduler.h>
-#include <random.h>
+#include <sync.h>
#include <util/syscall_sandbox.h>
#include <util/time.h>
-#include <assert.h>
+#include <cassert>
#include <functional>
#include <utility>
@@ -43,7 +43,7 @@ void CScheduler::serviceQueue()
// the time of the first item on the queue:
while (!shouldStop() && !taskQueue.empty()) {
- std::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
+ std::chrono::steady_clock::time_point timeToWaitFor = taskQueue.begin()->first;
if (newTaskScheduled.wait_until(lock, timeToWaitFor) == std::cv_status::timeout) {
break; // Exit loop after timeout, it means we reached the time of the event
}
@@ -72,7 +72,7 @@ void CScheduler::serviceQueue()
newTaskScheduled.notify_one();
}
-void CScheduler::schedule(CScheduler::Function f, std::chrono::system_clock::time_point t)
+void CScheduler::schedule(CScheduler::Function f, std::chrono::steady_clock::time_point t)
{
{
LOCK(newTaskMutex);
@@ -89,7 +89,7 @@ void CScheduler::MockForward(std::chrono::seconds delta_seconds)
LOCK(newTaskMutex);
// use temp_queue to maintain updated schedule
- std::multimap<std::chrono::system_clock::time_point, Function> temp_queue;
+ std::multimap<std::chrono::steady_clock::time_point, Function> temp_queue;
for (const auto& element : taskQueue) {
temp_queue.emplace_hint(temp_queue.cend(), element.first - delta_seconds, element.second);
@@ -114,8 +114,8 @@ void CScheduler::scheduleEvery(CScheduler::Function f, std::chrono::milliseconds
scheduleFromNow([this, f, delta] { Repeat(*this, f, delta); }, delta);
}
-size_t CScheduler::getQueueInfo(std::chrono::system_clock::time_point& first,
- std::chrono::system_clock::time_point& last) const
+size_t CScheduler::getQueueInfo(std::chrono::steady_clock::time_point& first,
+ std::chrono::steady_clock::time_point& last) const
{
LOCK(newTaskMutex);
size_t result = taskQueue.size();
@@ -143,7 +143,7 @@ void SingleThreadedSchedulerClient::MaybeScheduleProcessQueue()
if (m_are_callbacks_running) return;
if (m_callbacks_pending.empty()) return;
}
- m_scheduler.schedule([this] { this->ProcessQueue(); }, std::chrono::system_clock::now());
+ m_scheduler.schedule([this] { this->ProcessQueue(); }, std::chrono::steady_clock::now());
}
void SingleThreadedSchedulerClient::ProcessQueue()
diff --git a/src/scheduler.h b/src/scheduler.h
index eb350e4bc3..b8245f97ed 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -46,12 +46,12 @@ public:
typedef std::function<void()> Function;
/** Call func at/after time t */
- void schedule(Function f, std::chrono::system_clock::time_point t);
+ void schedule(Function f, std::chrono::steady_clock::time_point t);
/** Call f once after the delta has passed */
void scheduleFromNow(Function f, std::chrono::milliseconds delta)
{
- schedule(std::move(f), std::chrono::system_clock::now() + delta);
+ schedule(std::move(f), std::chrono::steady_clock::now() + delta);
}
/**
@@ -93,8 +93,8 @@ public:
* Returns number of tasks waiting to be serviced,
* and first and last task times
*/
- size_t getQueueInfo(std::chrono::system_clock::time_point& first,
- std::chrono::system_clock::time_point& last) const;
+ size_t getQueueInfo(std::chrono::steady_clock::time_point& first,
+ std::chrono::steady_clock::time_point& last) const;
/** Returns true if there are threads actively running in serviceQueue() */
bool AreThreadsServicingQueue() const;
@@ -102,7 +102,7 @@ public:
private:
mutable Mutex newTaskMutex;
std::condition_variable newTaskScheduled;
- std::multimap<std::chrono::system_clock::time_point, Function> taskQueue GUARDED_BY(newTaskMutex);
+ std::multimap<std::chrono::steady_clock::time_point, Function> taskQueue GUARDED_BY(newTaskMutex);
int nThreadsServicingQueue GUARDED_BY(newTaskMutex){0};
bool stopRequested GUARDED_BY(newTaskMutex){false};
bool stopWhenEmpty GUARDED_BY(newTaskMutex){false};
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 59adec075e..24ae34bd9e 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -194,7 +194,7 @@ int main(int argc, char** argv)
return 0;
}
std::signal(SIGABRT, signal_handler);
- int64_t start_time = GetTimeSeconds();
+ const auto start_time{Now<SteadySeconds>()};
int tested = 0;
for (int i = 1; i < argc; ++i) {
fs::path input_path(*(argv + i));
@@ -215,8 +215,8 @@ int main(int argc, char** argv)
buffer.clear();
}
}
- int64_t end_time = GetTimeSeconds();
- std::cout << g_fuzz_target << ": succeeded against " << tested << " files in " << (end_time - start_time) << "s." << std::endl;
+ const auto end_time{Now<SteadySeconds>()};
+ std::cout << g_fuzz_target << ": succeeded against " << tested << " files in " << count_seconds(end_time - start_time) << "s." << std::endl;
#endif
return 0;
}
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index 978a7bee4d..9b2760fd1c 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -26,11 +26,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
FastRandomContext ctx2(true);
for (int i = 10; i > 0; --i) {
- BOOST_CHECK_EQUAL(GetRand(std::numeric_limits<uint64_t>::max()), uint64_t{10393729187455219830U});
- BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits<int>::max()), int{769702006});
+ BOOST_CHECK_EQUAL(GetRand<uint64_t>(), uint64_t{10393729187455219830U});
+ BOOST_CHECK_EQUAL(GetRand<int>(), int{769702006});
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2917185654);
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2144374);
}
+ {
+ constexpr SteadySeconds time_point{1s};
+ FastRandomContext ctx{true};
+ BOOST_CHECK_EQUAL(7, ctx.rand_uniform_delay(time_point, 9s).time_since_epoch().count());
+ BOOST_CHECK_EQUAL(-6, ctx.rand_uniform_delay(time_point, -9s).time_since_epoch().count());
+ BOOST_CHECK_EQUAL(1, ctx.rand_uniform_delay(time_point, 0s).time_since_epoch().count());
+ BOOST_CHECK_EQUAL(1467825113502396065, ctx.rand_uniform_delay(time_point, 9223372036854775807s).time_since_epoch().count());
+ BOOST_CHECK_EQUAL(-970181367944767837, ctx.rand_uniform_delay(time_point, -9223372036854775807s).time_since_epoch().count());
+ BOOST_CHECK_EQUAL(24761, ctx.rand_uniform_delay(time_point, 9h).time_since_epoch().count());
+ }
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64());
@@ -47,8 +57,8 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
// Check that a nondeterministic ones are not
g_mock_deterministic_tests = false;
for (int i = 10; i > 0; --i) {
- BOOST_CHECK(GetRand(std::numeric_limits<uint64_t>::max()) != uint64_t{10393729187455219830U});
- BOOST_CHECK(GetRandInt(std::numeric_limits<int>::max()) != int{769702006});
+ BOOST_CHECK(GetRand<uint64_t>() != uint64_t{10393729187455219830U});
+ BOOST_CHECK(GetRand<int>() != int{769702006});
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}) != std::chrono::microseconds{2917185654});
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}) != std::chrono::milliseconds{2144374});
}
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index 6e089de0c1..7b5dda8114 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -15,13 +15,13 @@
BOOST_AUTO_TEST_SUITE(scheduler_tests)
-static void microTask(CScheduler& s, std::mutex& mutex, int& counter, int delta, std::chrono::system_clock::time_point rescheduleTime)
+static void microTask(CScheduler& s, std::mutex& mutex, int& counter, int delta, std::chrono::steady_clock::time_point rescheduleTime)
{
{
std::lock_guard<std::mutex> lock(mutex);
counter += delta;
}
- std::chrono::system_clock::time_point noTime = std::chrono::system_clock::time_point::min();
+ auto noTime = std::chrono::steady_clock::time_point::min();
if (rescheduleTime != noTime) {
CScheduler::Function f = std::bind(&microTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime);
s.schedule(f, rescheduleTime);
@@ -49,15 +49,15 @@ BOOST_AUTO_TEST_CASE(manythreads)
auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]
- std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
- std::chrono::system_clock::time_point now = start;
- std::chrono::system_clock::time_point first, last;
+ auto start = std::chrono::steady_clock::now();
+ auto now = start;
+ std::chrono::steady_clock::time_point first, last;
size_t nTasks = microTasks.getQueueInfo(first, last);
BOOST_CHECK(nTasks == 0);
for (int i = 0; i < 100; ++i) {
- std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
- std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
+ auto t = now + std::chrono::microseconds(randomMsec(rng));
+ auto tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
@@ -75,14 +75,14 @@ BOOST_AUTO_TEST_CASE(manythreads)
microThreads.emplace_back(std::bind(&CScheduler::serviceQueue, &microTasks));
UninterruptibleSleep(std::chrono::microseconds{600});
- now = std::chrono::system_clock::now();
+ now = std::chrono::steady_clock::now();
// More threads and more tasks:
for (int i = 0; i < 5; i++)
microThreads.emplace_back(std::bind(&CScheduler::serviceQueue, &microTasks));
for (int i = 0; i < 100; i++) {
- std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
- std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
+ auto t = now + std::chrono::microseconds(randomMsec(rng));
+ auto tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
@@ -111,8 +111,8 @@ BOOST_AUTO_TEST_CASE(wait_until_past)
Mutex mtx;
WAIT_LOCK(mtx, lock);
- const auto no_wait= [&](const std::chrono::seconds& d) {
- return condvar.wait_until(lock, std::chrono::system_clock::now() - d);
+ const auto no_wait = [&](const std::chrono::seconds& d) {
+ return condvar.wait_until(lock, std::chrono::steady_clock::now() - d);
};
BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::seconds{1}));
@@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(mockforward)
scheduler.scheduleFromNow(dummy, std::chrono::minutes{8});
// check taskQueue
- std::chrono::system_clock::time_point first, last;
+ std::chrono::steady_clock::time_point first, last;
size_t num_tasks = scheduler.getQueueInfo(first, last);
BOOST_CHECK_EQUAL(num_tasks, 3ul);
@@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(mockforward)
BOOST_CHECK_EQUAL(counter, 2);
// check that the time of the remaining job has been updated
- std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+ auto now = std::chrono::steady_clock::now();
int delta = std::chrono::duration_cast<std::chrono::seconds>(first - now).count();
// should be between 2 & 3 minutes from now
BOOST_CHECK(delta > 2*60 && delta < 3*60);
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 3b2aca5887..882ad7d424 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -265,9 +265,6 @@ BOOST_AUTO_TEST_CASE(util_FormatParseISO8601DateTime)
BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:00Z"), 0);
BOOST_CHECK_EQUAL(ParseISO8601DateTime("1960-01-01T00:00:00Z"), 0);
BOOST_CHECK_EQUAL(ParseISO8601DateTime("2011-09-30T23:36:17Z"), 1317425777);
-
- auto time = GetTimeSeconds();
- BOOST_CHECK_EQUAL(ParseISO8601DateTime(FormatISO8601DateTime(time)), time);
}
BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
@@ -1488,8 +1485,8 @@ BOOST_AUTO_TEST_CASE(util_time_GetTime)
{
SetMockTime(111);
// Check that mock time does not change after a sleep
- for (const auto& num_sleep : {0, 1}) {
- UninterruptibleSleep(std::chrono::milliseconds{num_sleep});
+ for (const auto& num_sleep : {0ms, 1ms}) {
+ UninterruptibleSleep(num_sleep);
BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
@@ -1497,10 +1494,14 @@ BOOST_AUTO_TEST_CASE(util_time_GetTime)
}
SetMockTime(0);
- // Check that system time changes after a sleep
+ // Check that steady time and system time changes after a sleep
+ const auto steady_ms_0 = Now<SteadyMilliseconds>();
+ const auto steady_0 = std::chrono::steady_clock::now();
const auto ms_0 = GetTime<std::chrono::milliseconds>();
const auto us_0 = GetTime<std::chrono::microseconds>();
- UninterruptibleSleep(std::chrono::milliseconds{1});
+ UninterruptibleSleep(1ms);
+ BOOST_CHECK(steady_ms_0 < Now<SteadyMilliseconds>());
+ BOOST_CHECK(steady_0 + 1ms <= std::chrono::steady_clock::now());
BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
}
diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
index bc060a44c9..9054db4759 100644
--- a/src/util/bytevectorhash.cpp
+++ b/src/util/bytevectorhash.cpp
@@ -6,10 +6,10 @@
#include <random.h>
#include <util/bytevectorhash.h>
-ByteVectorHash::ByteVectorHash()
+ByteVectorHash::ByteVectorHash() :
+ m_k0(GetRand<uint64_t>()),
+ m_k1(GetRand<uint64_t>())
{
- GetRandBytes({reinterpret_cast<unsigned char*>(&m_k0), sizeof(m_k0)});
- GetRandBytes({reinterpret_cast<unsigned char*>(&m_k1), sizeof(m_k1)});
}
size_t ByteVectorHash::operator()(const std::vector<unsigned char>& input) const
diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp
index 5900daf050..c21941eb88 100644
--- a/src/util/hasher.cpp
+++ b/src/util/hasher.cpp
@@ -7,11 +7,11 @@
#include <limits>
-SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
+SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {}
-SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
+SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {}
-SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand(std::numeric_limits<uint64_t>::max())), m_k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
+SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand<uint64_t>()), m_k1(GetRand<uint64_t>()) {}
size_t SaltedSipHasher::operator()(const Span<const unsigned char>& script) const
{
diff --git a/src/util/time.cpp b/src/util/time.cpp
index e428430bac..4ec44509ab 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -115,11 +115,6 @@ int64_t GetTimeMicros()
return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
}
-int64_t GetTimeSeconds()
-{
- return int64_t{GetSystemTime<std::chrono::seconds>().count()};
-}
-
int64_t GetTime() { return GetTime<std::chrono::seconds>().count(); }
std::string FormatISO8601DateTime(int64_t nTime) {
diff --git a/src/util/time.h b/src/util/time.h
index 9d92b23725..72956ea0d7 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -14,18 +14,27 @@
using namespace std::chrono_literals;
+using SteadySeconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::seconds>;
+using SteadyMilliseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds>;
+using SteadyMicroseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>;
+
void UninterruptibleSleep(const std::chrono::microseconds& n);
/**
- * Helper to count the seconds of a duration.
+ * Helper to count the seconds of a duration/time_point.
*
- * All durations should be using std::chrono and calling this should generally
+ * All durations/time_points should be using std::chrono and calling this should generally
* be avoided in code. Though, it is still preferred to an inline t.count() to
* protect against a reliance on the exact type of t.
*
- * This helper is used to convert durations before passing them over an
+ * This helper is used to convert durations/time_points before passing them over an
* interface that doesn't support std::chrono (e.g. RPC, debug log, or the GUI)
*/
+template <typename Clock>
+constexpr int64_t count_seconds(std::chrono::time_point<Clock, std::chrono::seconds> t)
+{
+ return t.time_since_epoch().count();
+}
constexpr int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
constexpr int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); }
constexpr int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); }
@@ -47,8 +56,6 @@ int64_t GetTime();
int64_t GetTimeMillis();
/** Returns the system time (not mockable) */
int64_t GetTimeMicros();
-/** Returns the system time (not mockable) */
-int64_t GetTimeSeconds(); // Like GetTime(), but not mockable
/**
* DEPRECATED
@@ -67,6 +74,15 @@ std::chrono::seconds GetMockTime();
/** Return system time (or mocked time, if set) */
template <typename T>
T GetTime();
+/**
+ * Return the current time point cast to the given precicion. Only use this
+ * when an exact precicion is needed, otherwise use T::clock::now() directly.
+ */
+template <typename T>
+T Now()
+{
+ return std::chrono::time_point_cast<typename T::duration>(T::clock::now());
+}
/**
* ISO 8601 formatting is preferred. Use the FormatISO8601{DateTime,Date}
diff --git a/src/validation.cpp b/src/validation.cpp
index 63c0f9a4ac..51d77b7945 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2455,9 +2455,9 @@ bool CChainState::FlushStateToDisk(
full_flush_completed = true;
TRACE5(utxocache, flush,
(int64_t)(GetTimeMicros() - nNow.count()), // in microseconds (µs)
- (u_int32_t)mode,
- (u_int64_t)coins_count,
- (u_int64_t)coins_mem_usage,
+ (uint32_t)mode,
+ (uint64_t)coins_count,
+ (uint64_t)coins_mem_usage,
(bool)fFlushForPrune);
}
}
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index 1aa0339445..f8230f7a1d 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -99,7 +99,7 @@ void BerkeleyEnvironment::Close()
if (ret != 0)
LogPrintf("BerkeleyEnvironment::Close: Error %d closing database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
- DbEnv((u_int32_t)0).remove(strPath.c_str(), 0);
+ DbEnv((uint32_t)0).remove(strPath.c_str(), 0);
if (error_file) fclose(error_file);
@@ -248,7 +248,7 @@ const void* BerkeleyBatch::SafeDbt::get_data() const
return m_dbt.get_data();
}
-u_int32_t BerkeleyBatch::SafeDbt::get_size() const
+uint32_t BerkeleyBatch::SafeDbt::get_size() const
{
return m_dbt.get_size();
}
diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h
index 1c99e1f9af..ddab85521b 100644
--- a/src/wallet/bdb.h
+++ b/src/wallet/bdb.h
@@ -34,7 +34,7 @@ struct bilingual_str;
namespace wallet {
struct WalletDatabaseFileId {
- u_int8_t value[DB_FILE_ID_LEN];
+ uint8_t value[DB_FILE_ID_LEN];
bool operator==(const WalletDatabaseFileId& rhs) const;
};
@@ -182,7 +182,7 @@ class BerkeleyBatch : public DatabaseBatch
// delegate to Dbt
const void* get_data() const;
- u_int32_t get_size() const;
+ uint32_t get_size() const;
// conversion operator to access the underlying Dbt
operator Dbt*();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 356d0ce5a0..5a23f739d3 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1707,8 +1707,10 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
*/
CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
{
- int64_t nNow = GetTime();
- int64_t start_time = GetTimeMillis();
+ using Clock = std::chrono::steady_clock;
+ constexpr auto LOG_INTERVAL{60s};
+ auto current_time{Clock::now()};
+ auto start_time{Clock::now()};
assert(reserver.isReserved());
@@ -1735,8 +1737,8 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
}
- if (GetTime() >= nNow + 60) {
- nNow = GetTime();
+ if (Clock::now() >= current_time + LOG_INTERVAL) {
+ current_time = Clock::now();
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
@@ -1803,7 +1805,8 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
result.status = ScanResult::USER_ABORT;
} else {
- WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
+ auto duration_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - start_time);
+ WalletLogPrintf("Rescan completed in %15dms\n", duration_milliseconds.count());
}
return result;
}
diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py
index 2c158e37e7..f36bbda3af 100755
--- a/test/functional/interface_rest.py
+++ b/test/functional/interface_rest.py
@@ -330,6 +330,9 @@ class RESTTest (BitcoinTestFramework):
# the size of the memory pool should be greater than 3x ~100 bytes
assert_greater_than(json_obj['bytes'], 300)
+ mempool_info = self.nodes[0].getmempoolinfo()
+ assert_equal(json_obj, mempool_info)
+
# Check that there are our submitted transactions in the TX memory pool
json_obj = self.test_rest_request("/mempool/contents")
raw_mempool_verbose = self.nodes[0].getrawmempool(verbose=True)
diff --git a/test/functional/p2p_message_capture.py b/test/functional/p2p_message_capture.py
index 0a7ae44de4..87c77f4540 100755
--- a/test/functional/p2p_message_capture.py
+++ b/test/functional/p2p_message_capture.py
@@ -43,12 +43,8 @@ def mini_parser(dat_file):
break
tmp_header = BytesIO(tmp_header_raw)
tmp_header.read(TIME_SIZE) # skip the timestamp field
- raw_msgtype = tmp_header.read(MSGTYPE_SIZE)
- msgtype: bytes = raw_msgtype.split(b'\x00', 1)[0]
- remainder = raw_msgtype.split(b'\x00', 1)[1]
- assert(len(msgtype) > 0)
+ msgtype = tmp_header.read(MSGTYPE_SIZE).rstrip(b'\x00')
assert(msgtype in MESSAGEMAP)
- assert(len(remainder) == 0 or not remainder.decode().isprintable())
length: int = int.from_bytes(tmp_header.read(LENGTH_SIZE), "little")
data = f_in.read(length)
assert_equal(len(data), length)
diff --git a/test/functional/rpc_dumptxoutset.py b/test/functional/rpc_dumptxoutset.py
index 4ca84748b2..672c9a53dc 100755
--- a/test/functional/rpc_dumptxoutset.py
+++ b/test/functional/rpc_dumptxoutset.py
@@ -49,9 +49,13 @@ class DumptxoutsetTest(BitcoinTestFramework):
out['txoutset_hash'], '1f7e3befd45dc13ae198dfbb22869a9c5c4196f8e9ef9735831af1288033f890')
assert_equal(out['nchaintx'], 101)
- # Specifying a path to an existing file will fail.
+ # Specifying a path to an existing or invalid file will fail.
assert_raises_rpc_error(
-8, '{} already exists'.format(FILENAME), node.dumptxoutset, FILENAME)
+ invalid_path = str(Path(node.datadir) / "invalid" / "path")
+ assert_raises_rpc_error(
+ -8, "Couldn't open file {}.incomplete for writing".format(invalid_path), node.dumptxoutset, invalid_path)
+
if __name__ == '__main__':
DumptxoutsetTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 7d6397d193..8416a5881d 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -28,7 +28,7 @@ import logging
import unittest
# Formatting. Default colors to empty strings.
-BOLD, GREEN, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
+DEFAULT, BOLD, GREEN, RED = ("", ""), ("", ""), ("", ""), ("", "")
try:
# Make sure python thinks it can write unicode to its stdout
"\u2713".encode("utf_8").decode(sys.stdout.encoding)
@@ -59,10 +59,10 @@ if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393): #type:ignore
kernel32.SetConsoleMode(stderr, stderr_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
# primitive formatting on supported
# terminal via ANSI escape sequences:
+ DEFAULT = ('\033[0m', '\033[0m')
BOLD = ('\033[0m', '\033[1m')
GREEN = ('\033[0m', '\033[0;32m')
RED = ('\033[0m', '\033[0;31m')
- GREY = ('\033[0m', '\033[1;30m')
TEST_EXIT_PASSED = 0
TEST_EXIT_SKIPPED = 77
@@ -372,11 +372,11 @@ def main():
args, unknown_args = parser.parse_known_args()
if not args.ansi:
- global BOLD, GREEN, RED, GREY
+ global DEFAULT, BOLD, GREEN, RED
+ DEFAULT = ("", "")
BOLD = ("", "")
GREEN = ("", "")
RED = ("", "")
- GREY = ("", "")
# args to be passed on always start with two dashes; tests are the remaining unknown args
tests = [arg for arg in unknown_args if arg[:2] != "--"]
@@ -720,7 +720,7 @@ class TestResult():
color = RED
glyph = CROSS
elif self.status == "Skipped":
- color = GREY
+ color = DEFAULT
glyph = CIRCLE
return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0]