aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am58
-rw-r--r--src/Makefile.qt.include43
-rw-r--r--src/bench/prevector.cpp4
-rw-r--r--src/blockencodings.h3
-rw-r--r--src/bloom.h10
-rw-r--r--src/flatfile.h8
-rw-r--r--src/httprpc.cpp6
-rw-r--r--src/httpserver.cpp6
-rw-r--r--src/index/blockfilterindex.cpp16
-rw-r--r--src/index/txindex.cpp10
-rw-r--r--src/init.cpp17
-rw-r--r--src/interfaces/node.cpp8
-rw-r--r--src/interfaces/node.h5
-rw-r--r--src/interfaces/wallet.cpp3
-rw-r--r--src/interfaces/wallet.h7
-rw-r--r--src/merkleblock.cpp18
-rw-r--r--src/merkleblock.h41
-rw-r--r--src/net_processing.cpp122
-rw-r--r--src/netaddress.h24
-rw-r--r--src/node/utxo_snapshot.h11
-rw-r--r--src/policy/feerate.h7
-rw-r--r--src/primitives/block.h30
-rw-r--r--src/primitives/transaction.h25
-rw-r--r--src/protocol.h118
-rw-r--r--src/qt/bitcoin.cpp3
-rw-r--r--src/qt/bitcoingui.cpp11
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/clientmodel.cpp37
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/transactiontablemodel.cpp2
-rw-r--r--src/qt/walletmodel.cpp33
-rw-r--r--src/qt/walletmodel.h6
-rw-r--r--src/qt/walletview.cpp1
-rw-r--r--src/random.cpp16
-rw-r--r--src/random.h16
-rw-r--r--src/rest.cpp9
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/rpc/blockchain.h2
-rw-r--r--src/rpc/mining.cpp14
-rw-r--r--src/script/keyorigin.h8
-rw-r--r--src/script/script.h7
-rw-r--r--src/serialize.h93
-rw-r--r--src/test/blockencodings_tests.cpp19
-rw-r--r--src/test/dbwrapper_tests.cpp36
-rw-r--r--src/test/fuzz/addrdb.cpp4
-rw-r--r--src/test/fuzz/asmap.cpp4
-rw-r--r--src/test/fuzz/asmap_direct.cpp6
-rw-r--r--src/test/fuzz/block.cpp5
-rw-r--r--src/test/fuzz/block_header.cpp12
-rw-r--r--src/test/fuzz/blockfilter.cpp4
-rw-r--r--src/test/fuzz/bloom_filter.cpp8
-rw-r--r--src/test/fuzz/chain.cpp4
-rw-r--r--src/test/fuzz/checkqueue.cpp1
-rw-r--r--src/test/fuzz/cuckoocache.cpp1
-rw-r--r--src/test/fuzz/fees.cpp1
-rw-r--r--src/test/fuzz/flatfile.cpp6
-rw-r--r--src/test/fuzz/golomb_rice.cpp2
-rw-r--r--src/test/fuzz/hex.cpp3
-rw-r--r--src/test/fuzz/merkleblock.cpp4
-rw-r--r--src/test/fuzz/message.cpp1
-rw-r--r--src/test/fuzz/net_permissions.cpp1
-rw-r--r--src/test/fuzz/policy_estimator.cpp6
-rw-r--r--src/test/fuzz/pow.cpp6
-rw-r--r--src/test/fuzz/prevector.cpp93
-rw-r--r--src/test/fuzz/primitives_transaction.cpp8
-rw-r--r--src/test/fuzz/protocol.cpp6
-rw-r--r--src/test/fuzz/rbf.cpp6
-rw-r--r--src/test/fuzz/rolling_bloom_filter.cpp4
-rw-r--r--src/test/fuzz/script.cpp9
-rw-r--r--src/test/fuzz/string.cpp6
-rw-r--r--src/test/fuzz/strprintf.cpp28
-rw-r--r--src/test/fuzz/util.h6
-rw-r--r--src/test/random_tests.cpp7
-rw-r--r--src/test/serialize_tests.cpp23
-rw-r--r--src/test/validation_block_tests.cpp14
-rw-r--r--src/test/validationinterface_tests.cpp34
-rw-r--r--src/txdb.cpp14
-rw-r--r--src/ui_interface.cpp4
-rw-r--r--src/ui_interface.h5
-rw-r--r--src/validation.cpp13
-rw-r--r--src/validation.h7
-rw-r--r--src/validationinterface.cpp35
-rw-r--r--src/validationinterface.h14
-rw-r--r--src/wallet/rpcwallet.cpp34
84 files changed, 700 insertions, 673 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d2c7400bbb..882d83e0b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,10 @@ if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
endif
+if BUILD_BITCOIN_NODE
+ bin_PROGRAMS += bitcoin-node
+endif
+
if BUILD_BITCOIN_CLI
bin_PROGRAMS += bitcoin-cli
endif
@@ -547,22 +551,21 @@ libbitcoin_cli_a_SOURCES = \
nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
#
-# bitcoind binary #
-bitcoind_SOURCES = bitcoind.cpp
-bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+# bitcoind & bitcoin-node binaries #
+bitcoin_daemon_sources = bitcoind.cpp
+bitcoin_bin_cppflags = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+bitcoin_bin_cxxflags = $(AM_CXXFLAGS) $(PIE_FLAGS)
+bitcoin_bin_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_WINDOWS
-bitcoind_SOURCES += bitcoind-res.rc
+bitcoin_daemon_sources += bitcoind-res.rc
endif
-bitcoind_LDADD = \
- $(LIBBITCOIN_SERVER) \
+bitcoin_bin_ldadd = \
$(LIBBITCOIN_WALLET) \
$(LIBBITCOIN_COMMON) \
- $(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \
+ $(LIBUNIVALUE) \
$(LIBBITCOIN_ZMQ) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
@@ -571,7 +574,19 @@ bitcoind_LDADD = \
$(LIBMEMENV) \
$(LIBSECP256K1)
-bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
+bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
+
+bitcoind_SOURCES = $(bitcoin_daemon_sources)
+bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags)
+bitcoind_CXXFLAGS = $(bitcoin_bin_cxxflags)
+bitcoind_LDFLAGS = $(bitcoin_bin_ldflags)
+bitcoind_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd)
+
+bitcoin_node_SOURCES = $(bitcoin_daemon_sources)
+bitcoin_node_CPPFLAGS = $(bitcoin_bin_cppflags)
+bitcoin_node_CXXFLAGS = $(bitcoin_bin_cxxflags)
+bitcoin_node_LDFLAGS = $(bitcoin_bin_ldflags)
+bitcoin_node_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd)
# bitcoin-cli binary #
bitcoin_cli_SOURCES = bitcoin-cli.cpp
@@ -615,29 +630,14 @@ bitcoin_tx_LDADD += $(BOOST_LIBS)
# bitcoin-wallet binary #
bitcoin_wallet_SOURCES = bitcoin-wallet.cpp
-bitcoin_wallet_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-bitcoin_wallet_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoin_wallet_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_wallet_CPPFLAGS = $(bitcoin_bin_cppflags)
+bitcoin_wallet_CXXFLAGS = $(bitcoin_bin_cxxflags)
+bitcoin_wallet_LDFLAGS = $(bitcoin_bin_ldflags)
+bitcoin_wallet_LDADD = $(LIBBITCOIN_WALLET_TOOL) $(bitcoin_bin_ldadd)
if TARGET_WINDOWS
bitcoin_wallet_SOURCES += bitcoin-wallet-res.rc
endif
-
-bitcoin_wallet_LDADD = \
- $(LIBBITCOIN_WALLET_TOOL) \
- $(LIBBITCOIN_WALLET) \
- $(LIBBITCOIN_COMMON) \
- $(LIBBITCOIN_CONSENSUS) \
- $(LIBBITCOIN_UTIL) \
- $(LIBBITCOIN_CRYPTO) \
- $(LIBBITCOIN_ZMQ) \
- $(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) \
- $(LIBMEMENV) \
- $(LIBSECP256K1) \
- $(LIBUNIVALUE)
-
-bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS)
#
# bitcoinconsensus library #
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index cf09eee2cb..13bfea7646 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -3,6 +3,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
bin_PROGRAMS += qt/bitcoin-qt
+
+if BUILD_BITCOIN_GUI
+ bin_PROGRAMS += bitcoin-gui
+endif
+
EXTRA_LIBRARIES += qt/libbitcoinqt.a
# bitcoin qt core #
@@ -294,29 +299,43 @@ QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:
# Most files will depend on the forms and moc files as includes. Generate them
# before anything else.
$(QT_MOC): $(QT_FORMS_H)
-$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC)
+$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) $(bitcoin_gui_OBJECTS) : | $(QT_MOC)
-# bitcoin-qt binary #
-qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
+# bitcoin-qt and bitcoin-gui binaries #
+bitcoin_qt_cppflags = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
$(QT_INCLUDES) $(QR_CFLAGS)
-qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
+bitcoin_qt_cxxflags = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
-qt_bitcoin_qt_SOURCES = qt/main.cpp
+bitcoin_qt_sources = qt/main.cpp
if TARGET_WINDOWS
- qt_bitcoin_qt_SOURCES += $(BITCOIN_RC)
+ bitcoin_qt_sources += $(BITCOIN_RC)
endif
-qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
+bitcoin_qt_ldadd = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
if ENABLE_WALLET
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_UTIL) $(LIBBITCOIN_WALLET)
+bitcoin_qt_ldadd += $(LIBBITCOIN_UTIL) $(LIBBITCOIN_WALLET)
endif
if ENABLE_ZMQ
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
+bitcoin_qt_ldadd += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
+bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
-qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX
+bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX
+
+qt_bitcoin_qt_CPPFLAGS = $(bitcoin_qt_cppflags)
+qt_bitcoin_qt_CXXFLAGS = $(bitcoin_qt_cxxflags)
+qt_bitcoin_qt_SOURCES = $(bitcoin_qt_sources)
+qt_bitcoin_qt_LDADD = $(bitcoin_qt_ldadd)
+qt_bitcoin_qt_LDFLAGS = $(bitcoin_qt_ldflags)
+qt_bitcoin_qt_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags)
+
+bitcoin_gui_CPPFLAGS = $(bitcoin_qt_cppflags)
+bitcoin_gui_CXXFLAGS = $(bitcoin_qt_cxxflags)
+bitcoin_gui_SOURCES = $(bitcoin_qt_sources)
+bitcoin_gui_LDADD = $(bitcoin_qt_ldadd)
+bitcoin_gui_LDFLAGS = $(bitcoin_qt_ldflags)
+bitcoin_gui_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags)
#locale/foo.ts -> locale/foo.qm
QT_QM=$(QT_TS:.ts=.qm)
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index 00e5d7e7a0..42b351a72d 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -20,9 +20,7 @@
struct nontrivial_t {
int x;
nontrivial_t() :x(-1) {}
- ADD_SERIALIZE_METHODS
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {READWRITE(x);}
+ SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); }
};
static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value,
"expected nontrivial_t to not be trivially constructible");
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 377ac3a1a6..9ec1beeaf7 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -92,12 +92,13 @@ private:
friend class PartiallyDownloadedBlock;
- static const int SHORTTXIDS_LENGTH = 6;
protected:
std::vector<uint64_t> shorttxids;
std::vector<PrefilledTransaction> prefilledtxn;
public:
+ static constexpr int SHORTTXIDS_LENGTH = 6;
+
CBlockHeader header;
// Dummy for deserialization
diff --git a/src/bloom.h b/src/bloom.h
index 9173b80d66..9307257852 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -64,15 +64,7 @@ public:
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(vData);
- READWRITE(nHashFuncs);
- READWRITE(nTweak);
- READWRITE(nFlags);
- }
+ SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); }
void insert(const std::vector<unsigned char>& vKey);
void insert(const COutPoint& outpoint);
diff --git a/src/flatfile.h b/src/flatfile.h
index 60b3503cc3..04f6373a24 100644
--- a/src/flatfile.h
+++ b/src/flatfile.h
@@ -16,13 +16,7 @@ struct FlatFilePos
int nFile;
unsigned int nPos;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(VARINT_MODE(nFile, VarIntMode::NONNEGATIVE_SIGNED));
- READWRITE(VARINT(nPos));
- }
+ SERIALIZE_METHODS(FlatFilePos, obj) { READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos)); }
FlatFilePos() : nFile(-1), nPos(0) {}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index f03d8c0c2c..f1b9997371 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -9,7 +9,6 @@
#include <httpserver.h>
#include <rpc/protocol.h>
#include <rpc/server.h>
-#include <ui_interface.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
@@ -249,11 +248,8 @@ static bool InitRPCAuthentication()
{
if (gArgs.GetArg("-rpcpassword", "") == "")
{
- LogPrintf("No rpcpassword set - using random cookie authentication.\n");
+ LogPrintf("Using random cookie authentication.\n");
if (!GenerateAuthCookie(&strRPCUserColonPass)) {
- uiInterface.ThreadSafeMessageBox(
- _("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode
- "", CClientUIInterface::MSG_ERROR);
return false;
}
} else {
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index ffe246b241..5e78fd1d71 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -421,7 +421,7 @@ bool UpdateHTTPServerLogging(bool enable) {
#endif
}
-static std::thread threadHTTP;
+static std::thread g_thread_http;
static std::vector<std::thread> g_thread_http_workers;
void StartHTTPServer()
@@ -429,7 +429,7 @@ void StartHTTPServer()
LogPrint(BCLog::HTTP, "Starting HTTP server\n");
int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
- threadHTTP = std::thread(ThreadHTTP, eventBase);
+ g_thread_http = std::thread(ThreadHTTP, eventBase);
for (int i = 0; i < rpcThreads; i++) {
g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue, i);
@@ -467,7 +467,7 @@ void StopHTTPServer()
boundSockets.clear();
if (eventBase) {
LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n");
- threadHTTP.join();
+ if (g_thread_http.joinable()) g_thread_http.join();
}
if (eventHTTP) {
evhttp_free(eventHTTP);
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index c3ce8d7af0..f2c3d66ebd 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -39,14 +39,7 @@ struct DBVal {
uint256 header;
FlatFilePos pos;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(hash);
- READWRITE(header);
- READWRITE(pos);
- }
+ SERIALIZE_METHODS(DBVal, obj) { READWRITE(obj.hash, obj.header, obj.pos); }
};
struct DBHeightKey {
@@ -78,17 +71,14 @@ struct DBHashKey {
explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
+ SERIALIZE_METHODS(DBHashKey, obj) {
char prefix = DB_BLOCK_HASH;
READWRITE(prefix);
if (prefix != DB_BLOCK_HASH) {
throw std::ios_base::failure("Invalid format for block filter index DB hash key");
}
- READWRITE(hash);
+ READWRITE(obj.hash);
}
};
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 5bbe6ad1df..4626395ef0 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -21,12 +21,10 @@ struct CDiskTxPos : public FlatFilePos
{
unsigned int nTxOffset; // after header
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(FlatFilePos, *this);
- READWRITE(VARINT(nTxOffset));
+ SERIALIZE_METHODS(CDiskTxPos, obj)
+ {
+ READWRITEAS(FlatFilePos, obj);
+ READWRITE(VARINT(obj.nTxOffset));
}
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
diff --git a/src/init.cpp b/src/init.cpp
index f01416e136..025ae06520 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -59,9 +59,10 @@
#include <validationinterface.h>
#include <walletinitinterface.h>
+#include <functional>
+#include <set>
#include <stdint.h>
#include <stdio.h>
-#include <set>
#ifndef WIN32
#include <attributes.h>
@@ -350,13 +351,13 @@ static void registerSignalHandler(int signal, void(*handler)(int))
static boost::signals2::connection rpc_notify_block_change_connection;
static void OnRPCStarted()
{
- rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange);
+ rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(std::bind(RPCNotifyBlockChange, std::placeholders::_2));
}
static void OnRPCStopped()
{
rpc_notify_block_change_connection.disconnect();
- RPCNotifyBlockChange(false, nullptr);
+ RPCNotifyBlockChange(nullptr);
g_best_block_cv.notify_all();
LogPrint(BCLog::RPC, "RPC stopped.\n");
}
@@ -604,9 +605,9 @@ std::string LicenseInfo()
}
#if HAVE_SYSTEM
-static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex)
+static void BlockNotifyCallback(SynchronizationState sync_state, const CBlockIndex* pBlockIndex)
{
- if (initialSync || !pBlockIndex)
+ if (sync_state != SynchronizationState::POST_INIT || !pBlockIndex)
return;
std::string strCmd = gArgs.GetArg("-blocknotify", "");
@@ -622,7 +623,7 @@ static bool fHaveGenesis = false;
static Mutex g_genesis_wait_mutex;
static std::condition_variable g_genesis_wait_cv;
-static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
+static void BlockNotifyGenesisWait(const CBlockIndex* pBlockIndex)
{
if (pBlockIndex != nullptr) {
{
@@ -1700,7 +1701,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
}
const CBlockIndex* tip = chainstate->m_chain.Tip();
- RPCNotifyBlockChange(true, tip);
+ RPCNotifyBlockChange(tip);
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
strLoadError = _("The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. "
@@ -1825,7 +1826,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
// No locking, as this happens before any background thread is started.
boost::signals2::connection block_notify_genesis_wait_connection;
if (::ChainActive().Tip() == nullptr) {
- block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait);
+ block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
} else {
fHaveGenesis = true;
}
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index cc0f7db5c1..3c94e44b53 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -309,16 +309,16 @@ public:
}
std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
{
- return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](bool initial_download, const CBlockIndex* block) {
- fn(initial_download, block->nHeight, block->GetBlockTime(),
+ return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
+ fn(sync_state, block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
}));
}
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
{
return MakeHandler(
- ::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) {
- fn(initial_download, block->nHeight, block->GetBlockTime(),
+ ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
+ fn(sync_state, block->nHeight, block->GetBlockTime(),
/* verification progress is unused when a header was received */ 0);
}));
}
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index aef6b19458..45b0e18fae 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -27,6 +27,7 @@ class Coin;
class RPCTimerInterface;
class UniValue;
class proxyType;
+enum class SynchronizationState;
enum class WalletCreationStatus;
struct CNodeStateStats;
struct NodeContext;
@@ -249,12 +250,12 @@ public:
//! Register handler for block tip messages.
using NotifyBlockTipFn =
- std::function<void(bool initial_download, int height, int64_t block_time, double verification_progress)>;
+ std::function<void(SynchronizationState, int height, int64_t block_time, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) = 0;
//! Register handler for header tip messages.
using NotifyHeaderTipFn =
- std::function<void(bool initial_download, int height, int64_t block_time, double verification_progress)>;
+ std::function<void(SynchronizationState, int height, int64_t block_time, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
//! Return pointer to internal chain interface, useful for testing.
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 13b034936b..349dce0247 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -351,14 +351,13 @@ public:
}
return result;
}
- bool tryGetBalances(WalletBalances& balances, int& num_blocks, bool force, int cached_num_blocks) override
+ bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
{
TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
num_blocks = m_wallet->GetLastBlockHeight();
- if (!force && num_blocks == cached_num_blocks) return false;
balances = getBalances();
return true;
}
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index f35335c69f..421d35af15 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -202,11 +202,8 @@ public:
//! Get balances.
virtual WalletBalances getBalances() = 0;
- //! Get balances if possible without waiting for chain and wallet locks.
- virtual bool tryGetBalances(WalletBalances& balances,
- int& num_blocks,
- bool force,
- int cached_num_blocks) = 0;
+ //! Get balances if possible without blocking.
+ virtual bool tryGetBalances(WalletBalances& balances, int& num_blocks) = 0;
//! Get balance.
virtual CAmount getBalance() = 0;
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 4ac6219886..8072b12119 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -9,6 +9,24 @@
#include <consensus/consensus.h>
+std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits)
+{
+ std::vector<unsigned char> ret((bits.size() + 7) / 8);
+ for (unsigned int p = 0; p < bits.size(); p++) {
+ ret[p / 8] |= bits[p] << (p % 8);
+ }
+ return ret;
+}
+
+std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes)
+{
+ std::vector<bool> ret(bytes.size() * 8);
+ for (unsigned int p = 0; p < ret.size(); p++) {
+ ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0;
+ }
+ return ret;
+}
+
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
{
header = block.GetBlockHeader();
diff --git a/src/merkleblock.h b/src/merkleblock.h
index e641c8aa94..b2d2828784 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -13,6 +13,10 @@
#include <vector>
+// Helper functions for serialization.
+std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits);
+std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes);
+
/** Data structure that represents a partial merkle tree.
*
* It represents a subset of the txid's of a known block, in a way that
@@ -81,27 +85,14 @@ protected:
public:
- /** serialization implementation */
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nTransactions);
- READWRITE(vHash);
- std::vector<unsigned char> vBytes;
- if (ser_action.ForRead()) {
- READWRITE(vBytes);
- CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
- us.vBits.resize(vBytes.size() * 8);
- for (unsigned int p = 0; p < us.vBits.size(); p++)
- us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
- us.fBad = false;
- } else {
- vBytes.resize((vBits.size()+7)/8);
- for (unsigned int p = 0; p < vBits.size(); p++)
- vBytes[p / 8] |= vBits[p] << (p % 8);
- READWRITE(vBytes);
- }
+ SERIALIZE_METHODS(CPartialMerkleTree, obj)
+ {
+ READWRITE(obj.nTransactions, obj.vHash);
+ std::vector<unsigned char> bytes;
+ SER_WRITE(obj, bytes = BitsToBytes(obj.vBits));
+ READWRITE(bytes);
+ SER_READ(obj, obj.vBits = BytesToBits(bytes));
+ SER_READ(obj, obj.fBad = false);
}
/** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */
@@ -157,13 +148,7 @@ public:
CMerkleBlock() {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(header);
- READWRITE(txn);
- }
+ SERIALIZE_METHODS(CMerkleBlock, obj) { READWRITE(obj.header, obj.txn); }
private:
// Combined constructor to consolidate code
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 1df1fab59d..6d85b46831 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1608,6 +1608,37 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
}
}
+//! Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed).
+CTransactionRef static FindTxForGetData(CNode* peer, const uint256& txid, const std::chrono::seconds mempool_req, const std::chrono::seconds longlived_mempool_time) LOCKS_EXCLUDED(cs_main)
+{
+ // Check if the requested transaction is so recent that we're just
+ // about to announce it to the peer; if so, they certainly shouldn't
+ // know we already have it.
+ {
+ LOCK(peer->m_tx_relay->cs_tx_inventory);
+ if (peer->m_tx_relay->setInventoryTxToSend.count(txid)) return {};
+ }
+
+ {
+ LOCK(cs_main);
+ // Look up transaction in relay pool
+ auto mi = mapRelay.find(txid);
+ if (mi != mapRelay.end()) return mi->second;
+ }
+
+ auto txinfo = mempool.info(txid);
+ if (txinfo.tx) {
+ // To protect privacy, do not answer getdata using the mempool when
+ // that TX couldn't have been INVed in reply to a MEMPOOL request,
+ // or when it's too recent to have expired from mapRelay.
+ if ((mempool_req.count() && txinfo.m_time <= mempool_req) || txinfo.m_time <= longlived_mempool_time) {
+ return txinfo.tx;
+ }
+ }
+
+ return {};
+}
+
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
{
AssertLockNotHeld(cs_main);
@@ -1622,58 +1653,31 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
const std::chrono::seconds mempool_req = pfrom->m_tx_relay != nullptr ? pfrom->m_tx_relay->m_last_mempool_req.load()
: std::chrono::seconds::min();
- {
- LOCK(cs_main);
-
- // Process as many TX items from the front of the getdata queue as
- // possible, since they're common and it's efficient to batch process
- // them.
- while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) {
- if (interruptMsgProc)
- return;
- // The send buffer provides backpressure. If there's no space in
- // the buffer, pause processing until the next call.
- if (pfrom->fPauseSend)
- break;
+ // Process as many TX items from the front of the getdata queue as
+ // possible, since they're common and it's efficient to batch process
+ // them.
+ while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) {
+ if (interruptMsgProc) return;
+ // The send buffer provides backpressure. If there's no space in
+ // the buffer, pause processing until the next call.
+ if (pfrom->fPauseSend) break;
- const CInv &inv = *it++;
+ const CInv &inv = *it++;
- if (pfrom->m_tx_relay == nullptr) {
- // Ignore GETDATA requests for transactions from blocks-only peers.
- continue;
- }
+ if (pfrom->m_tx_relay == nullptr) {
+ // Ignore GETDATA requests for transactions from blocks-only peers.
+ continue;
+ }
- // Send stream from relay memory
- bool push = false;
- auto mi = mapRelay.find(inv.hash);
+ CTransactionRef tx = FindTxForGetData(pfrom, inv.hash, mempool_req, longlived_mempool_time);
+ if (tx) {
int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
- if (mi != mapRelay.end()) {
- connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
- push = true;
- } else {
- auto txinfo = mempool.info(inv.hash);
- // To protect privacy, do not answer getdata using the mempool when
- // that TX couldn't have been INVed in reply to a MEMPOOL request,
- // or when it's too recent to have expired from mapRelay.
- if (txinfo.tx && (
- (mempool_req.count() && txinfo.m_time <= mempool_req)
- || (txinfo.m_time <= longlived_mempool_time)))
- {
- connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
- push = true;
- }
- }
-
- if (push) {
- // We interpret fulfilling a GETDATA for a transaction as a
- // successful initial broadcast and remove it from our
- // unbroadcast set.
- mempool.RemoveUnbroadcastTx(inv.hash);
- } else {
- vNotFound.push_back(inv);
- }
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *tx));
+ mempool.RemoveUnbroadcastTx(inv.hash);
+ } else {
+ vNotFound.push_back(inv);
}
- } // release cs_main
+ }
// Only process one BLOCK item per call, since they're uncommon and can be
// expensive to process.
@@ -2420,6 +2424,7 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
uint32_t nFetchFlags = GetFetchFlags(pfrom);
const auto current_time = GetTime<std::chrono::microseconds>();
+ uint256* best_block{nullptr};
for (CInv &inv : vInv)
{
@@ -2436,17 +2441,14 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
if (inv.type == MSG_BLOCK) {
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
- // We used to request the full block here, but since headers-announcements are now the
- // primary method of announcement on the network, and since, in the case that a node
- // fell back to inv we probably have a reorg which we should get the headers for first,
- // we now only provide a getheaders response here. When we receive the headers, we will
- // then ask for the blocks we need.
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), inv.hash));
- LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
+ // Headers-first is the primary method of announcement on
+ // the network. If a node fell back to sending blocks by inv,
+ // it's probably for a re-org. The final block hash
+ // provided should be the highest, so send a getheaders and
+ // then fetch the blocks we need to catch up.
+ best_block = &inv.hash;
}
- }
- else
- {
+ } else {
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol, disconnecting peer=%d\n", inv.hash.ToString(), pfrom->GetId());
@@ -2457,6 +2459,12 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
}
}
}
+
+ if (best_block != nullptr) {
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), *best_block));
+ LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, best_block->ToString(), pfrom->GetId());
+ }
+
return true;
}
diff --git a/src/netaddress.h b/src/netaddress.h
index d8f19deffe..e640c07d32 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -99,12 +99,7 @@ class CNetAddr
friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); }
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(ip);
- }
+ SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip); }
friend class CSubNet;
};
@@ -136,14 +131,7 @@ class CSubNet
friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); }
friend bool operator<(const CSubNet& a, const CSubNet& b);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(network);
- READWRITE(netmask);
- READWRITE(valid);
- }
+ SERIALIZE_METHODS(CSubNet, obj) { READWRITE(obj.network, obj.netmask, obj.valid); }
};
/** A combination of a network address (CNetAddr) and a (TCP) port */
@@ -171,13 +159,7 @@ class CService : public CNetAddr
CService(const struct in6_addr& ipv6Addr, unsigned short port);
explicit CService(const struct sockaddr_in6& addr);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(ip);
- READWRITE(WrapBigEndian(port));
- }
+ SERIALIZE_METHODS(CService, obj) { READWRITE(obj.ip, Using<BigEndianFormatter<2>>(obj.port)); }
};
bool SanityCheckASMap(const std::vector<bool>& asmap);
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index 702a0cbe53..c8b4d60fd0 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -35,16 +35,7 @@ public:
m_coins_count(coins_count),
m_nchaintx(nchaintx) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(m_base_blockhash);
- READWRITE(m_coins_count);
- READWRITE(m_nchaintx);
- }
-
+ SERIALIZE_METHODS(SnapshotMetadata, obj) { READWRITE(obj.m_base_blockhash, obj.m_coins_count, obj.m_nchaintx); }
};
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index c040867965..61fa80c130 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -48,12 +48,7 @@ public:
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString() const;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nSatoshisPerK);
- }
+ SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
};
#endif // BITCOIN_POLICY_FEERATE_H
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 750d42efbc..fd8fc8b868 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -33,17 +33,7 @@ public:
SetNull();
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(this->nVersion);
- READWRITE(hashPrevBlock);
- READWRITE(hashMerkleRoot);
- READWRITE(nTime);
- READWRITE(nBits);
- READWRITE(nNonce);
- }
+ SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
void SetNull()
{
@@ -89,12 +79,10 @@ public:
*(static_cast<CBlockHeader*>(this)) = header;
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(CBlockHeader, *this);
- READWRITE(vtx);
+ SERIALIZE_METHODS(CBlock, obj)
+ {
+ READWRITEAS(CBlockHeader, obj);
+ READWRITE(obj.vtx);
}
void SetNull()
@@ -131,14 +119,12 @@ struct CBlockLocator
explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
+ SERIALIZE_METHODS(CBlockLocator, obj)
+ {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
- READWRITE(vHave);
+ READWRITE(obj.vHave);
}
void SetNull()
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 58b3e8aedc..4514db578a 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -26,13 +26,7 @@ public:
COutPoint(): n(NULL_INDEX) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(hash);
- READWRITE(n);
- }
+ SERIALIZE_METHODS(COutPoint, obj) { READWRITE(obj.hash, obj.n); }
void SetNull() { hash.SetNull(); n = NULL_INDEX; }
bool IsNull() const { return (hash.IsNull() && n == NULL_INDEX); }
@@ -103,14 +97,7 @@ public:
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- }
+ SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
friend bool operator==(const CTxIn& a, const CTxIn& b)
{
@@ -143,13 +130,7 @@ public:
CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- }
+ SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
void SetNull()
{
diff --git a/src/protocol.h b/src/protocol.h
index dfcb0e0660..0bf9f1d7b5 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -46,16 +46,7 @@ public:
std::string GetCommand() const;
bool IsValid(const MessageStartChars& messageStart) const;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(pchMessageStart);
- READWRITE(pchCommand);
- READWRITE(nMessageSize);
- READWRITE(pchChecksum);
- }
+ SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); }
char pchMessageStart[MESSAGE_START_SIZE];
char pchCommand[COMMAND_SIZE];
@@ -74,100 +65,100 @@ namespace NetMsgType {
* receiving node at the beginning of a connection.
* @see https://bitcoin.org/en/developer-reference#version
*/
-extern const char *VERSION;
+extern const char* VERSION;
/**
* The verack message acknowledges a previously-received version message,
* informing the connecting node that it can begin to send other messages.
* @see https://bitcoin.org/en/developer-reference#verack
*/
-extern const char *VERACK;
+extern const char* VERACK;
/**
* The addr (IP address) message relays connection information for peers on the
* network.
* @see https://bitcoin.org/en/developer-reference#addr
*/
-extern const char *ADDR;
+extern const char* ADDR;
/**
* The inv message (inventory message) transmits one or more inventories of
* objects known to the transmitting peer.
* @see https://bitcoin.org/en/developer-reference#inv
*/
-extern const char *INV;
+extern const char* INV;
/**
* The getdata message requests one or more data objects from another node.
* @see https://bitcoin.org/en/developer-reference#getdata
*/
-extern const char *GETDATA;
+extern const char* GETDATA;
/**
* The merkleblock message is a reply to a getdata message which requested a
* block using the inventory type MSG_MERKLEBLOCK.
* @since protocol version 70001 as described by BIP37.
* @see https://bitcoin.org/en/developer-reference#merkleblock
*/
-extern const char *MERKLEBLOCK;
+extern const char* MERKLEBLOCK;
/**
* The getblocks message requests an inv message that provides block header
* hashes starting from a particular point in the block chain.
* @see https://bitcoin.org/en/developer-reference#getblocks
*/
-extern const char *GETBLOCKS;
+extern const char* GETBLOCKS;
/**
* The getheaders message requests a headers message that provides block
* headers starting from a particular point in the block chain.
* @since protocol version 31800.
* @see https://bitcoin.org/en/developer-reference#getheaders
*/
-extern const char *GETHEADERS;
+extern const char* GETHEADERS;
/**
* The tx message transmits a single transaction.
* @see https://bitcoin.org/en/developer-reference#tx
*/
-extern const char *TX;
+extern const char* TX;
/**
* The headers message sends one or more block headers to a node which
* previously requested certain headers with a getheaders message.
* @since protocol version 31800.
* @see https://bitcoin.org/en/developer-reference#headers
*/
-extern const char *HEADERS;
+extern const char* HEADERS;
/**
* The block message transmits a single serialized block.
* @see https://bitcoin.org/en/developer-reference#block
*/
-extern const char *BLOCK;
+extern const char* BLOCK;
/**
* The getaddr message requests an addr message from the receiving node,
* preferably one with lots of IP addresses of other receiving nodes.
* @see https://bitcoin.org/en/developer-reference#getaddr
*/
-extern const char *GETADDR;
+extern const char* GETADDR;
/**
* The mempool message requests the TXIDs of transactions that the receiving
* node has verified as valid but which have not yet appeared in a block.
* @since protocol version 60002.
* @see https://bitcoin.org/en/developer-reference#mempool
*/
-extern const char *MEMPOOL;
+extern const char* MEMPOOL;
/**
* The ping message is sent periodically to help confirm that the receiving
* peer is still connected.
* @see https://bitcoin.org/en/developer-reference#ping
*/
-extern const char *PING;
+extern const char* PING;
/**
* The pong message replies to a ping message, proving to the pinging node that
* the ponging node is still alive.
* @since protocol version 60001 as described by BIP31.
* @see https://bitcoin.org/en/developer-reference#pong
*/
-extern const char *PONG;
+extern const char* PONG;
/**
* The notfound message is a reply to a getdata message which requested an
* object the receiving node does not have available for relay.
* @since protocol version 70001.
* @see https://bitcoin.org/en/developer-reference#notfound
*/
-extern const char *NOTFOUND;
+extern const char* NOTFOUND;
/**
* The filterload message tells the receiving peer to filter all relayed
* transactions and requested merkle blocks through the provided filter.
@@ -176,7 +167,7 @@ extern const char *NOTFOUND;
* 70011 as described by BIP111.
* @see https://bitcoin.org/en/developer-reference#filterload
*/
-extern const char *FILTERLOAD;
+extern const char* FILTERLOAD;
/**
* The filteradd message tells the receiving peer to add a single element to a
* previously-set bloom filter, such as a new public key.
@@ -185,7 +176,7 @@ extern const char *FILTERLOAD;
* 70011 as described by BIP111.
* @see https://bitcoin.org/en/developer-reference#filteradd
*/
-extern const char *FILTERADD;
+extern const char* FILTERADD;
/**
* The filterclear message tells the receiving peer to remove a previously-set
* bloom filter.
@@ -194,20 +185,20 @@ extern const char *FILTERADD;
* 70011 as described by BIP111.
* @see https://bitcoin.org/en/developer-reference#filterclear
*/
-extern const char *FILTERCLEAR;
+extern const char* FILTERCLEAR;
/**
* Indicates that a node prefers to receive new block announcements via a
* "headers" message rather than an "inv".
* @since protocol version 70012 as described by BIP130.
* @see https://bitcoin.org/en/developer-reference#sendheaders
*/
-extern const char *SENDHEADERS;
+extern const char* SENDHEADERS;
/**
* The feefilter message tells the receiving peer not to inv us any txs
* which do not meet the specified min fee rate.
* @since protocol version 70013 as described by BIP133
*/
-extern const char *FEEFILTER;
+extern const char* FEEFILTER;
/**
* Contains a 1-byte bool and 8-byte LE version number.
* Indicates that a node is willing to provide blocks via "cmpctblock" messages.
@@ -215,43 +206,43 @@ extern const char *FEEFILTER;
* "cmpctblock" message rather than an "inv", depending on message contents.
* @since protocol version 70014 as described by BIP 152
*/
-extern const char *SENDCMPCT;
+extern const char* SENDCMPCT;
/**
* Contains a CBlockHeaderAndShortTxIDs object - providing a header and
* list of "short txids".
* @since protocol version 70014 as described by BIP 152
*/
-extern const char *CMPCTBLOCK;
+extern const char* CMPCTBLOCK;
/**
* Contains a BlockTransactionsRequest
* Peer should respond with "blocktxn" message.
* @since protocol version 70014 as described by BIP 152
*/
-extern const char *GETBLOCKTXN;
+extern const char* GETBLOCKTXN;
/**
* Contains a BlockTransactions.
* Sent in response to a "getblocktxn" message.
* @since protocol version 70014 as described by BIP 152
*/
-extern const char *BLOCKTXN;
+extern const char* BLOCKTXN;
/**
* getcfcheckpt requests evenly spaced compact filter headers, enabling
* parallelized download and validation of the headers between them.
* Only available with service bit NODE_COMPACT_FILTERS as described by
* BIP 157 & 158.
*/
-extern const char *GETCFCHECKPT;
+extern const char* GETCFCHECKPT;
/**
* cfcheckpt is a response to a getcfcheckpt request containing a vector of
* evenly spaced filter headers for blocks on the requested chain.
* Only available with service bit NODE_COMPACT_FILTERS as described by
* BIP 157 & 158.
*/
-extern const char *CFCHECKPT;
-};
+extern const char* CFCHECKPT;
+}; // namespace NetMsgType
/* Get a vector of all valid message types (see above) */
-const std::vector<std::string> &getAllNetMessageTypes();
+const std::vector<std::string>& getAllNetMessageTypes();
/** nServices flags */
enum ServiceFlags : uint64_t {
@@ -320,7 +311,8 @@ void SetServiceFlagsIBDCache(bool status);
* == GetDesirableServiceFlags(services), ie determines whether the given
* set of service flags are sufficient for a peer to be "relevant".
*/
-static inline bool HasAllDesirableServiceFlags(ServiceFlags services) {
+static inline bool HasAllDesirableServiceFlags(ServiceFlags services)
+{
return !(GetDesirableServiceFlags(services) & (~services));
}
@@ -328,7 +320,8 @@ static inline bool HasAllDesirableServiceFlags(ServiceFlags services) {
* Checks if a peer with the given service flags may be capable of having a
* robust address-storage DB.
*/
-static inline bool MayHaveUsefulAddressDB(ServiceFlags services) {
+static inline bool MayHaveUsefulAddressDB(ServiceFlags services)
+{
return (services & NODE_NETWORK) || (services & NODE_NETWORK_LIMITED);
}
@@ -341,27 +334,21 @@ public:
void Init();
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
+ SERIALIZE_METHODS(CAddress, obj)
{
- if (ser_action.ForRead())
- Init();
+ SER_READ(obj, obj.Init());
int nVersion = s.GetVersion();
- if (s.GetType() & SER_DISK)
+ if (s.GetType() & SER_DISK) {
READWRITE(nVersion);
+ }
if ((s.GetType() & SER_DISK) ||
- (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
- READWRITE(nTime);
- uint64_t nServicesInt = nServices;
- READWRITE(nServicesInt);
- nServices = static_cast<ServiceFlags>(nServicesInt);
- READWRITEAS(CService, *this);
+ (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) {
+ READWRITE(obj.nTime);
+ }
+ READWRITE(Using<CustomUintFormatter<8>>(obj.nServices));
+ READWRITEAS(CService, obj);
}
- // TODO: make private (improves encapsulation)
-public:
ServiceFlags nServices;
// disk and network only
@@ -370,20 +357,19 @@ public:
/** getdata message type flags */
const uint32_t MSG_WITNESS_FLAG = 1 << 30;
-const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2;
+const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2;
/** getdata / inv message types.
* These numbers are defined by the protocol. When adding a new value, be sure
* to mention it in the respective BIP.
*/
-enum GetDataMsg
-{
+enum GetDataMsg {
UNDEFINED = 0,
MSG_TX = 1,
MSG_BLOCK = 2,
// The following can only occur in getdata. Invs always use TX or BLOCK.
- MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37
- MSG_CMPCT_BLOCK = 4, //!< Defined in BIP152
+ MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37
+ MSG_CMPCT_BLOCK = 4, //!< Defined in BIP152
MSG_WITNESS_BLOCK = MSG_BLOCK | MSG_WITNESS_FLAG, //!< Defined in BIP144
MSG_WITNESS_TX = MSG_TX | MSG_WITNESS_FLAG, //!< Defined in BIP144
MSG_FILTERED_WITNESS_BLOCK = MSG_FILTERED_BLOCK | MSG_WITNESS_FLAG,
@@ -396,21 +382,13 @@ public:
CInv();
CInv(int typeIn, const uint256& hashIn);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(type);
- READWRITE(hash);
- }
+ SERIALIZE_METHODS(CInv, obj) { READWRITE(obj.type, obj.hash); }
friend bool operator<(const CInv& a, const CInv& b);
std::string GetCommand() const;
std::string ToString() const;
-public:
int type;
uint256 hash;
};
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 8939b566f7..6fdf6322ff 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -34,6 +34,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/threadnames.h>
+#include <validation.h>
#include <memory>
@@ -61,6 +62,7 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE(bool*)
Q_DECLARE_METATYPE(CAmount)
+Q_DECLARE_METATYPE(SynchronizationState)
Q_DECLARE_METATYPE(uint256)
static QString GetLangTerritory()
@@ -435,6 +437,7 @@ int GuiMain(int argc, char* argv[])
// Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
qRegisterMetaType<bool*>();
+ qRegisterMetaType<SynchronizationState>();
#ifdef ENABLE_WALLET
qRegisterMetaType<WalletModel*>();
#endif
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 3a1fdc22a6..4de4850903 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -37,6 +37,7 @@
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
+#include <validation.h>
#include <QAction>
#include <QApplication>
@@ -567,7 +568,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
- setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false);
+ setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false, SynchronizationState::INIT_DOWNLOAD);
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
// Receive and report messages from client model
@@ -926,11 +927,15 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
dlg.exec();
}
-void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header)
+void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
{
// Disabling macOS App Nap on initial sync, disk and reindex operations.
#ifdef Q_OS_MAC
- (m_node.isInitialBlockDownload() || m_node.getReindex() || m_node.getImporting()) ? m_app_nap_inhibitor->disableAppNap() : m_app_nap_inhibitor->enableAppNap();
+ if (sync_state == SynchronizationState::POST_INIT) {
+ m_app_nap_inhibitor->enableAppNap();
+ } else {
+ m_app_nap_inhibitor->disableAppNap();
+ }
#endif
if (modalOverlay)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 6733585f68..82a2db9ba2 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -38,6 +38,7 @@ class WalletFrame;
class WalletModel;
class HelpMessageDialog;
class ModalOverlay;
+enum class SynchronizationState;
namespace interfaces {
class Handler;
@@ -213,7 +214,7 @@ public Q_SLOTS:
/** Set network state shown in the UI */
void setNetworkActive(bool networkActive);
/** Set number of blocks and last block date shown in the UI */
- void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers);
+ void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state);
/** Notify the user of an event from the core network or transaction handling code.
@param[in] title the message box / notification title
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index b94fcc9865..159b0d3df3 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -15,6 +15,7 @@
#include <net.h>
#include <netbase.h>
#include <util/system.h>
+#include <validation.h>
#include <stdint.h>
@@ -234,17 +235,8 @@ static void BannedListChanged(ClientModel *clientmodel)
assert(invoked);
}
-static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int height, int64_t blockTime, double verificationProgress, bool fHeader)
+static void BlockTipChanged(ClientModel* clientmodel, SynchronizationState sync_state, int height, int64_t blockTime, double verificationProgress, bool fHeader)
{
- // lock free async UI updates in case we have a new block tip
- // during initial sync, only update the UI if the last update
- // was > 250ms (MODEL_UPDATE_DELAY) ago
- int64_t now = 0;
- if (initialSync)
- now = GetTimeMillis();
-
- int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
-
if (fHeader) {
// cache best headers time and height to reduce future cs_main locks
clientmodel->cachedBestHeaderHeight = height;
@@ -253,17 +245,22 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int heig
clientmodel->m_cached_num_blocks = height;
}
- // During initial sync, block notifications, and header notifications from reindexing are both throttled.
- if (!initialSync || (fHeader && !clientmodel->node().getReindex()) || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
- //pass an async signal to the UI thread
- bool invoked = QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
- Q_ARG(int, height),
- Q_ARG(QDateTime, QDateTime::fromTime_t(blockTime)),
- Q_ARG(double, verificationProgress),
- Q_ARG(bool, fHeader));
- assert(invoked);
- nLastUpdateNotification = now;
+ // Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
+ const bool throttle = (sync_state != SynchronizationState::POST_INIT && !fHeader) || sync_state == SynchronizationState::INIT_REINDEX;
+ const int64_t now = throttle ? GetTimeMillis() : 0;
+ int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
+ if (throttle && now < nLastUpdateNotification + MODEL_UPDATE_DELAY) {
+ return;
}
+
+ bool invoked = QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
+ Q_ARG(int, height),
+ Q_ARG(QDateTime, QDateTime::fromTime_t(blockTime)),
+ Q_ARG(double, verificationProgress),
+ Q_ARG(bool, fHeader),
+ Q_ARG(SynchronizationState, sync_state));
+ assert(invoked);
+ nLastUpdateNotification = now;
}
void ClientModel::subscribeToCoreSignals()
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 7ac4120a8f..ace77f5972 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -12,10 +12,10 @@
#include <memory>
class BanTableModel;
+class CBlockIndex;
class OptionsModel;
class PeerTableModel;
-
-class CBlockIndex;
+enum class SynchronizationState;
namespace interfaces {
class Handler;
@@ -100,7 +100,7 @@ private:
Q_SIGNALS:
void numConnectionsChanged(int count);
- void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header);
+ void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state);
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
void networkActiveChanged(bool networkActive);
void alertsChanged(const QString &warnings);
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 18554aef1f..7a15503228 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -664,7 +664,7 @@ QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientat
QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent);
- TransactionRecord *data = priv->index(walletModel->wallet(), walletModel->clientModel().getNumBlocks(), row);
+ TransactionRecord *data = priv->index(walletModel->wallet(), walletModel->getNumBlocks(), row);
if(data)
{
return createIndex(row, column, data);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 70ee7f4917..1084ec9725 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -39,14 +39,15 @@
WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel& client_model, const PlatformStyle *platformStyle, QObject *parent) :
QObject(parent),
m_wallet(std::move(wallet)),
- m_client_model(client_model),
+ m_client_model(&client_model),
m_node(client_model.node()),
optionsModel(client_model.getOptionsModel()),
addressTableModel(nullptr),
transactionTableModel(nullptr),
recentRequestsTableModel(nullptr),
cachedEncryptionStatus(Unencrypted),
- cachedNumBlocks(0)
+ cachedNumBlocks(0),
+ timer(new QTimer(this))
{
fHaveWatchOnly = m_wallet->haveWatchOnly();
addressTableModel = new AddressTableModel(this);
@@ -64,11 +65,16 @@ WalletModel::~WalletModel()
void WalletModel::startPollBalance()
{
// This timer will be fired repeatedly to update the balance
- QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged);
timer->start(MODEL_UPDATE_DELAY);
}
+void WalletModel::setClientModel(ClientModel* client_model)
+{
+ m_client_model = client_model;
+ if (!m_client_model) timer->stop();
+}
+
void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
@@ -80,24 +86,31 @@ void WalletModel::updateStatus()
void WalletModel::pollBalanceChanged()
{
+ // Avoid recomputing wallet balances unless a TransactionChanged or
+ // BlockTip notification was received.
+ if (!fForceCheckBalanceChanged && cachedNumBlocks == m_client_model->getNumBlocks()) return;
+
// Try to get balances and return early if locks can't be acquired. This
// avoids the GUI from getting stuck on periodical polls if the core is
// holding the locks for a longer time - for example, during a wallet
// rescan.
interfaces::WalletBalances new_balances;
int numBlocks = -1;
- if (!m_wallet->tryGetBalances(new_balances, numBlocks, fForceCheckBalanceChanged, cachedNumBlocks)) {
+ if (!m_wallet->tryGetBalances(new_balances, numBlocks)) {
return;
}
- fForceCheckBalanceChanged = false;
+ if(fForceCheckBalanceChanged || numBlocks != cachedNumBlocks)
+ {
+ fForceCheckBalanceChanged = false;
- // Balance and number of transactions might have changed
- cachedNumBlocks = numBlocks;
+ // Balance and number of transactions might have changed
+ cachedNumBlocks = numBlocks;
- checkBalanceChanged(new_balances);
- if(transactionTableModel)
- transactionTableModel->updateConfirmations();
+ checkBalanceChanged(new_balances);
+ if(transactionTableModel)
+ transactionTableModel->updateConfirmations();
+ }
}
void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances)
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 07004b7c6b..23232ec66b 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -144,7 +144,8 @@ public:
interfaces::Node& node() const { return m_node; }
interfaces::Wallet& wallet() const { return *m_wallet; }
- ClientModel& clientModel() const { return m_client_model; }
+ void setClientModel(ClientModel* client_model);
+ int getNumBlocks() const { return cachedNumBlocks; }
QString getWalletName() const;
QString getDisplayName() const;
@@ -161,7 +162,7 @@ private:
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
- ClientModel& m_client_model;
+ ClientModel* m_client_model;
interfaces::Node& m_node;
bool fHaveWatchOnly;
@@ -179,6 +180,7 @@ private:
interfaces::WalletBalances m_cached_balances;
EncryptionStatus cachedEncryptionStatus;
int cachedNumBlocks;
+ QTimer* timer;
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 5d9b420df7..c4e607990a 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -97,6 +97,7 @@ void WalletView::setClientModel(ClientModel *_clientModel)
overviewPage->setClientModel(_clientModel);
sendCoinsPage->setClientModel(_clientModel);
+ if (walletModel) walletModel->setClientModel(_clientModel);
}
void WalletView::setWalletModel(WalletModel *_walletModel)
diff --git a/src/random.cpp b/src/random.cpp
index 5b8782d1ce..9c9a35709a 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -14,16 +14,14 @@
#include <wincrypt.h>
#endif
#include <logging.h> // for LogPrintf()
+#include <randomenv.h>
+#include <support/allocators/secure.h>
#include <sync.h> // for Mutex
#include <util/time.h> // for GetTimeMicros()
#include <stdlib.h>
#include <thread>
-#include <randomenv.h>
-
-#include <support/allocators/secure.h>
-
#ifndef WIN32
#include <fcntl.h>
#include <sys/time.h>
@@ -590,16 +588,6 @@ uint64_t GetRand(uint64_t nMax) noexcept
return FastRandomContext(g_mock_deterministic_tests).randrange(nMax);
}
-std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max) noexcept
-{
- return std::chrono::microseconds{GetRand(duration_max.count())};
-}
-
-std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept
-{
- return std::chrono::milliseconds{GetRand(duration_max.count())};
-}
-
int GetRandInt(int nMax) noexcept
{
return GetRand(nMax);
diff --git a/src/random.h b/src/random.h
index 690125079b..0c6dc24983 100644
--- a/src/random.h
+++ b/src/random.h
@@ -67,9 +67,21 @@
* Thread-safe.
*/
void GetRandBytes(unsigned char* buf, int num) noexcept;
+/** Generate a uniform random integer in the range [0..range). Precondition: range > 0 */
uint64_t GetRand(uint64_t nMax) noexcept;
-std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max) noexcept;
-std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept;
+/** 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
+// Having the compiler infer the template argument from the function argument
+// is dangerous, because the desired return value generally has a different
+// type than the function argument. So std::common_type is used to force the
+// call site to specify the type of the return value.
+{
+ assert(max.count() > 0);
+ return D{GetRand(max.count())};
+};
+constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
+constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
int GetRandInt(int nMax) noexcept;
uint256 GetRandHash() noexcept;
diff --git a/src/rest.cpp b/src/rest.cpp
index 02b35f92ab..cde8b472d3 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -50,18 +50,13 @@ struct CCoin {
uint32_t nHeight;
CTxOut out;
- ADD_SERIALIZE_METHODS;
-
CCoin() : nHeight(0) {}
explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {}
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
+ SERIALIZE_METHODS(CCoin, obj)
{
uint32_t nTxVerDummy = 0;
- READWRITE(nTxVerDummy);
- READWRITE(nHeight);
- READWRITE(out);
+ READWRITE(nTxVerDummy, obj.nHeight, obj.out);
}
};
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index c04e4fc77b..3c5fd565e3 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -214,7 +214,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request)
return ::ChainActive().Tip()->GetBlockHash().GetHex();
}
-void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
+void RPCNotifyBlockChange(const CBlockIndex* pindex)
{
if(pindex) {
std::lock_guard<std::mutex> lock(cs_blockchange);
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 2417340d64..453d0bc650 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -33,7 +33,7 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
double GetDifficulty(const CBlockIndex* blockindex);
/** Callback for when block tip changed. */
-void RPCNotifyBlockChange(bool ibd, const CBlockIndex *);
+void RPCNotifyBlockChange(const CBlockIndex*);
/** Block description to JSON */
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false) LOCKS_EXCLUDED(cs_main);
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 28b3582866..bcaed1ef88 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -788,6 +788,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
result.pushKV("capabilities", aCaps);
UniValue aRules(UniValue::VARR);
+ aRules.push_back("csv");
+ if (!fPreSegWit) aRules.push_back("!segwit");
UniValue vbavailable(UniValue::VOBJ);
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
@@ -875,7 +877,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
return result;
}
-class submitblock_StateCatcher : public CValidationInterface
+class submitblock_StateCatcher final : public CValidationInterface
{
public:
uint256 hash;
@@ -943,17 +945,17 @@ static UniValue submitblock(const JSONRPCRequest& request)
}
bool new_block;
- submitblock_StateCatcher sc(block.GetHash());
- RegisterValidationInterface(&sc);
+ auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
+ RegisterSharedValidationInterface(sc);
bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
- UnregisterValidationInterface(&sc);
+ UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) {
return "duplicate";
}
- if (!sc.found) {
+ if (!sc->found) {
return "inconclusive";
}
- return BIP22ValidationResult(sc.state);
+ return BIP22ValidationResult(sc->state);
}
static UniValue submitheader(const JSONRPCRequest& request)
diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h
index 467605ce46..a318ff0f9d 100644
--- a/src/script/keyorigin.h
+++ b/src/script/keyorigin.h
@@ -18,13 +18,7 @@ struct KeyOriginInfo
return std::equal(std::begin(a.fingerprint), std::end(a.fingerprint), std::begin(b.fingerprint)) && a.path == b.path;
}
- ADD_SERIALIZE_METHODS;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(fingerprint);
- READWRITE(path);
- }
+ SERIALIZE_METHODS(KeyOriginInfo, obj) { READWRITE(obj.fingerprint, obj.path); }
void clear()
{
diff --git a/src/script/script.h b/src/script/script.h
index 773ffbb985..b61581767f 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -412,12 +412,7 @@ public:
CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(CScriptBase, *this);
- }
+ SERIALIZE_METHODS(CScript, obj) { READWRITEAS(CScriptBase, obj); }
explicit CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
diff --git a/src/serialize.h b/src/serialize.h
index fe53eeed31..af75c50ff9 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -190,6 +190,8 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
+#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
+#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
/**
* Implement three methods for serializable objects. These are actually wrappers over
@@ -518,7 +520,16 @@ struct VarIntFormatter
}
};
-template<int Bytes>
+/** Serialization wrapper class for custom integers and enums.
+ *
+ * It permits specifying the serialized size (1 to 8 bytes) and endianness.
+ *
+ * Use the big endian mode for values that are stored in memory in native
+ * byte order, but serialized in big endian notation. This is only intended
+ * to implement serializers that are compatible with existing formats, and
+ * its use is not recommended for new data structures.
+ */
+template<int Bytes, bool BigEndian = false>
struct CustomUintFormatter
{
static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
@@ -527,52 +538,31 @@ struct CustomUintFormatter
template <typename Stream, typename I> void Ser(Stream& s, I v)
{
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
- uint64_t raw = htole64(v);
- s.write((const char*)&raw, Bytes);
+ if (BigEndian) {
+ uint64_t raw = htobe64(v);
+ s.write(((const char*)&raw) + 8 - Bytes, Bytes);
+ } else {
+ uint64_t raw = htole64(v);
+ s.write((const char*)&raw, Bytes);
+ }
}
template <typename Stream, typename I> void Unser(Stream& s, I& v)
{
- static_assert(std::numeric_limits<I>::max() >= MAX && std::numeric_limits<I>::min() <= 0, "CustomUintFormatter type too small");
+ using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
+ static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
uint64_t raw = 0;
- s.read((char*)&raw, Bytes);
- v = le64toh(raw);
+ if (BigEndian) {
+ s.read(((char*)&raw) + 8 - Bytes, Bytes);
+ v = static_cast<I>(be64toh(raw));
+ } else {
+ s.read((char*)&raw, Bytes);
+ v = static_cast<I>(le64toh(raw));
+ }
}
};
-/** Serialization wrapper class for big-endian integers.
- *
- * Use this wrapper around integer types that are stored in memory in native
- * byte order, but serialized in big endian notation. This is only intended
- * to implement serializers that are compatible with existing formats, and
- * its use is not recommended for new data structures.
- *
- * Only 16-bit types are supported for now.
- */
-template<typename I>
-class BigEndian
-{
-protected:
- I& m_val;
-public:
- explicit BigEndian(I& val) : m_val(val)
- {
- static_assert(std::is_unsigned<I>::value, "BigEndian type must be unsigned integer");
- static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 && std::numeric_limits<I>::max() == std::numeric_limits<uint16_t>::max(), "Unsupported BigEndian size");
- }
-
- template<typename Stream>
- void Serialize(Stream& s) const
- {
- ser_writedata16be(s, m_val);
- }
-
- template<typename Stream>
- void Unserialize(Stream& s)
- {
- m_val = ser_readdata16be(s);
- }
-};
+template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
/** Formatter for integers in CompactSize format. */
struct CompactSizeFormatter
@@ -626,9 +616,6 @@ public:
}
};
-template<typename I>
-BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
-
/** Formatter to serialize/deserialize vector elements using another formatter
*
* Example:
@@ -1124,6 +1111,28 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&
::UnserializeMany(s, args...);
}
+template<typename Stream, typename Type, typename Fn>
+inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
+{
+}
+
+template<typename Stream, typename Type, typename Fn>
+inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
+{
+ fn(s, std::forward<Type>(obj));
+}
+
+template<typename Stream, typename Type, typename Fn>
+inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
+{
+ fn(s, std::forward<Type>(obj));
+}
+
+template<typename Stream, typename Type, typename Fn>
+inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
+{
+}
+
template<typename I>
inline void WriteVarInt(CSizeComputer &s, I n)
{
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 8694891a51..14cf1a4a76 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -132,24 +132,7 @@ public:
return base.GetShortID(txhash);
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(header);
- READWRITE(nonce);
- size_t shorttxids_size = shorttxids.size();
- READWRITE(VARINT(shorttxids_size));
- shorttxids.resize(shorttxids_size);
- for (size_t i = 0; i < shorttxids.size(); i++) {
- uint32_t lsb = shorttxids[i] & 0xffffffff;
- uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
- READWRITE(lsb);
- READWRITE(msb);
- shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
- }
- READWRITE(prefilledtxn);
- }
+ SERIALIZE_METHODS(TestHeaderAndShortIDs, obj) { READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<CBlockHeaderAndShortTxIDs::SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); }
};
BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index c378546e8b..3d802cbeb3 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -331,24 +331,26 @@ struct StringContentsSerializer {
}
StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- if (ser_action.ForRead()) {
- str.clear();
- char c = 0;
- while (true) {
- try {
- READWRITE(c);
- str.push_back(c);
- } catch (const std::ios_base::failure&) {
- break;
- }
+ template<typename Stream>
+ void Serialize(Stream& s) const
+ {
+ for (size_t i = 0; i < str.size(); i++) {
+ s << str[i];
+ }
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream& s)
+ {
+ str.clear();
+ char c = 0;
+ while (true) {
+ try {
+ s >> c;
+ str.push_back(c);
+ } catch (const std::ios_base::failure&) {
+ break;
}
- } else {
- for (size_t i = 0; i < str.size(); i++)
- READWRITE(str[i]);
}
}
};
diff --git a/src/test/fuzz/addrdb.cpp b/src/test/fuzz/addrdb.cpp
index f21ff3fac3..524cea83fe 100644
--- a/src/test/fuzz/addrdb.cpp
+++ b/src/test/fuzz/addrdb.cpp
@@ -3,13 +3,13 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrdb.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cassert>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -30,7 +30,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
})};
break;
case 2: {
- const Optional<CBanEntry> ban_entry = ConsumeDeserializable<CBanEntry>(fuzzed_data_provider);
+ const std::optional<CBanEntry> ban_entry = ConsumeDeserializable<CBanEntry>(fuzzed_data_provider);
if (ban_entry) {
return *ban_entry;
}
diff --git a/src/test/fuzz/asmap.cpp b/src/test/fuzz/asmap.cpp
index ea56277eac..40ca01bd9f 100644
--- a/src/test/fuzz/asmap.cpp
+++ b/src/test/fuzz/asmap.cpp
@@ -23,8 +23,8 @@ static const std::vector<bool> IPV4_PREFIX_ASMAP = {
true, true, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, // Match 0x00
true, true, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, // Match 0x00
true, true, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, // Match 0x00
- true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, // Match 0xFF
- true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true // Match 0xFF
+ true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, // Match 0xFF
+ true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true // Match 0xFF
};
void test_one_input(const std::vector<uint8_t>& buffer)
diff --git a/src/test/fuzz/asmap_direct.cpp b/src/test/fuzz/asmap_direct.cpp
index 6d8a65f5ab..2d21eff9d6 100644
--- a/src/test/fuzz/asmap_direct.cpp
+++ b/src/test/fuzz/asmap_direct.cpp
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util/asmap.h>
#include <test/fuzz/fuzz.h>
+#include <util/asmap.h>
#include <cstdint>
#include <optional>
@@ -34,7 +34,9 @@ void test_one_input(const std::vector<uint8_t>& buffer)
if (SanityCheckASMap(asmap, buffer.size() - 1 - sep_pos)) {
// Verify that for valid asmaps, no prefix (except up to 7 zero padding bits) is valid.
std::vector<bool> asmap_prefix = asmap;
- while (!asmap_prefix.empty() && asmap_prefix.size() + 7 > asmap.size() && asmap_prefix.back() == false) asmap_prefix.pop_back();
+ while (!asmap_prefix.empty() && asmap_prefix.size() + 7 > asmap.size() && asmap_prefix.back() == false) {
+ asmap_prefix.pop_back();
+ }
while (!asmap_prefix.empty()) {
asmap_prefix.pop_back();
assert(!SanityCheckASMap(asmap_prefix, buffer.size() - 1 - sep_pos));
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index f30fa03e0b..91bd34a251 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -38,12 +38,17 @@ void test_one_input(const std::vector<uint8_t>& buffer)
const Consensus::Params& consensus_params = Params().GetConsensus();
BlockValidationState validation_state_pow_and_merkle;
const bool valid_incl_pow_and_merkle = CheckBlock(block, validation_state_pow_and_merkle, consensus_params, /* fCheckPOW= */ true, /* fCheckMerkleRoot= */ true);
+ assert(validation_state_pow_and_merkle.IsValid() || validation_state_pow_and_merkle.IsInvalid() || validation_state_pow_and_merkle.IsError());
+ (void)validation_state_pow_and_merkle.Error("");
BlockValidationState validation_state_pow;
const bool valid_incl_pow = CheckBlock(block, validation_state_pow, consensus_params, /* fCheckPOW= */ true, /* fCheckMerkleRoot= */ false);
+ assert(validation_state_pow.IsValid() || validation_state_pow.IsInvalid() || validation_state_pow.IsError());
BlockValidationState validation_state_merkle;
const bool valid_incl_merkle = CheckBlock(block, validation_state_merkle, consensus_params, /* fCheckPOW= */ false, /* fCheckMerkleRoot= */ true);
+ assert(validation_state_merkle.IsValid() || validation_state_merkle.IsInvalid() || validation_state_merkle.IsError());
BlockValidationState validation_state_none;
const bool valid_incl_none = CheckBlock(block, validation_state_none, consensus_params, /* fCheckPOW= */ false, /* fCheckMerkleRoot= */ false);
+ assert(validation_state_none.IsValid() || validation_state_none.IsInvalid() || validation_state_none.IsError());
if (valid_incl_pow_and_merkle) {
assert(valid_incl_pow && valid_incl_merkle && valid_incl_none);
} else if (valid_incl_merkle || valid_incl_pow) {
diff --git a/src/test/fuzz/block_header.cpp b/src/test/fuzz/block_header.cpp
index 92dcccc0e1..09c2b4a951 100644
--- a/src/test/fuzz/block_header.cpp
+++ b/src/test/fuzz/block_header.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <primitives/block.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -11,13 +10,14 @@
#include <cassert>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const Optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
+ const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
if (!block_header) {
return;
}
@@ -38,4 +38,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
block.SetNull();
assert(block.GetBlockHeader().GetHash() == mut_block_header.GetHash());
}
+ {
+ std::optional<CBlockLocator> block_locator = ConsumeDeserializable<CBlockLocator>(fuzzed_data_provider);
+ if (block_locator) {
+ (void)block_locator->IsNull();
+ block_locator->SetNull();
+ assert(block_locator->IsNull());
+ }
+ }
}
diff --git a/src/test/fuzz/blockfilter.cpp b/src/test/fuzz/blockfilter.cpp
index be9320dcbf..7232325a20 100644
--- a/src/test/fuzz/blockfilter.cpp
+++ b/src/test/fuzz/blockfilter.cpp
@@ -3,19 +3,19 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <blockfilter.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const Optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
+ const std::optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
if (!block_filter) {
return;
}
diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp
index 7039bf16c1..d955c71bc9 100644
--- a/src/test/fuzz/bloom_filter.cpp
+++ b/src/test/fuzz/bloom_filter.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bloom.h>
-#include <optional.h>
#include <primitives/transaction.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -12,6 +11,7 @@
#include <cassert>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -35,7 +35,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 1: {
- const Optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
+ const std::optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
if (!out_point) {
break;
}
@@ -46,7 +46,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 2: {
- const Optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ const std::optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
if (!u256) {
break;
}
@@ -57,7 +57,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 3: {
- const Optional<CMutableTransaction> mut_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> mut_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mut_tx) {
break;
}
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index b322516cc7..47c71850ce 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -3,18 +3,18 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- Optional<CDiskBlockIndex> disk_block_index = ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
+ std::optional<CDiskBlockIndex> disk_block_index = ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
if (!disk_block_index) {
return;
}
diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp
index 2ed097b827..c69043bb6b 100644
--- a/src/test/fuzz/checkqueue.cpp
+++ b/src/test/fuzz/checkqueue.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <checkqueue.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp
index f674efe1b1..5b45aa79d8 100644
--- a/src/test/fuzz/cuckoocache.cpp
+++ b/src/test/fuzz/cuckoocache.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <cuckoocache.h>
-#include <optional.h>
#include <script/sigcache.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp
index f29acace23..ce8700befa 100644
--- a/src/test/fuzz/fees.cpp
+++ b/src/test/fuzz/fees.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <amount.h>
-#include <optional.h>
#include <policy/fees.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
diff --git a/src/test/fuzz/flatfile.cpp b/src/test/fuzz/flatfile.cpp
index a55de77df7..95dabb8bab 100644
--- a/src/test/fuzz/flatfile.cpp
+++ b/src/test/fuzz/flatfile.cpp
@@ -3,24 +3,24 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <flatfile.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cassert>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- Optional<FlatFilePos> flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
+ std::optional<FlatFilePos> flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
if (!flat_file_pos) {
return;
}
- Optional<FlatFilePos> another_flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
+ std::optional<FlatFilePos> another_flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
if (another_flat_file_pos) {
assert((*flat_file_pos == *another_flat_file_pos) != (*flat_file_pos != *another_flat_file_pos));
}
diff --git a/src/test/fuzz/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp
index 3e20416116..a9f450b0c4 100644
--- a/src/test/fuzz/golomb_rice.cpp
+++ b/src/test/fuzz/golomb_rice.cpp
@@ -5,8 +5,8 @@
#include <blockfilter.h>
#include <serialize.h>
#include <streams.h>
-#include <test/fuzz/fuzz.h>
#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/bytevectorhash.h>
#include <util/golombrice.h>
diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp
index 5fed17c17c..6a8699fd0f 100644
--- a/src/test/fuzz/hex.cpp
+++ b/src/test/fuzz/hex.cpp
@@ -16,7 +16,8 @@
#include <string>
#include <vector>
-void initialize() {
+void initialize()
+{
static const ECCVerifyHandle verify_handle;
}
diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp
index eb8fa1d421..c44e334272 100644
--- a/src/test/fuzz/merkleblock.cpp
+++ b/src/test/fuzz/merkleblock.cpp
@@ -3,20 +3,20 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <merkleblock.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <uint256.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- Optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
+ std::optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
if (!partial_merkle_tree) {
return;
}
diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp
index dfa98a812b..fa0322a391 100644
--- a/src/test/fuzz/message.cpp
+++ b/src/test/fuzz/message.cpp
@@ -4,7 +4,6 @@
#include <chainparams.h>
#include <key_io.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
diff --git a/src/test/fuzz/net_permissions.cpp b/src/test/fuzz/net_permissions.cpp
index bfc5d21427..c071283467 100644
--- a/src/test/fuzz/net_permissions.cpp
+++ b/src/test/fuzz/net_permissions.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net_permissions.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index 201f49c87b..1cbf9b347f 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <policy/fees.h>
#include <primitives/transaction.h>
#include <test/fuzz/FuzzedDataProvider.h>
@@ -11,6 +10,7 @@
#include <txmempool.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -21,7 +21,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
while (fuzzed_data_provider.ConsumeBool()) {
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3)) {
case 0: {
- const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mtx) {
break;
}
@@ -35,7 +35,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
case 1: {
std::vector<CTxMemPoolEntry> mempool_entries;
while (fuzzed_data_provider.ConsumeBool()) {
- const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mtx) {
break;
}
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index 0343d33401..b7fc72373d 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -4,7 +4,6 @@
#include <chain.h>
#include <chainparams.h>
-#include <optional.h>
#include <pow.h>
#include <primitives/block.h>
#include <test/fuzz/FuzzedDataProvider.h>
@@ -12,6 +11,7 @@
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -28,7 +28,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
while (fuzzed_data_provider.remaining_bytes() > 0) {
- const Optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
+ const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
if (!block_header) {
continue;
}
@@ -72,7 +72,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
}
{
- const Optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ const std::optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
if (hash) {
(void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
}
diff --git a/src/test/fuzz/prevector.cpp b/src/test/fuzz/prevector.cpp
index 64920f4af5..626e187cbd 100644
--- a/src/test/fuzz/prevector.cpp
+++ b/src/test/fuzz/prevector.cpp
@@ -14,8 +14,9 @@
namespace {
-template<unsigned int N, typename T>
-class prevector_tester {
+template <unsigned int N, typename T>
+class prevector_tester
+{
typedef std::vector<T> realtype;
realtype real_vector;
realtype real_vector_alt;
@@ -27,35 +28,36 @@ class prevector_tester {
typedef typename pretype::size_type Size;
public:
- void test() const {
+ void test() const
+ {
const pretype& const_pre_vector = pre_vector;
assert(real_vector.size() == pre_vector.size());
assert(real_vector.empty() == pre_vector.empty());
for (Size s = 0; s < real_vector.size(); s++) {
- assert(real_vector[s] == pre_vector[s]);
- assert(&(pre_vector[s]) == &(pre_vector.begin()[s]));
- assert(&(pre_vector[s]) == &*(pre_vector.begin() + s));
- assert(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
+ assert(real_vector[s] == pre_vector[s]);
+ assert(&(pre_vector[s]) == &(pre_vector.begin()[s]));
+ assert(&(pre_vector[s]) == &*(pre_vector.begin() + s));
+ assert(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
}
// assert(realtype(pre_vector) == real_vector);
assert(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
assert(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
size_t pos = 0;
for (const T& v : pre_vector) {
- assert(v == real_vector[pos]);
- ++pos;
+ assert(v == real_vector[pos]);
+ ++pos;
}
for (const T& v : reverse_iterate(pre_vector)) {
- --pos;
- assert(v == real_vector[pos]);
+ --pos;
+ assert(v == real_vector[pos]);
}
for (const T& v : const_pre_vector) {
- assert(v == real_vector[pos]);
- ++pos;
+ assert(v == real_vector[pos]);
+ ++pos;
}
for (const T& v : reverse_iterate(const_pre_vector)) {
- --pos;
- assert(v == real_vector[pos]);
+ --pos;
+ assert(v == real_vector[pos]);
}
CDataStream ss1(SER_DISK, 0);
CDataStream ss2(SER_DISK, 0);
@@ -67,101 +69,120 @@ public:
}
}
- void resize(Size s) {
+ void resize(Size s)
+ {
real_vector.resize(s);
assert(real_vector.size() == s);
pre_vector.resize(s);
assert(pre_vector.size() == s);
}
- void reserve(Size s) {
+ void reserve(Size s)
+ {
real_vector.reserve(s);
assert(real_vector.capacity() >= s);
pre_vector.reserve(s);
assert(pre_vector.capacity() >= s);
}
- void insert(Size position, const T& value) {
+ void insert(Size position, const T& value)
+ {
real_vector.insert(real_vector.begin() + position, value);
pre_vector.insert(pre_vector.begin() + position, value);
}
- void insert(Size position, Size count, const T& value) {
+ void insert(Size position, Size count, const T& value)
+ {
real_vector.insert(real_vector.begin() + position, count, value);
pre_vector.insert(pre_vector.begin() + position, count, value);
}
- template<typename I>
- void insert_range(Size position, I first, I last) {
+ template <typename I>
+ void insert_range(Size position, I first, I last)
+ {
real_vector.insert(real_vector.begin() + position, first, last);
pre_vector.insert(pre_vector.begin() + position, first, last);
}
- void erase(Size position) {
+ void erase(Size position)
+ {
real_vector.erase(real_vector.begin() + position);
pre_vector.erase(pre_vector.begin() + position);
}
- void erase(Size first, Size last) {
+ void erase(Size first, Size last)
+ {
real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
}
- void update(Size pos, const T& value) {
+ void update(Size pos, const T& value)
+ {
real_vector[pos] = value;
pre_vector[pos] = value;
}
- void push_back(const T& value) {
+ void push_back(const T& value)
+ {
real_vector.push_back(value);
pre_vector.push_back(value);
}
- void pop_back() {
+ void pop_back()
+ {
real_vector.pop_back();
pre_vector.pop_back();
}
- void clear() {
+ void clear()
+ {
real_vector.clear();
pre_vector.clear();
}
- void assign(Size n, const T& value) {
+ void assign(Size n, const T& value)
+ {
real_vector.assign(n, value);
pre_vector.assign(n, value);
}
- Size size() const {
+ Size size() const
+ {
return real_vector.size();
}
- Size capacity() const {
+ Size capacity() const
+ {
return pre_vector.capacity();
}
- void shrink_to_fit() {
+ void shrink_to_fit()
+ {
pre_vector.shrink_to_fit();
}
- void swap() {
+ void swap()
+ {
real_vector.swap(real_vector_alt);
pre_vector.swap(pre_vector_alt);
}
- void move() {
+ void move()
+ {
real_vector = std::move(real_vector_alt);
real_vector_alt.clear();
pre_vector = std::move(pre_vector_alt);
pre_vector_alt.clear();
}
- void copy() {
+ void copy()
+ {
real_vector = real_vector_alt;
pre_vector = pre_vector_alt;
}
- void resize_uninitialized(realtype values) {
+ void resize_uninitialized(realtype values)
+ {
size_t r = values.size();
size_t s = real_vector.size() / 2;
if (real_vector.capacity() < s + r) {
@@ -181,7 +202,7 @@ public:
}
};
-}
+} // namespace
void test_one_input(const std::vector<uint8_t>& buffer)
{
diff --git a/src/test/fuzz/primitives_transaction.cpp b/src/test/fuzz/primitives_transaction.cpp
index 2e5ba6bdb0..4a0f920f58 100644
--- a/src/test/fuzz/primitives_transaction.cpp
+++ b/src/test/fuzz/primitives_transaction.cpp
@@ -2,13 +2,13 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <primitives/transaction.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -16,7 +16,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CScript script = ConsumeScript(fuzzed_data_provider);
- const Optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
+ const std::optional<COutPoint> out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
if (out_point) {
const CTxIn tx_in{*out_point, script, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
(void)tx_in;
@@ -24,8 +24,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
const CTxOut tx_out_1{ConsumeMoney(fuzzed_data_provider), script};
const CTxOut tx_out_2{ConsumeMoney(fuzzed_data_provider), ConsumeScript(fuzzed_data_provider)};
assert((tx_out_1 == tx_out_2) != (tx_out_1 != tx_out_2));
- const Optional<CMutableTransaction> mutable_tx_1 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
- const Optional<CMutableTransaction> mutable_tx_2 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> mutable_tx_1 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> mutable_tx_2 = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (mutable_tx_1 && mutable_tx_2) {
const CTransaction tx_1{*mutable_tx_1};
const CTransaction tx_2{*mutable_tx_2};
diff --git a/src/test/fuzz/protocol.cpp b/src/test/fuzz/protocol.cpp
index 954471de6c..78df0f89e7 100644
--- a/src/test/fuzz/protocol.cpp
+++ b/src/test/fuzz/protocol.cpp
@@ -2,20 +2,20 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <protocol.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <cstdint>
+#include <optional>
#include <stdexcept>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const Optional<CInv> inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
+ const std::optional<CInv> inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
if (!inv) {
return;
}
@@ -24,7 +24,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
} catch (const std::out_of_range&) {
}
(void)inv->ToString();
- const Optional<CInv> another_inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
+ const std::optional<CInv> another_inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
if (!another_inv) {
return;
}
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index eb54b05df9..1fd88a5f7b 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <optional.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <sync.h>
@@ -12,19 +11,20 @@
#include <txmempool.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mtx) {
return;
}
CTxMemPool pool;
while (fuzzed_data_provider.ConsumeBool()) {
- const Optional<CMutableTransaction> another_mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ const std::optional<CMutableTransaction> another_mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!another_mtx) {
break;
}
diff --git a/src/test/fuzz/rolling_bloom_filter.cpp b/src/test/fuzz/rolling_bloom_filter.cpp
index 3b37321977..623b8cff3a 100644
--- a/src/test/fuzz/rolling_bloom_filter.cpp
+++ b/src/test/fuzz/rolling_bloom_filter.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bloom.h>
-#include <optional.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
@@ -11,6 +10,7 @@
#include <cassert>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -32,7 +32,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 1: {
- const Optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
+ const std::optional<uint256> u256 = ConsumeDeserializable<uint256>(fuzzed_data_provider);
if (!u256) {
break;
}
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index de82122dd6..e0c4ad7eb7 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -21,6 +21,11 @@
#include <univalue.h>
#include <util/memory.h>
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <vector>
+
void initialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
@@ -32,7 +37,7 @@ void initialize()
void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const Optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
+ const std::optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
if (!script_opt) return;
const CScript script{*script_opt};
@@ -101,7 +106,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
}
- const Optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
+ const std::optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
if (other_script) {
{
CScript script_mut{script};
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 49bee0e81f..3c1f911f7e 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -119,4 +119,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
int64_t amount_out;
(void)ParseFixedPoint(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1024), &amount_out);
}
+ {
+ (void)Untranslated(random_string_1);
+ const bilingual_str bs1{random_string_1, random_string_2};
+ const bilingual_str bs2{random_string_2, random_string_1};
+ (void)(bs1 + bs2);
+ }
}
diff --git a/src/test/fuzz/strprintf.cpp b/src/test/fuzz/strprintf.cpp
index d5be1070bd..29064bc45c 100644
--- a/src/test/fuzz/strprintf.cpp
+++ b/src/test/fuzz/strprintf.cpp
@@ -6,6 +6,7 @@
#include <test/fuzz/fuzz.h>
#include <tinyformat.h>
#include <util/strencodings.h>
+#include <util/translation.h>
#include <algorithm>
#include <cstdint>
@@ -16,6 +17,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string format_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
+ const bilingual_str bilingual_string{format_string, format_string};
const int digits_in_format_specifier = std::count_if(format_string.begin(), format_string.end(), IsDigit);
@@ -47,50 +49,62 @@ void test_one_input(const std::vector<uint8_t>& buffer)
try {
(void)strprintf(format_string, (signed char*)nullptr);
+ (void)tinyformat::format(bilingual_string, (signed char*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (unsigned char*)nullptr);
+ (void)tinyformat::format(bilingual_string, (unsigned char*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (void*)nullptr);
+ (void)tinyformat::format(bilingual_string, (void*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (bool*)nullptr);
+ (void)tinyformat::format(bilingual_string, (bool*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (float*)nullptr);
+ (void)tinyformat::format(bilingual_string, (float*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (double*)nullptr);
+ (void)tinyformat::format(bilingual_string, (double*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (int16_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (int16_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (uint16_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (uint16_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (int32_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (int32_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (uint32_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (uint32_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (int64_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (int64_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
try {
(void)strprintf(format_string, (uint64_t*)nullptr);
+ (void)tinyformat::format(bilingual_string, (uint64_t*)nullptr);
} catch (const tinyformat::format_error&) {
}
@@ -98,21 +112,27 @@ void test_one_input(const std::vector<uint8_t>& buffer)
switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 5)) {
case 0:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32));
break;
case 1:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeRandomLengthString(32).c_str());
break;
case 2:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<signed char>());
break;
case 3:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<unsigned char>());
break;
case 4:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<char>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<char>());
break;
case 5:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeBool());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeBool());
break;
}
} catch (const tinyformat::format_error&) {
@@ -138,27 +158,35 @@ void test_one_input(const std::vector<uint8_t>& buffer)
switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 7)) {
case 0:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<float>());
break;
case 1:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeFloatingPoint<double>());
break;
case 2:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int16_t>());
break;
case 3:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint16_t>());
break;
case 4:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int32_t>());
break;
case 5:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
break;
case 6:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<int64_t>());
break;
case 7:
(void)strprintf(format_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ (void)tinyformat::format(bilingual_string, fuzzed_data_provider.ConsumeIntegral<uint64_t>());
break;
}
} catch (const tinyformat::format_error&) {
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index 501bb1de5a..f72d9380eb 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -9,7 +9,6 @@
#include <arith_uint256.h>
#include <attributes.h>
#include <consensus/consensus.h>
-#include <optional.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <serialize.h>
@@ -21,6 +20,7 @@
#include <version.h>
#include <cstdint>
+#include <optional>
#include <string>
#include <vector>
@@ -52,7 +52,7 @@ NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProv
}
template <typename T>
-NODISCARD inline Optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
+NODISCARD inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);
CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
@@ -60,7 +60,7 @@ NODISCARD inline Optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_da
try {
ds >> obj;
} catch (const std::ios_base::failure&) {
- return nullopt;
+ return std::nullopt;
}
return obj;
}
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index d1f60e8972..978a7bee4d 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -28,6 +28,8 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
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(GetRandMicros(std::chrono::hours{1}).count(), 2917185654);
+ BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2144374);
}
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
@@ -47,6 +49,8 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
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(GetRandMicros(std::chrono::hours{1}) != std::chrono::microseconds{2917185654});
+ BOOST_CHECK(GetRandMillis(std::chrono::hours{1}) != std::chrono::milliseconds{2144374});
}
{
FastRandomContext ctx3, ctx4;
@@ -87,7 +91,7 @@ BOOST_AUTO_TEST_CASE(stdrandom_test)
BOOST_CHECK(x >= 3);
BOOST_CHECK(x <= 9);
- std::vector<int> test{1,2,3,4,5,6,7,8,9,10};
+ std::vector<int> test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::shuffle(test.begin(), test.end(), ctx);
for (int j = 1; j <= 10; ++j) {
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
@@ -97,7 +101,6 @@ BOOST_AUTO_TEST_CASE(stdrandom_test)
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
}
}
-
}
/** Test that Shuffle reaches every permutation with equal probability. */
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 9a6c721ab8..c2328f931c 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -29,15 +29,13 @@ public:
memcpy(charstrval, charstrvalin, sizeof(charstrval));
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval);
- READWRITE(boolval);
- READWRITE(stringval);
- READWRITE(charstrval);
- READWRITE(txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestSingle, obj)
+ {
+ READWRITE(obj.intval);
+ READWRITE(obj.boolval);
+ READWRITE(obj.stringval);
+ READWRITE(obj.charstrval);
+ READWRITE(obj.txval);
}
bool operator==(const CSerializeMethodsTestSingle& rhs)
@@ -54,11 +52,10 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
{
public:
using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
- ADD_SERIALIZE_METHODS;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval, boolval, stringval, charstrval, txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestMany, obj)
+ {
+ READWRITE(obj.intval, obj.boolval, obj.stringval, obj.charstrval, obj.txval);
}
};
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index c345f1eafb..899f054b83 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -32,7 +32,7 @@ struct MinerTestingSetup : public RegTestingSetup {
BOOST_FIXTURE_TEST_SUITE(validation_block_tests, MinerTestingSetup)
-struct TestSubscriber : public CValidationInterface {
+struct TestSubscriber final : public CValidationInterface {
uint256 m_expected_tip;
explicit TestSubscriber(uint256 tip) : m_expected_tip(tip) {}
@@ -175,8 +175,8 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
LOCK(cs_main);
initial_tip = ::ChainActive().Tip();
}
- TestSubscriber sub(initial_tip->GetBlockHash());
- RegisterValidationInterface(&sub);
+ auto sub = std::make_shared<TestSubscriber>(initial_tip->GetBlockHash());
+ RegisterSharedValidationInterface(sub);
// create a bunch of threads that repeatedly process a block generated above at random
// this will create parallelism and randomness inside validation - the ValidationInterface
@@ -204,14 +204,12 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
for (auto& t : threads) {
t.join();
}
- while (GetMainSignals().CallbacksPending() > 0) {
- UninterruptibleSleep(std::chrono::milliseconds{100});
- }
+ SyncWithValidationInterfaceQueue();
- UnregisterValidationInterface(&sub);
+ UnregisterSharedValidationInterface(sub);
LOCK(cs_main);
- BOOST_CHECK_EQUAL(sub.m_expected_tip, ::ChainActive().Tip()->GetBlockHash());
+ BOOST_CHECK_EQUAL(sub->m_expected_tip, ::ChainActive().Tip()->GetBlockHash());
}
/**
diff --git a/src/test/validationinterface_tests.cpp b/src/test/validationinterface_tests.cpp
index 208be92852..ceba689e52 100644
--- a/src/test/validationinterface_tests.cpp
+++ b/src/test/validationinterface_tests.cpp
@@ -12,6 +12,40 @@
BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup)
+struct TestSubscriberNoop final : public CValidationInterface {
+ void BlockChecked(const CBlock&, const BlockValidationState&) override {}
+};
+
+BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
+{
+ std::atomic<bool> generate{true};
+
+ // Start thread to generate notifications
+ std::thread gen{[&] {
+ const CBlock block_dummy;
+ BlockValidationState state_dummy;
+ while (generate) {
+ GetMainSignals().BlockChecked(block_dummy, state_dummy);
+ }
+ }};
+
+ // Start thread to consume notifications
+ std::thread sub{[&] {
+ // keep going for about 1 sec, which is 250k iterations
+ for (int i = 0; i < 250000; i++) {
+ auto sub = std::make_shared<TestSubscriberNoop>();
+ RegisterSharedValidationInterface(sub);
+ UnregisterSharedValidationInterface(sub);
+ }
+ // tell the other thread we are done
+ generate = false;
+ }};
+
+ gen.join();
+ sub.join();
+ BOOST_CHECK(!generate);
+}
+
class TestInterface : public CValidationInterface
{
public:
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 071aa1336b..129697f0e7 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -36,19 +36,7 @@ struct CoinEntry {
char key;
explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
- template<typename Stream>
- void Serialize(Stream &s) const {
- s << key;
- s << outpoint->hash;
- s << VARINT(outpoint->n);
- }
-
- template<typename Stream>
- void Unserialize(Stream& s) {
- s >> key;
- s >> outpoint->hash;
- s >> VARINT(outpoint->n);
- }
+ SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
};
}
diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp
index bb41154afc..15795bd67f 100644
--- a/src/ui_interface.cpp
+++ b/src/ui_interface.cpp
@@ -49,8 +49,8 @@ void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { re
void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); }
void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
-void CClientUIInterface::NotifyBlockTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(b, i); }
-void CClientUIInterface::NotifyHeaderTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(b, i); }
+void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); }
+void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(s, i); }
void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }
bool InitError(const bilingual_str& str)
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 9c49451e84..d45811178f 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -11,6 +11,7 @@
#include <string>
class CBlockIndex;
+enum class SynchronizationState;
struct bilingual_str;
namespace boost {
@@ -110,10 +111,10 @@ public:
ADD_SIGNALS_DECL_WRAPPER(ShowProgress, void, const std::string& title, int nProgress, bool resume_possible);
/** New block has been accepted */
- ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, bool, const CBlockIndex*);
+ ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, SynchronizationState, const CBlockIndex*);
/** Best header has changed */
- ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, bool, const CBlockIndex*);
+ ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, SynchronizationState, const CBlockIndex*);
/** Banlist did change. */
ADD_SIGNALS_DECL_WRAPPER(BannedListChanged, void, void);
diff --git a/src/validation.cpp b/src/validation.cpp
index 8a454c8d1b..a9dfa5c171 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2800,6 +2800,13 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
return true;
}
+static SynchronizationState GetSynchronizationState(bool init)
+{
+ if (!init) return SynchronizationState::POST_INIT;
+ if (::fReindex) return SynchronizationState::INIT_REINDEX;
+ return SynchronizationState::INIT_DOWNLOAD;
+}
+
static bool NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
bool fNotify = false;
bool fInitialBlockDownload = false;
@@ -2817,7 +2824,7 @@ static bool NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
}
// Send block tip changed notifications without cs_main
if (fNotify) {
- uiInterface.NotifyHeaderTip(fInitialBlockDownload, pindexHeader);
+ uiInterface.NotifyHeaderTip(GetSynchronizationState(fInitialBlockDownload), pindexHeader);
}
return fNotify;
}
@@ -2906,7 +2913,7 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
// Always notify the UI if a new block tip was connected
- uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
+ uiInterface.NotifyBlockTip(GetSynchronizationState(fInitialDownload), pindexNewTip);
}
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
@@ -3097,7 +3104,7 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, const CChainParam
// Only notify about a new block tip if the active chain was modified.
if (pindex_was_in_chain) {
- uiInterface.NotifyBlockTip(IsInitialBlockDownload(), to_mark_failed->pprev);
+ uiInterface.NotifyBlockTip(GetSynchronizationState(IsInitialBlockDownload()), to_mark_failed->pprev);
}
return true;
}
diff --git a/src/validation.h b/src/validation.h
index c4a5cc4593..cbab65e79e 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -103,6 +103,13 @@ struct BlockHasher
size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
};
+/** Current sync state passed to tip changed callbacks. */
+enum class SynchronizationState {
+ INIT_REINDEX,
+ INIT_DOWNLOAD,
+ POST_INIT
+};
+
extern RecursiveMutex cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 11000774c0..9437f9c817 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -89,22 +89,26 @@ public:
static CMainSignals g_signals;
-void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
+void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler)
+{
assert(!m_internals);
m_internals.reset(new MainSignalsInstance(&scheduler));
}
-void CMainSignals::UnregisterBackgroundSignalScheduler() {
+void CMainSignals::UnregisterBackgroundSignalScheduler()
+{
m_internals.reset(nullptr);
}
-void CMainSignals::FlushBackgroundCallbacks() {
+void CMainSignals::FlushBackgroundCallbacks()
+{
if (m_internals) {
m_internals->m_schedulerClient.EmptyQueue();
}
}
-size_t CMainSignals::CallbacksPending() {
+size_t CMainSignals::CallbacksPending()
+{
if (!m_internals) return 0;
return m_internals->m_schedulerClient.CallbacksPending();
}
@@ -114,10 +118,11 @@ CMainSignals& GetMainSignals()
return g_signals;
}
-void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> pwalletIn) {
- // Each connection captures pwalletIn to ensure that each callback is
- // executed before pwalletIn is destroyed. For more details see #18338.
- g_signals.m_internals->Register(std::move(pwalletIn));
+void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
+{
+ // Each connection captures the shared_ptr to ensure that each callback is
+ // executed before the subscriber is destroyed. For more details see #18338.
+ g_signals.m_internals->Register(std::move(callbacks));
}
void RegisterValidationInterface(CValidationInterface* callbacks)
@@ -132,24 +137,28 @@ void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> c
UnregisterValidationInterface(callbacks.get());
}
-void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
+void UnregisterValidationInterface(CValidationInterface* callbacks)
+{
if (g_signals.m_internals) {
- g_signals.m_internals->Unregister(pwalletIn);
+ g_signals.m_internals->Unregister(callbacks);
}
}
-void UnregisterAllValidationInterfaces() {
+void UnregisterAllValidationInterfaces()
+{
if (!g_signals.m_internals) {
return;
}
g_signals.m_internals->Clear();
}
-void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
+void CallFunctionInValidationInterfaceQueue(std::function<void()> func)
+{
g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
}
-void SyncWithValidationInterfaceQueue() {
+void SyncWithValidationInterfaceQueue()
+{
AssertLockNotHeld(cs_main);
// Block until the validation queue drains
std::promise<void> promise;
diff --git a/src/validationinterface.h b/src/validationinterface.h
index cb0204a555..9c23965bc1 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -22,20 +22,20 @@ class CValidationInterface;
class uint256;
class CScheduler;
-// These functions dispatch to one or all registered wallets
-
-/** Register a wallet to receive updates from core */
-void RegisterValidationInterface(CValidationInterface* pwalletIn);
-/** Unregister a wallet from core */
-void UnregisterValidationInterface(CValidationInterface* pwalletIn);
-/** Unregister all wallets from core */
+/** Register subscriber */
+void RegisterValidationInterface(CValidationInterface* callbacks);
+/** Unregister subscriber. DEPRECATED. This is not safe to use when the RPC server or main message handler thread is running. */
+void UnregisterValidationInterface(CValidationInterface* callbacks);
+/** Unregister all subscribers */
void UnregisterAllValidationInterfaces();
// Alternate registration functions that release a shared_ptr after the last
// notification is sent. These are useful for race-free cleanup, since
// unregistration is nonblocking and can return before the last notification is
// processed.
+/** Register subscriber */
void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
+/** Unregister subscriber */
void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
/**
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 250a4503f5..2a57248705 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1482,10 +1482,9 @@ UniValue listtransactions(const JSONRPCRequest& request)
static UniValue listsinceblock(const JSONRPCRequest& request)
{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- const CWallet* const pwallet = wallet.get();
+ std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ if (!EnsureWalletIsAvailable(pwallet.get(), request.fHelp)) {
return NullUniValue;
}
@@ -1542,11 +1541,12 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
},
}.Check(request);
+ const CWallet& wallet = *pwallet;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
- pwallet->BlockUntilSyncedToCurrentChain();
+ wallet.BlockUntilSyncedToCurrentChain();
- LOCK(pwallet->cs_wallet);
+ LOCK(wallet.cs_wallet);
// The way the 'height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
Optional<int> height = MakeOptional(false, int()); // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
@@ -1557,9 +1557,9 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
uint256 blockId;
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
blockId = ParseHashV(request.params[0], "blockhash");
- height.emplace();
- altheight.emplace();
- if (!pwallet->chain().findCommonAncestor(blockId, pwallet->GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) {
+ height = int{};
+ altheight = int{};
+ if (!wallet.chain().findCommonAncestor(blockId, wallet.GetLastBlockHash(), /* ancestor out */ FoundBlock().height(*height), /* blockId out */ FoundBlock().height(*altheight))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
}
@@ -1572,21 +1572,21 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
}
}
- if (ParseIncludeWatchonly(request.params[2], *pwallet)) {
+ if (ParseIncludeWatchonly(request.params[2], wallet)) {
filter |= ISMINE_WATCH_ONLY;
}
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
- int depth = height ? pwallet->GetLastBlockHeight() + 1 - *height : -1;
+ int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
UniValue transactions(UniValue::VARR);
- for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : wallet.mapWallet) {
const CWalletTx& tx = pairWtx.second;
if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
- ListTransactions(pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
+ ListTransactions(&wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
}
}
@@ -1595,15 +1595,15 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
UniValue removed(UniValue::VARR);
while (include_removed && altheight && *altheight > *height) {
CBlock block;
- if (!pwallet->chain().findBlock(blockId, FoundBlock().data(block)) || block.IsNull()) {
+ if (!wallet.chain().findBlock(blockId, FoundBlock().data(block)) || block.IsNull()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
}
for (const CTransactionRef& tx : block.vtx) {
- auto it = pwallet->mapWallet.find(tx->GetHash());
- if (it != pwallet->mapWallet.end()) {
+ auto it = wallet.mapWallet.find(tx->GetHash());
+ if (it != wallet.mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(pwallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
+ ListTransactions(&wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
}
}
blockId = block.hashPrevBlock;
@@ -1611,7 +1611,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
}
uint256 lastblock;
- CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(pwallet->GetLastBlockHash(), pwallet->GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
+ CHECK_NONFATAL(wallet.chain().findAncestorByHeight(wallet.GetLastBlockHash(), wallet.GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
UniValue ret(UniValue::VOBJ);
ret.pushKV("transactions", transactions);