aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.clang-format1
-rw-r--r--src/Makefile.am10
-rw-r--r--src/Makefile.bench.include2
-rw-r--r--src/Makefile.qt.include42
-rw-r--r--src/Makefile.qttest.include14
-rw-r--r--src/Makefile.test.include33
-rw-r--r--src/arith_uint256.cpp2
-rw-r--r--src/arith_uint256.h2
-rw-r--r--src/bech32.cpp8
-rw-r--r--src/bench/base58.cpp1
-rw-r--r--src/bench/bench.h1
-rw-r--r--src/bench/bench_bitcoin.cpp7
-rw-r--r--src/bench/block_assemble.cpp1
-rw-r--r--src/bench/chacha20.cpp1
-rw-r--r--src/bench/chacha_poly_aead.cpp1
-rw-r--r--src/bench/crypto_hash.cpp1
-rw-r--r--src/bench/duplicate_inputs.cpp3
-rw-r--r--src/bench/lockedpool.cpp1
-rw-r--r--src/bench/mempool_eviction.cpp2
-rw-r--r--src/bench/poly1305.cpp1
-rw-r--r--src/bench/rollingbloom.cpp1
-rw-r--r--src/bench/rpc_blockchain.cpp1
-rw-r--r--src/bench/rpc_mempool.cpp2
-rw-r--r--src/bench/verify_script.cpp40
-rw-r--r--src/bitcoin-cli.cpp16
-rw-r--r--src/bitcoin-tx.cpp1
-rw-r--r--src/bitcoin-wallet.cpp2
-rw-r--r--src/bitcoind.cpp1
-rw-r--r--src/blockencodings.h1
-rw-r--r--src/chain.h72
-rw-r--r--src/compat/byteswap.h9
-rw-r--r--src/compressor.cpp1
-rw-r--r--src/consensus/merkle.h2
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/consensus/tx_check.cpp35
-rw-r--r--src/consensus/tx_check.h2
-rw-r--r--src/consensus/tx_verify.cpp10
-rw-r--r--src/consensus/validation.h19
-rw-r--r--src/crypto/aes.cpp1
-rw-r--r--src/crypto/chacha_poly_aead.cpp1
-rw-r--r--src/crypto/sha256.cpp1
-rw-r--r--src/crypto/sha256_shani.cpp1
-rw-r--r--src/dbwrapper.h1
-rw-r--r--src/dummywallet.cpp5
-rw-r--r--src/httprpc.cpp2
-rw-r--r--src/httprpc.h2
-rw-r--r--src/httpserver.cpp2
-rw-r--r--src/httpserver.h1
-rw-r--r--src/index/base.h1
-rw-r--r--src/init.cpp2
-rw-r--r--src/interfaces/chain.cpp7
-rw-r--r--src/interfaces/chain.h5
-rw-r--r--src/interfaces/node.cpp17
-rw-r--r--src/interfaces/node.h4
-rw-r--r--src/interfaces/wallet.cpp23
-rw-r--r--src/interfaces/wallet.h5
-rw-r--r--src/key.h19
-rw-r--r--src/key_io.cpp1
-rw-r--r--src/logging.cpp24
-rw-r--r--src/miner.cpp2
-rw-r--r--src/net.cpp10
-rw-r--r--src/net_processing.cpp44
-rw-r--r--src/netaddress.h1
-rw-r--r--src/node/coinstats.cpp2
-rw-r--r--src/node/transaction.cpp1
-rw-r--r--src/node/transaction.h1
-rw-r--r--src/noui.cpp2
-rw-r--r--src/outputtype.cpp6
-rw-r--r--src/policy/fees.cpp1
-rw-r--r--src/prevector.h1
-rw-r--r--src/primitives/block.cpp1
-rw-r--r--src/protocol.h1
-rw-r--r--src/psbt.cpp1
-rw-r--r--src/pubkey.h25
-rw-r--r--src/qt/README.md2
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp9
-rw-r--r--src/qt/bitcoinamountfield.cpp2
-rw-r--r--src/qt/bitcoingui.cpp10
-rw-r--r--src/qt/clientmodel.cpp31
-rw-r--r--src/qt/clientmodel.h4
-rw-r--r--src/qt/coincontroldialog.cpp1
-rw-r--r--src/qt/forms/openuridialog.ui22
-rw-r--r--src/qt/forms/sendcoinsentry.ui9
-rw-r--r--src/qt/forms/signverifymessagedialog.ui21
-rw-r--r--src/qt/modaloverlay.cpp6
-rw-r--r--src/qt/modaloverlay.h2
-rw-r--r--src/qt/openuridialog.cpp9
-rw-r--r--src/qt/openuridialog.h3
-rw-r--r--src/qt/optionsmodel.cpp20
-rw-r--r--src/qt/optionsmodel.h5
-rw-r--r--src/qt/paymentrequest.proto48
-rw-r--r--src/qt/paymentrequestplus.cpp213
-rw-r--r--src/qt/paymentrequestplus.h52
-rw-r--r--src/qt/paymentserver.cpp553
-rw-r--r--src/qt/paymentserver.h55
-rw-r--r--src/qt/peertablemodel.cpp1
-rw-r--r--src/qt/qrimagewidget.cpp1
-rw-r--r--src/qt/rpcconsole.cpp16
-rw-r--r--src/qt/rpcconsole.h12
-rw-r--r--src/qt/sendcoinsdialog.cpp21
-rw-r--r--src/qt/sendcoinsentry.cpp36
-rw-r--r--src/qt/signverifymessagedialog.cpp1
-rw-r--r--src/qt/splashscreen.cpp1
-rw-r--r--src/qt/test/compattests.cpp4
-rw-r--r--src/qt/test/paymentrequestdata.h465
-rw-r--r--src/qt/test/paymentservertests.cpp216
-rw-r--r--src/qt/test/paymentservertests.h35
-rw-r--r--src/qt/test/test_main.cpp9
-rw-r--r--src/qt/transactiondesc.cpp11
-rw-r--r--src/qt/utilitydialog.cpp3
-rw-r--r--src/qt/walletcontroller.cpp11
-rw-r--r--src/qt/walletcontroller.h2
-rw-r--r--src/qt/walletframe.cpp1
-rw-r--r--src/qt/walletmodel.cpp61
-rw-r--r--src/qt/walletmodel.h33
-rw-r--r--src/qt/walletmodeltransaction.cpp19
-rw-r--r--src/qt/walletmodeltransaction.h1
-rw-r--r--src/qt/winshutdownmonitor.cpp13
-rw-r--r--src/random.cpp8
-rw-r--r--src/rest.cpp1
-rw-r--r--src/rpc/blockchain.cpp4
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/rpc/misc.cpp9
-rw-r--r--src/rpc/net.cpp1
-rw-r--r--src/rpc/rawtransaction.cpp10
-rw-r--r--src/rpc/server.cpp2
-rw-r--r--src/rpc/server.h2
-rw-r--r--src/rpc/util.h13
-rw-r--r--src/script/descriptor.cpp36
-rw-r--r--src/script/descriptor.h78
-rw-r--r--src/script/interpreter.h1
-rw-r--r--src/script/keyorigin.h1
-rw-r--r--src/script/sign.h1
-rw-r--r--src/script/standard.h1
-rw-r--r--src/serialize.h1
-rw-r--r--src/streams.h2
-rw-r--r--src/sync.cpp2
-rw-r--r--src/test/bip32_tests.cpp17
-rw-r--r--src/test/blockfilter_index_tests.cpp20
-rw-r--r--src/test/compress_tests.cpp74
-rw-r--r--src/test/dbwrapper_tests.cpp80
-rw-r--r--src/test/fs_tests.cpp2
-rw-r--r--src/test/fuzz/FuzzedDataProvider.h245
-rw-r--r--src/test/fuzz/descriptor_parse.cpp22
-rw-r--r--src/test/fuzz/deserialize.cpp7
-rw-r--r--src/test/fuzz/eval_script.cpp30
-rw-r--r--src/test/fuzz/fuzz.cpp16
-rw-r--r--src/test/fuzz/fuzz.h2
-rw-r--r--src/test/fuzz/script.cpp64
-rw-r--r--src/test/fuzz/spanparsing.cpp30
-rw-r--r--src/test/fuzz/transaction.cpp7
-rw-r--r--src/test/key_properties.cpp1
-rw-r--r--src/test/lib/transaction_utils.cpp39
-rw-r--r--src/test/lib/transaction_utils.h19
-rw-r--r--src/test/policyestimator_tests.cpp1
-rw-r--r--src/test/pow_tests.cpp1
-rw-r--r--src/test/script_tests.cpp35
-rw-r--r--src/test/skiplist_tests.cpp1
-rw-r--r--src/test/streams_tests.cpp1
-rw-r--r--src/test/txindex_tests.cpp1
-rw-r--r--src/test/util_tests.cpp124
-rw-r--r--src/threadinterrupt.h1
-rw-r--r--src/torcontrol.h1
-rw-r--r--src/txdb.cpp3
-rw-r--r--src/txdb.h1
-rw-r--r--src/txmempool.h1
-rw-r--r--src/ui_interface.h1
-rw-r--r--src/uint256.cpp1
-rw-r--r--src/uint256.h1
-rw-r--r--src/util/check.h41
-rw-r--r--src/util/moneystr.cpp1
-rw-r--r--src/util/moneystr.h1
-rw-r--r--src/util/string.h1
-rw-r--r--src/util/system.cpp10
-rw-r--r--src/util/threadnames.cpp1
-rw-r--r--src/util/translation.h1
-rw-r--r--src/util/validation.cpp5
-rw-r--r--src/util/vector.h51
-rw-r--r--src/validation.cpp126
-rw-r--r--src/validation.h10
-rw-r--r--src/validationinterface.cpp2
-rw-r--r--src/wallet/crypter.cpp3
-rw-r--r--src/wallet/crypter.h1
-rw-r--r--src/wallet/db.cpp6
-rw-r--r--src/wallet/db.h4
-rw-r--r--src/wallet/feebumper.cpp92
-rw-r--r--src/wallet/feebumper.h8
-rw-r--r--src/wallet/fees.cpp1
-rw-r--r--src/wallet/init.cpp3
-rw-r--r--src/wallet/ismine.cpp1
-rw-r--r--src/wallet/load.cpp13
-rw-r--r--src/wallet/psbtwallet.h2
-rw-r--r--src/wallet/rpcdump.cpp1
-rw-r--r--src/wallet/rpcwallet.cpp43
-rw-r--r--src/wallet/test/wallet_tests.cpp4
-rw-r--r--src/wallet/wallet.cpp188
-rw-r--r--src/wallet/wallet.h22
-rw-r--r--src/wallet/walletdb.cpp9
-rw-r--r--src/wallet/walletdb.h5
-rw-r--r--src/wallet/wallettool.h1
-rw-r--r--src/warnings.h1
-rw-r--r--src/zmq/zmqconfig.h2
-rw-r--r--src/zmq/zmqnotificationinterface.cpp1
-rw-r--r--src/zmq/zmqnotificationinterface.h2
205 files changed, 1484 insertions, 2829 deletions
diff --git a/src/.clang-format b/src/.clang-format
index 38e19edf2c..aae039dd77 100644
--- a/src/.clang-format
+++ b/src/.clang-format
@@ -5,6 +5,7 @@ AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
diff --git a/src/Makefile.am b/src/Makefile.am
index eec84122ae..82cc19d57c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,7 +19,7 @@ else
LIBUNIVALUE = $(UNIVALUE_LIBS)
endif
-BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
+BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS)
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS)
@@ -206,6 +206,7 @@ BITCOIN_CORE_H = \
undo.h \
util/bip32.h \
util/bytevectorhash.h \
+ util/check.h \
util/error.h \
util/fees.h \
util/spanparsing.h \
@@ -220,6 +221,7 @@ BITCOIN_CORE_H = \
util/translation.h \
util/url.h \
util/validation.h \
+ util/vector.h \
validation.h \
validationinterface.h \
versionbits.h \
@@ -700,12 +702,6 @@ if HARDEN
$(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS)
endif
-if ENABLE_BIP70
-%.pb.cc %.pb.h: %.proto
- @test -f $(PROTOC)
- $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
-endif
-
if EMBEDDED_LEVELDB
include Makefile.leveldb.include
endif
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index e421b377a0..38143e32b9 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -39,6 +39,8 @@ bench_bench_bitcoin_SOURCES = \
bench/lockedpool.cpp \
bench/poly1305.cpp \
bench/prevector.cpp \
+ test/lib/transaction_utils.h \
+ test/lib/transaction_utils.cpp \
test/setup_common.h \
test/setup_common.cpp \
test/util.h \
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 9ab7f02e22..13b1470b58 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -95,16 +95,6 @@ QT_QRC = qt/bitcoin.qrc
QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp
QT_QRC_LOCALE = qt/bitcoin_locale.qrc
-if ENABLE_BIP70
-PROTOBUF_CC = qt/paymentrequest.pb.cc
-PROTOBUF_H = qt/paymentrequest.pb.h
-PROTOBUF_PROTO = qt/paymentrequest.proto
-else
-PROTOBUF_CC =
-PROTOBUF_H =
-PROTOBUF_PROTO =
-endif
-
BITCOIN_QT_H = \
qt/addressbookpage.h \
qt/addresstablemodel.h \
@@ -134,7 +124,6 @@ BITCOIN_QT_H = \
qt/optionsdialog.h \
qt/optionsmodel.h \
qt/overviewpage.h \
- qt/paymentrequestplus.h \
qt/paymentserver.h \
qt/peertablemodel.h \
qt/platformstyle.h \
@@ -269,18 +258,12 @@ BITCOIN_QT_WALLET_CPP = \
qt/walletmodeltransaction.cpp \
qt/walletview.cpp
-BITCOIN_QT_WALLET_BIP70_CPP = \
- qt/paymentrequestplus.cpp
-
BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP)
if TARGET_WINDOWS
BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP)
endif
if ENABLE_WALLET
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP)
-if ENABLE_BIP70
-BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP)
-endif # ENABLE_BIP70
endif # ENABLE_WALLET
RES_IMAGES =
@@ -292,18 +275,17 @@ BITCOIN_RC = qt/res/bitcoin-qt-res.rc
BITCOIN_QT_INCLUDES = -DQT_NO_KEYWORDS
qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
- $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
+ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(QR_CFLAGS)
qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
- $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
+ $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
if TARGET_DARWIN
qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM)
endif
-nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
- $(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
+nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
# forms/foo.h -> forms/ui_foo.h
QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
@@ -313,14 +295,9 @@ QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:
$(QT_MOC): $(QT_FORMS_H)
$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC)
-#Generating these with a half-written protobuf header leads to wacky results.
-#This makes sure it's done.
-$(QT_MOC): $(PROTOBUF_H)
-$(QT_MOC_CPP): $(PROTOBUF_H)
-
# bitcoin-qt binary #
qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
- $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
+ $(QT_INCLUDES) $(QR_CFLAGS)
qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
qt_bitcoin_qt_SOURCES = qt/main.cpp
@@ -335,15 +312,8 @@ if ENABLE_ZMQ
qt_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) \
- $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
-if ENABLE_BIP70
-qt_bitcoin_qt_LDADD += $(SSL_LIBS)
-else
-if TARGET_WINDOWS
-qt_bitcoin_qt_LDADD += $(SSL_LIBS)
-endif
-endif
qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS)
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX
@@ -368,7 +338,7 @@ $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
@rm $(@D)/temp_$(<F)
-$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
+$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
@test -f $(RCC)
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 4acfff809e..c309340fd7 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -15,10 +15,6 @@ if ENABLE_WALLET
TEST_QT_MOC_CPP += \
qt/test/moc_addressbooktests.cpp \
qt/test/moc_wallettests.cpp
-if ENABLE_BIP70
-TEST_QT_MOC_CPP += \
- qt/test/moc_paymentservertests.cpp
-endif # ENABLE_BIP70
endif # ENABLE_WALLET
TEST_QT_H = \
@@ -28,8 +24,6 @@ TEST_QT_H = \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
qt/test/util.h \
- qt/test/paymentrequestdata.h \
- qt/test/paymentservertests.h \
qt/test/wallettests.h
TEST_BITCOIN_CPP = \
@@ -39,7 +33,7 @@ TEST_BITCOIN_H = \
test/setup_common.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
- $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
+ $(QT_INCLUDES) $(QT_TEST_INCLUDES)
qt_test_test_bitcoin_qt_SOURCES = \
qt/test/apptests.cpp \
@@ -56,10 +50,6 @@ qt_test_test_bitcoin_qt_SOURCES += \
qt/test/addressbooktests.cpp \
qt/test/wallettests.cpp \
wallet/test/wallet_test_fixture.cpp
-if ENABLE_BIP70
-qt_test_test_bitcoin_qt_SOURCES += \
- qt/test/paymentservertests.cpp
-endif # ENABLE_BIP70
endif # ENABLE_WALLET
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
@@ -73,7 +63,7 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
- $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(QR_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 48df50d100..019e832cc6 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -16,12 +16,16 @@ FUZZ_TARGETS = \
test/fuzz/blockundo_deserialize \
test/fuzz/bloomfilter_deserialize \
test/fuzz/coins_deserialize \
+ test/fuzz/descriptor_parse \
test/fuzz/diskblockindex_deserialize \
+ test/fuzz/eval_script \
test/fuzz/inv_deserialize \
test/fuzz/messageheader_deserialize \
test/fuzz/netaddr_deserialize \
+ test/fuzz/script \
test/fuzz/script_flags \
test/fuzz/service_deserialize \
+ test/fuzz/spanparsing \
test/fuzz/transaction \
test/fuzz/txoutcompressor_deserialize \
test/fuzz/txundo_deserialize
@@ -51,6 +55,8 @@ RAW_TEST_FILES =
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
BITCOIN_TEST_SUITE = \
+ test/lib/transaction_utils.h \
+ test/lib/transaction_utils.cpp \
test/main.cpp \
test/setup_common.h \
test/setup_common.cpp
@@ -59,7 +65,8 @@ FUZZ_SUITE = \
test/setup_common.h \
test/setup_common.cpp \
test/fuzz/fuzz.cpp \
- test/fuzz/fuzz.h
+ test/fuzz/fuzz.h \
+ test/fuzz/FuzzedDataProvider.h
FUZZ_SUITE_LD_COMMON = \
$(LIBBITCOIN_SERVER) \
@@ -250,12 +257,24 @@ test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_descriptor_parse_SOURCES = $(FUZZ_SUITE) test/fuzz/descriptor_parse.cpp
+test_fuzz_descriptor_parse_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_descriptor_parse_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_descriptor_parse_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_descriptor_parse_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_script_SOURCES = $(FUZZ_SUITE) test/fuzz/script.cpp
+test_fuzz_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp
test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -268,6 +287,12 @@ test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_spanparsing_SOURCES = $(FUZZ_SUITE) test/fuzz/spanparsing.cpp
+test_fuzz_spanparsing_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_spanparsing_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_spanparsing_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_spanparsing_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -298,6 +323,12 @@ test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_eval_script_SOURCES = $(FUZZ_SUITE) test/fuzz/eval_script.cpp
+test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_eval_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index be145a0e63..1111f27771 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -8,8 +8,6 @@
#include <uint256.h>
#include <crypto/common.h>
-#include <stdio.h>
-#include <string.h>
template <unsigned int BITS>
base_uint<BITS>::base_uint(const std::string& str)
diff --git a/src/arith_uint256.h b/src/arith_uint256.h
index bd0360087d..171135b01f 100644
--- a/src/arith_uint256.h
+++ b/src/arith_uint256.h
@@ -6,13 +6,11 @@
#ifndef BITCOIN_ARITH_UINT256_H
#define BITCOIN_ARITH_UINT256_H
-#include <assert.h>
#include <cstring>
#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string>
-#include <vector>
class uint256;
diff --git a/src/bech32.cpp b/src/bech32.cpp
index 4c966350b4..1e0471f110 100644
--- a/src/bech32.cpp
+++ b/src/bech32.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bech32.h>
+#include <util/vector.h>
#include <assert.h>
@@ -26,13 +27,6 @@ const int8_t CHARSET_REV[128] = {
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
};
-/** Concatenate two byte arrays. */
-data Cat(data x, const data& y)
-{
- x.insert(x.end(), y.begin(), y.end());
- return x;
-}
-
/** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to
* make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher
* bits correspond to earlier values. */
diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp
index 0f4b52cf79..40a7b5e320 100644
--- a/src/bench/base58.cpp
+++ b/src/bench/base58.cpp
@@ -8,7 +8,6 @@
#include <array>
#include <vector>
-#include <string>
static void Base58Encode(benchmark::State& state)
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 35eeab3393..3a8c487b9a 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -6,7 +6,6 @@
#define BITCOIN_BENCH_BENCH_H
#include <functional>
-#include <limits>
#include <map>
#include <string>
#include <vector>
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index d0d7c03ee1..655a5a3459 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -51,6 +51,13 @@ int main(int argc, char** argv)
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
bool is_list_only = gArgs.GetBoolArg("-list", false);
+ if (evaluations == 0) {
+ return EXIT_SUCCESS;
+ } else if (evaluations < 0) {
+ tfm::format(std::cerr, "Error parsing evaluations argument: %d\n", evaluations);
+ return EXIT_FAILURE;
+ }
+
double scaling_factor;
if (!ParseDouble(scaling_str, &scaling_factor)) {
tfm::format(std::cerr, "Error parsing scaling factor as double: %s\n", scaling_str.c_str());
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index fb33c09ab2..157f936a95 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -10,7 +10,6 @@
#include <validation.h>
-#include <list>
#include <vector>
static void AssembleBlock(benchmark::State& state)
diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp
index 030067aca5..f1b0a9a989 100644
--- a/src/bench/chacha20.cpp
+++ b/src/bench/chacha20.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 <iostream>
#include <bench/bench.h>
#include <crypto/chacha20.h>
diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp
index f5f7297490..a02a5315a4 100644
--- a/src/bench/chacha_poly_aead.cpp
+++ b/src/bench/chacha_poly_aead.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 <iostream>
#include <bench/bench.h>
#include <crypto/chacha_poly_aead.h>
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index fb2bab9dee..674753c191 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.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 <iostream>
#include <bench/bench.h>
#include <hash.h>
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index 2440341287..6cfa3750d6 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -4,15 +4,12 @@
#include <bench/bench.h>
#include <chainparams.h>
-#include <coins.h>
#include <consensus/merkle.h>
#include <consensus/validation.h>
#include <pow.h>
#include <txmempool.h>
#include <validation.h>
-#include <list>
-#include <vector>
static void DuplicateInputs(benchmark::State& state)
diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp
index 0712eab4bc..0d9b123400 100644
--- a/src/bench/lockedpool.cpp
+++ b/src/bench/lockedpool.cpp
@@ -6,7 +6,6 @@
#include <support/lockedpool.h>
-#include <iostream>
#include <vector>
#define ASIZE 2048
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index ac8a182358..a2a21c673b 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -6,8 +6,6 @@
#include <policy/policy.h>
#include <txmempool.h>
-#include <list>
-#include <vector>
static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{
diff --git a/src/bench/poly1305.cpp b/src/bench/poly1305.cpp
index 16342d0fbe..02e5fecc0d 100644
--- a/src/bench/poly1305.cpp
+++ b/src/bench/poly1305.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 <iostream>
#include <bench/bench.h>
#include <crypto/poly1305.h>
diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp
index 4016530dac..cffdb388f8 100644
--- a/src/bench/rollingbloom.cpp
+++ b/src/bench/rollingbloom.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 <iostream>
#include <bench/bench.h>
#include <bloom.h>
diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp
index 29e448fc43..2fc6f116a4 100644
--- a/src/bench/rpc_blockchain.cpp
+++ b/src/bench/rpc_blockchain.cpp
@@ -7,7 +7,6 @@
#include <validation.h>
#include <streams.h>
-#include <consensus/validation.h>
#include <rpc/blockchain.h>
#include <univalue.h>
diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp
index b35a744055..bf63cccf09 100644
--- a/src/bench/rpc_mempool.cpp
+++ b/src/bench/rpc_mempool.cpp
@@ -8,8 +8,6 @@
#include <univalue.h>
-#include <list>
-#include <vector>
static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index 4891c57b3a..c9947f192e 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -10,44 +10,10 @@
#include <script/script.h>
#include <script/standard.h>
#include <streams.h>
+#include <test/lib/transaction_utils.h>
#include <array>
-// FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp.
-static CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
-{
- CMutableTransaction txCredit;
- txCredit.nVersion = 1;
- txCredit.nLockTime = 0;
- txCredit.vin.resize(1);
- txCredit.vout.resize(1);
- txCredit.vin[0].prevout.SetNull();
- txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
- txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txCredit.vout[0].scriptPubKey = scriptPubKey;
- txCredit.vout[0].nValue = 1;
-
- return txCredit;
-}
-
-// FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp.
-static CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit)
-{
- CMutableTransaction txSpend;
- txSpend.nVersion = 1;
- txSpend.nLockTime = 0;
- txSpend.vin.resize(1);
- txSpend.vout.resize(1);
- txSpend.vin[0].prevout.hash = txCredit.GetHash();
- txSpend.vin[0].prevout.n = 0;
- txSpend.vin[0].scriptSig = scriptSig;
- txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txSpend.vout[0].scriptPubKey = CScript();
- txSpend.vout[0].nValue = txCredit.vout[0].nValue;
-
- return txSpend;
-}
-
// Microbenchmark for verification of a basic P2WPKH script. Can be easily
// modified to measure performance of other types of scripts.
static void VerifyScriptBench(benchmark::State& state)
@@ -71,8 +37,8 @@ static void VerifyScriptBench(benchmark::State& state)
CScript scriptPubKey = CScript() << witnessversion << ToByteVector(pubkeyHash);
CScript scriptSig;
CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG;
- const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey);
- CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
+ const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey, 1);
+ CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, CScriptWitness(), CTransaction(txCredit));
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
witness.stack.emplace_back();
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back());
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 73773c4ec5..93b7a7152c 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -9,7 +9,6 @@
#include <chainparamsbase.h>
#include <clientversion.h>
-#include <fs.h>
#include <rpc/client.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
@@ -316,7 +315,20 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
// Synchronously look up hostname
raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);
- evhttp_connection_set_timeout(evcon.get(), gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
+
+ // Set connection timeout
+ {
+ const int timeout = gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
+ if (timeout > 0) {
+ evhttp_connection_set_timeout(evcon.get(), timeout);
+ } else {
+ // Indefinite request timeouts are not possible in libevent-http, so we
+ // set the timeout to a very long time period instead.
+
+ constexpr int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
+ evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
+ }
+ }
HTTPReply response;
raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 88219f0d0f..cabea610f3 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -11,7 +11,6 @@
#include <consensus/consensus.h>
#include <core_io.h>
#include <key_io.h>
-#include <policy/policy.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <script/script.h>
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index eb7f0098ec..eda4f8ce78 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -9,13 +9,11 @@
#include <chainparams.h>
#include <chainparamsbase.h>
#include <logging.h>
-#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallettool.h>
#include <functional>
-#include <stdio.h>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 17989a4214..ddd6f8839c 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -10,7 +10,6 @@
#include <chainparams.h>
#include <clientversion.h>
#include <compat.h>
-#include <fs.h>
#include <init.h>
#include <interfaces/chain.h>
#include <noui.h>
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 0c2b83ebcf..18a6e35f31 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -7,7 +7,6 @@
#include <primitives/block.h>
-#include <memory>
class CTxMemPool;
diff --git a/src/chain.h b/src/chain.h
index 1b67ebbe41..321bc95dbc 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -140,91 +140,65 @@ class CBlockIndex
{
public:
//! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
- const uint256* phashBlock;
+ const uint256* phashBlock{nullptr};
//! pointer to the index of the predecessor of this block
- CBlockIndex* pprev;
+ CBlockIndex* pprev{nullptr};
//! pointer to the index of some further predecessor of this block
- CBlockIndex* pskip;
+ CBlockIndex* pskip{nullptr};
//! height of the entry in the chain. The genesis block has height 0
- int nHeight;
+ int nHeight{0};
//! Which # file this block is stored in (blk?????.dat)
- int nFile;
+ int nFile{0};
//! Byte offset within blk?????.dat where this block's data is stored
- unsigned int nDataPos;
+ unsigned int nDataPos{0};
//! Byte offset within rev?????.dat where this block's undo data is stored
- unsigned int nUndoPos;
+ unsigned int nUndoPos{0};
//! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
- arith_uint256 nChainWork;
+ arith_uint256 nChainWork{};
//! Number of transactions in this block.
//! Note: in a potential headers-first mode, this number cannot be relied upon
- unsigned int nTx;
+ unsigned int nTx{0};
//! (memory only) Number of transactions in the chain up to and including this block.
//! This value will be non-zero only if and only if transactions for this block and all its parents are available.
//! Change to 64-bit type when necessary; won't happen before 2030
- unsigned int nChainTx;
+ unsigned int nChainTx{0};
//! Verification status of this block. See enum BlockStatus
- uint32_t nStatus;
+ uint32_t nStatus{0};
//! block header
- int32_t nVersion;
- uint256 hashMerkleRoot;
- uint32_t nTime;
- uint32_t nBits;
- uint32_t nNonce;
+ int32_t nVersion{0};
+ uint256 hashMerkleRoot{};
+ uint32_t nTime{0};
+ uint32_t nBits{0};
+ uint32_t nNonce{0};
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
- int32_t nSequenceId;
+ int32_t nSequenceId{0};
//! (memory only) Maximum nTime in the chain up to and including this block.
- unsigned int nTimeMax;
-
- void SetNull()
- {
- phashBlock = nullptr;
- pprev = nullptr;
- pskip = nullptr;
- nHeight = 0;
- nFile = 0;
- nDataPos = 0;
- nUndoPos = 0;
- nChainWork = arith_uint256();
- nTx = 0;
- nChainTx = 0;
- nStatus = 0;
- nSequenceId = 0;
- nTimeMax = 0;
-
- nVersion = 0;
- hashMerkleRoot = uint256();
- nTime = 0;
- nBits = 0;
- nNonce = 0;
- }
+ unsigned int nTimeMax{0};
CBlockIndex()
{
- SetNull();
}
explicit CBlockIndex(const CBlockHeader& block)
+ : nVersion{block.nVersion},
+ hashMerkleRoot{block.hashMerkleRoot},
+ nTime{block.nTime},
+ nBits{block.nBits},
+ nNonce{block.nNonce}
{
- SetNull();
-
- nVersion = block.nVersion;
- hashMerkleRoot = block.hashMerkleRoot;
- nTime = block.nTime;
- nBits = block.nBits;
- nNonce = block.nNonce;
}
FlatFilePos GetBlockPos() const {
diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h
index fe47f4899f..c254fe7cbf 100644
--- a/src/compat/byteswap.h
+++ b/src/compat/byteswap.h
@@ -17,20 +17,13 @@
#if defined(MAC_OSX)
-#if !defined(bswap_16)
-
-// Mac OS X / Darwin features; we include a check for bswap_16 because if it is already defined, protobuf has
-// defined these macros for us already; if it isn't, we do it ourselves. In either case, we get the exact same
-// result regardless which path was taken
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
-#endif // !defined(bswap_16)
-
#else
-// Non-Mac OS X / non-Darwin
+// Non-MacOS / non-Darwin
#if HAVE_DECL_BSWAP_16 == 0
inline uint16_t bswap_16(uint16_t x)
diff --git a/src/compressor.cpp b/src/compressor.cpp
index a2d9af8805..a7f45b5c1e 100644
--- a/src/compressor.cpp
+++ b/src/compressor.cpp
@@ -5,7 +5,6 @@
#include <compressor.h>
-#include <hash.h>
#include <pubkey.h>
#include <script/standard.h>
diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h
index 7675877de5..f28f76bd34 100644
--- a/src/consensus/merkle.h
+++ b/src/consensus/merkle.h
@@ -5,10 +5,8 @@
#ifndef BITCOIN_CONSENSUS_MERKLE_H
#define BITCOIN_CONSENSUS_MERKLE_H
-#include <stdint.h>
#include <vector>
-#include <primitives/transaction.h>
#include <primitives/block.h>
#include <uint256.h>
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 2f8c490dc4..e191fd6d26 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -8,8 +8,6 @@
#include <uint256.h>
#include <limits>
-#include <map>
-#include <string>
namespace Consensus {
diff --git a/src/consensus/tx_check.cpp b/src/consensus/tx_check.cpp
index 00ebbbd1ab..6793f871cf 100644
--- a/src/consensus/tx_check.cpp
+++ b/src/consensus/tx_check.cpp
@@ -7,50 +7,51 @@
#include <primitives/transaction.h>
#include <consensus/validation.h>
-bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
+bool CheckTransaction(const CTransaction& tx, CValidationState& state)
{
// Basic checks that don't depend on any context
if (tx.vin.empty())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vin-empty");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vin-empty");
if (tx.vout.empty())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-empty");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-empty");
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-oversize");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-oversize");
// Check for negative or overflow output values (see CVE-2010-5139)
CAmount nValueOut = 0;
for (const auto& txout : tx.vout)
{
if (txout.nValue < 0)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-negative");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-negative");
if (txout.nValue > MAX_MONEY)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-toolarge");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-toolarge");
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-txouttotal-toolarge");
}
- // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
- if (fCheckDuplicateInputs) {
- std::set<COutPoint> vInOutPoints;
- for (const auto& txin : tx.vin)
- {
- if (!vInOutPoints.insert(txin.prevout).second)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
- }
+ // Check for duplicate inputs (see CVE-2018-17144)
+ // While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
+ // of a tx as spent, it does not check if the tx has duplicate inputs.
+ // Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
+ // the underlying coins database.
+ std::set<COutPoint> vInOutPoints;
+ for (const auto& txin : tx.vin) {
+ if (!vInOutPoints.insert(txin.prevout).second)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate");
}
if (tx.IsCoinBase())
{
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-length");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-length");
}
else
{
for (const auto& txin : tx.vin)
if (txin.prevout.IsNull())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-prevout-null");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-prevout-null");
}
return true;
diff --git a/src/consensus/tx_check.h b/src/consensus/tx_check.h
index bcfdf36bf9..6f3f8fe969 100644
--- a/src/consensus/tx_check.h
+++ b/src/consensus/tx_check.h
@@ -15,6 +15,6 @@
class CTransaction;
class CValidationState;
-bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
+bool CheckTransaction(const CTransaction& tx, CValidationState& state);
#endif // BITCOIN_CONSENSUS_TX_CHECK_H
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index 4b93cae848..ceeddc3f6d 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -160,7 +160,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
- return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, REJECT_INVALID, "bad-txns-inputs-missingorspent",
+ return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, "bad-txns-inputs-missingorspent",
strprintf("%s: inputs missing/spent", __func__));
}
@@ -172,27 +172,27 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
// If prev is coinbase, check that it's matured
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
- return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "bad-txns-premature-spend-of-coinbase",
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
}
// Check for negative or overflow input values
nValueIn += coin.out.nValue;
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputvalues-outofrange");
}
}
const CAmount value_out = tx.GetValueOut();
if (nValueIn < value_out) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-in-belowout",
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-in-belowout",
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
}
// Tally transaction fees
const CAmount txfee_aux = nValueIn - value_out;
if (!MoneyRange(txfee_aux)) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-fee-outofrange");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-fee-outofrange");
}
txfee = txfee_aux;
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 2e23f4b3a4..4920cdf881 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -12,20 +12,8 @@
#include <primitives/transaction.h>
#include <primitives/block.h>
-/** "reject" message codes */
-static const unsigned char REJECT_MALFORMED = 0x01;
-static const unsigned char REJECT_INVALID = 0x10;
-static const unsigned char REJECT_OBSOLETE = 0x11;
-static const unsigned char REJECT_DUPLICATE = 0x12;
-static const unsigned char REJECT_NONSTANDARD = 0x40;
-// static const unsigned char REJECT_DUST = 0x41; // part of BIP 61
-static const unsigned char REJECT_INSUFFICIENTFEE = 0x42;
-static const unsigned char REJECT_CHECKPOINT = 0x43;
-
/** A "reason" why something was invalid, suitable for determining whether the
* provider of the object should be banned/ignored/disconnected/etc.
- * These are much more granular than the rejection codes, which may be more
- * useful for some other use-cases.
*/
enum class ValidationInvalidReason {
// txn and blocks:
@@ -104,15 +92,13 @@ private:
} mode;
ValidationInvalidReason m_reason;
std::string strRejectReason;
- unsigned int chRejectCode;
std::string strDebugMessage;
public:
- CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE), chRejectCode(0) {}
+ CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {}
bool Invalid(ValidationInvalidReason reasonIn, bool ret = false,
- unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="",
+ const std::string &strRejectReasonIn="",
const std::string &strDebugMessageIn="") {
m_reason = reasonIn;
- chRejectCode = chRejectCodeIn;
strRejectReason = strRejectReasonIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
@@ -136,7 +122,6 @@ public:
return mode == MODE_ERROR;
}
ValidationInvalidReason GetReason() const { return m_reason; }
- unsigned int GetRejectCode() const { return chRejectCode; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
};
diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp
index b3fb927760..6ed9088434 100644
--- a/src/crypto/aes.cpp
+++ b/src/crypto/aes.cpp
@@ -4,7 +4,6 @@
#include <crypto/aes.h>
-#include <assert.h>
#include <string.h>
extern "C" {
diff --git a/src/crypto/chacha_poly_aead.cpp b/src/crypto/chacha_poly_aead.cpp
index 6a3d43deb1..0582a60c4f 100644
--- a/src/crypto/chacha_poly_aead.cpp
+++ b/src/crypto/chacha_poly_aead.cpp
@@ -4,7 +4,6 @@
#include <crypto/chacha_poly_aead.h>
-#include <crypto/common.h>
#include <crypto/poly1305.h>
#include <support/cleanse.h>
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index cab37e0322..3257ee7f97 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -7,7 +7,6 @@
#include <assert.h>
#include <string.h>
-#include <atomic>
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
#if defined(USE_ASM)
diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_shani.cpp
index e561da42c5..7ea0c34796 100644
--- a/src/crypto/sha256_shani.cpp
+++ b/src/crypto/sha256_shani.cpp
@@ -11,7 +11,6 @@
#include <stdint.h>
#include <immintrin.h>
-#include <crypto/common.h>
namespace {
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 416f5e8399..061c9b6bca 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -11,7 +11,6 @@
#include <streams.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <version.h>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 126e3479f3..0edcb0286d 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.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 <stdio.h>
#include <util/system.h>
#include <walletinitinterface.h>
#include <support/allocators/secure.h>
@@ -71,12 +70,12 @@ std::vector<std::shared_ptr<CWallet>> GetWallets()
throw std::logic_error("Wallet function called in non-wallet build.");
}
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}
-WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result)
+WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 306d718574..2c2f67b169 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -7,10 +7,8 @@
#include <chainparams.h>
#include <crypto/hmac_sha256.h>
#include <httpserver.h>
-#include <key_io.h>
#include <rpc/protocol.h>
#include <rpc/server.h>
-#include <sync.h>
#include <ui_interface.h>
#include <util/strencodings.h>
#include <util/system.h>
diff --git a/src/httprpc.h b/src/httprpc.h
index 2230a8ca4e..91c2ec0c9d 100644
--- a/src/httprpc.h
+++ b/src/httprpc.h
@@ -5,8 +5,6 @@
#ifndef BITCOIN_HTTPRPC_H
#define BITCOIN_HTTPRPC_H
-#include <string>
-#include <map>
/** Start HTTP RPC subsystem.
* Precondition; HTTP and RPC has been started.
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index d17667223b..d9c7113323 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -15,6 +15,7 @@
#include <sync.h>
#include <ui_interface.h>
+#include <deque>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
@@ -22,7 +23,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <signal.h>
#include <event2/thread.h>
#include <event2/buffer.h>
diff --git a/src/httpserver.h b/src/httpserver.h
index 7943f0094b..bc72fc8512 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -6,7 +6,6 @@
#define BITCOIN_HTTPSERVER_H
#include <string>
-#include <stdint.h>
#include <functional>
static const int DEFAULT_HTTP_THREADS=4;
diff --git a/src/index/base.h b/src/index/base.h
index 31acbed0c1..f95eeb8197 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -9,7 +9,6 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <threadinterrupt.h>
-#include <uint256.h>
#include <validationinterface.h>
class CBlockIndex;
diff --git a/src/init.cpp b/src/init.cpp
index 035725b090..da4d322669 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -354,7 +354,7 @@ void SetupServerArgs()
std::vector<std::string> hidden_args = {
"-dbcrashratio", "-forcecompactdb",
// GUI args. These will be overwritten by SetupUIArgs for the GUI
- "-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
+ "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"};
gArgs.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#if HAVE_SYSTEM
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index b8b9ecded9..b2c20573fb 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -18,12 +18,10 @@
#include <policy/settings.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
-#include <protocol.h>
#include <rpc/protocol.h>
#include <rpc/server.h>
#include <shutdown.h>
#include <sync.h>
-#include <threadsafety.h>
#include <timedata.h>
#include <txmempool.h>
#include <ui_interface.h>
@@ -298,6 +296,11 @@ public:
{
::mempool.GetTransactionAncestry(txid, ancestors, descendants);
}
+ void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
+ {
+ limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
+ limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
+ }
bool checkChainLimits(const CTransactionRef& tx) override
{
LockPoints lp;
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index da670a3370..73a78e21fb 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -163,6 +163,11 @@ public:
//! Calculate mempool ancestor and descendant counts for the given transaction.
virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0;
+ //! Get the node's package limits.
+ //! Currently only returns the ancestor and descendant count limits, but could be enhanced to
+ //! return more policy settings.
+ virtual void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) = 0;
+
//! Check if transaction will pass the mempool's chain limits.
virtual bool checkChainLimits(const CTransactionRef& tx) = 0;
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 3d89e17163..6577895d50 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -5,7 +5,6 @@
#include <interfaces/node.h>
#include <addrdb.h>
-#include <amount.h>
#include <banman.h>
#include <chain.h>
#include <chainparams.h>
@@ -19,7 +18,6 @@
#include <netbase.h>
#include <policy/feerate.h>
#include <policy/fees.h>
-#include <policy/policy.h>
#include <policy/settings.h>
#include <primitives/block.h>
#include <rpc/server.h>
@@ -36,15 +34,14 @@
#include <config/bitcoin-config.h>
#endif
-#include <atomic>
#include <univalue.h>
class CWallet;
fs::path GetWalletDir();
std::vector<fs::path> ListWalletDir();
std::vector<std::shared_ptr<CWallet>> GetWallets();
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning);
-WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result);
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings);
+WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result);
namespace interfaces {
@@ -256,14 +253,14 @@ public:
}
return wallets;
}
- std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override
+ std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) override
{
- return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
+ return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warnings));
}
- WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) override
+ WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) override
{
std::shared_ptr<CWallet> wallet;
- WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warning, wallet);
+ WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
result = MakeWallet(wallet);
return status;
}
@@ -315,7 +312,7 @@ public:
return MakeHandler(
::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) {
fn(initial_download, block->nHeight, block->GetBlockTime(),
- GuessVerificationProgress(Params().TxData(), block));
+ /* verification progress is unused when a header was received */ 0);
}));
}
InitInterfaces m_interfaces;
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 688ff434ba..4ee467014c 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -200,10 +200,10 @@ public:
//! Attempts to load a wallet from file or directory.
//! The loaded wallet is also notified to handlers previously registered
//! with handleLoadWallet.
- virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0;
+ virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) = 0;
//! Create a wallet from file
- virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::unique_ptr<Wallet>& result) = 0;
+ virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) = 0;
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 0c8d92eba5..9b0a8b64c9 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -5,10 +5,8 @@
#include <interfaces/wallet.h>
#include <amount.h>
-#include <consensus/validation.h>
#include <interfaces/chain.h>
#include <interfaces/handler.h>
-#include <policy/feerate.h>
#include <policy/fees.h>
#include <primitives/transaction.h>
#include <script/standard.h>
@@ -23,7 +21,6 @@
#include <wallet/rpcwallet.h>
#include <wallet/load.h>
#include <wallet/wallet.h>
-#include <wallet/walletutil.h>
#include <memory>
#include <string>
@@ -218,19 +215,13 @@ public:
}
return tx;
}
- bool commitTransaction(CTransactionRef tx,
+ void commitTransaction(CTransactionRef tx,
WalletValueMap value_map,
- WalletOrderForm order_form,
- std::string& reject_reason) override
+ WalletOrderForm order_form) override
{
auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
- CValidationState state;
- if (!m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form), state)) {
- reject_reason = state.GetRejectReason();
- return false;
- }
- return true;
+ m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form));
}
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
@@ -241,7 +232,7 @@ public:
}
bool transactionCanBeBumped(const uint256& txid) override
{
- return feebumper::TransactionCanBeBumped(m_wallet.get(), txid);
+ return feebumper::TransactionCanBeBumped(*m_wallet.get(), txid);
}
bool createBumpTransaction(const uint256& txid,
const CCoinControl& coin_control,
@@ -255,17 +246,17 @@ public:
return feebumper::CreateTotalBumpTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
feebumper::Result::OK;
} else {
- return feebumper::CreateRateBumpTransaction(m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) ==
+ return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) ==
feebumper::Result::OK;
}
}
- bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(m_wallet.get(), mtx); }
+ bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); }
bool commitBumpTransaction(const uint256& txid,
CMutableTransaction&& mtx,
std::vector<std::string>& errors,
uint256& bumped_txid) override
{
- return feebumper::CommitTransaction(m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) ==
+ return feebumper::CommitTransaction(*m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) ==
feebumper::Result::OK;
}
CTransactionRef getTx(const uint256& txid) override
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 89e056b18b..a96b93b4c3 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -141,10 +141,9 @@ public:
std::string& fail_reason) = 0;
//! Commit transaction.
- virtual bool commitTransaction(CTransactionRef tx,
+ virtual void commitTransaction(CTransactionRef tx,
WalletValueMap value_map,
- WalletOrderForm order_form,
- std::string& reject_reason) = 0;
+ WalletOrderForm order_form) = 0;
//! Return whether transaction can be abandoned.
virtual bool transactionCanBeAbandoned(const uint256& txid) = 0;
diff --git a/src/key.h b/src/key.h
index 67e2cfc094..6a86b0411d 100644
--- a/src/key.h
+++ b/src/key.h
@@ -162,25 +162,6 @@ struct CExtKey {
bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
void SetSeed(const unsigned char* seed, unsigned int nSeedLen);
- template <typename Stream>
- void Serialize(Stream& s) const
- {
- unsigned int len = BIP32_EXTKEY_SIZE;
- ::WriteCompactSize(s, len);
- unsigned char code[BIP32_EXTKEY_SIZE];
- Encode(code);
- s.write((const char *)&code[0], len);
- }
- template <typename Stream>
- void Unserialize(Stream& s)
- {
- unsigned int len = ::ReadCompactSize(s);
- unsigned char code[BIP32_EXTKEY_SIZE];
- if (len != BIP32_EXTKEY_SIZE)
- throw std::runtime_error("Invalid extended key size\n");
- s.read((char *)&code[0], len);
- Decode(code);
- }
};
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
diff --git a/src/key_io.cpp b/src/key_io.cpp
index cd41a93549..363055d6b3 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -6,7 +6,6 @@
#include <base58.h>
#include <bech32.h>
-#include <script/script.h>
#include <util/strencodings.h>
#include <boost/variant/apply_visitor.hpp>
diff --git a/src/logging.cpp b/src/logging.cpp
index dc2d130a2a..60ab486198 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -224,10 +224,32 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str)
return strStamped;
}
+namespace BCLog {
+ /** Belts and suspenders: make sure outgoing log messages don't contain
+ * potentially suspicious characters, such as terminal control codes.
+ *
+ * This escapes control characters except newline ('\n') in C syntax.
+ * It escapes instead of removes them to still allow for troubleshooting
+ * issues where they accidentally end up in strings.
+ */
+ std::string LogEscapeMessage(const std::string& str) {
+ std::string ret;
+ for (char ch_in : str) {
+ uint8_t ch = (uint8_t)ch_in;
+ if ((ch >= 32 || ch == '\n') && ch != '\x7f') {
+ ret += ch_in;
+ } else {
+ ret += strprintf("\\x%02x", ch);
+ }
+ }
+ return ret;
+ }
+}
+
void BCLog::Logger::LogPrintStr(const std::string& str)
{
std::lock_guard<std::mutex> scoped_lock(m_cs);
- std::string str_prefixed = str;
+ std::string str_prefixed = LogEscapeMessage(str);
if (m_log_threadnames && m_started_new_line) {
str_prefixed.insert(0, "[" + util::ThreadGetInternalName() + "] ");
diff --git a/src/miner.cpp b/src/miner.cpp
index 015645c9c6..4f51be8a08 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -17,14 +17,12 @@
#include <policy/policy.h>
#include <pow.h>
#include <primitives/transaction.h>
-#include <script/standard.h>
#include <timedata.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/validation.h>
#include <algorithm>
-#include <queue>
#include <utility>
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
diff --git a/src/net.cpp b/src/net.cpp
index be4427f793..7ae88b47a0 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -13,11 +13,9 @@
#include <chainparams.h>
#include <clientversion.h>
#include <consensus/consensus.h>
-#include <crypto/common.h>
#include <crypto/sha256.h>
#include <netbase.h>
#include <net_permissions.h>
-#include <primitives/transaction.h>
#include <scheduler.h>
#include <ui_interface.h>
#include <util/strencodings.h>
@@ -35,7 +33,6 @@
#ifdef USE_UPNP
#include <miniupnpc/miniupnpc.h>
-#include <miniupnpc/miniwget.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
@@ -1380,7 +1377,7 @@ void CConnman::SocketHandler()
{
// socket closed gracefully
if (!pnode->fDisconnect) {
- LogPrint(BCLog::NET, "socket closed\n");
+ LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
}
pnode->CloseSocketDisconnect();
}
@@ -1390,8 +1387,9 @@ void CConnman::SocketHandler()
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
- if (!pnode->fDisconnect)
- LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
+ if (!pnode->fDisconnect) {
+ LogPrint(BCLog::NET, "socket recv error for peer=%d: %s\n", pnode->GetId(), NetworkErrorString(nErr));
+ }
pnode->CloseSocketDisconnect();
}
}
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 9496516c37..fd31c962c2 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -7,7 +7,6 @@
#include <addrman.h>
#include <banman.h>
-#include <arith_uint256.h>
#include <blockencodings.h>
#include <chainparams.h>
#include <consensus/validation.h>
@@ -39,6 +38,8 @@
static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
/** Minimum time between orphan transactions expire time checks in seconds */
static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
+/** How long to cache transactions in mapRelay for normal relay */
+static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME{15 * 60};
/** Headers download timeout expressed in microseconds
* Timeout = base + per_header * (expected number of headers) */
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
@@ -117,8 +118,8 @@ namespace {
int nSyncStarted GUARDED_BY(cs_main) = 0;
/**
- * Sources of received blocks, saved to be able to send them reject
- * messages or ban them when processing happens afterwards.
+ * Sources of received blocks, saved to be able punish them when processing
+ * happens afterwards.
* Set mapBlockSource[hash].second to false if the node should not be
* punished if the block is invalid.
*/
@@ -1234,11 +1235,12 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
const uint256 hash(block.GetHash());
std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
- if (state.IsInvalid()) {
- // Don't send reject message with code 0 or an internal reject code.
- if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) {
+ // If the block failed validation, we know where it came from and we're still connected
+ // to that peer, maybe punish.
+ if (state.IsInvalid() &&
+ it != mapBlockSource.end() &&
+ State(it->second.first)) {
MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
- }
}
// Check that:
// 1. The block is valid
@@ -1513,6 +1515,10 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
// messages from this peer (likely resulting in our peer eventually
// disconnecting us).
if (pfrom->m_tx_relay != nullptr) {
+ // mempool entries added before this time have likely expired from mapRelay
+ const std::chrono::seconds longlived_mempool_time = GetTime<std::chrono::seconds>() - RELAY_TX_CACHE_TIME;
+ const std::chrono::seconds mempool_req = pfrom->m_tx_relay->m_last_mempool_req.load();
+
LOCK(cs_main);
while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) {
@@ -1532,11 +1538,15 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
if (mi != mapRelay.end()) {
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
push = true;
- } else if (pfrom->m_tx_relay->m_last_mempool_req.load().count()) {
+ } 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.
- if (txinfo.tx && txinfo.m_time <= pfrom->m_tx_relay->m_last_mempool_req.load()) {
+ // 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;
}
@@ -2860,11 +2870,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// been run). This is handled below, so just treat this as
// though the block was successfully read, and rely on the
// handling in ProcessNewBlock to ensure the block index is
- // updated, reject messages go out, etc.
+ // updated, etc.
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
fBlockRead = true;
- // mapBlockSource is only used for sending reject messages and DoS scores,
- // so the race between here and cs_main in ProcessNewBlock is fine.
+ // mapBlockSource is used for potentially punishing peers and
+ // updating which peers send us compact blocks, so the race
+ // between here and cs_main in ProcessNewBlock is fine.
// BIP 152 permits peers to relay compact blocks after validating
// the header only; we should not punish peers if the block turns
// out to be invalid.
@@ -2936,8 +2947,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Also always process if we requested the block explicitly, as we may
// need it even though it is not a candidate for a new best tip.
forceProcessing |= MarkBlockAsReceived(hash);
- // mapBlockSource is only used for sending reject messages and DoS scores,
- // so the race between here and cs_main in ProcessNewBlock is fine.
+ // mapBlockSource is only used for punishing peers and setting
+ // which peers send us compact blocks, so the race between here and
+ // cs_main in ProcessNewBlock is fine.
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
}
bool fNewBlock = false;
@@ -3870,7 +3882,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
auto ret = mapRelay.insert(std::make_pair(hash, std::move(txinfo.tx)));
if (ret.second) {
- vRelayExpiration.push_back(std::make_pair(nNow + 15 * 60 * 1000000, ret.first));
+ vRelayExpiration.push_back(std::make_pair(nNow + std::chrono::microseconds{RELAY_TX_CACHE_TIME}.count(), ret.first));
}
}
if (vInv.size() == MAX_INV_SZ) {
diff --git a/src/netaddress.h b/src/netaddress.h
index 673eaf8d7b..fbb1553338 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -11,7 +11,6 @@
#include <compat.h>
#include <serialize.h>
-#include <span.h>
#include <stdint.h>
#include <string>
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index e1891b9898..57fa158ad2 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -5,9 +5,7 @@
#include <node/coinstats.h>
-#include <amount.h>
#include <coins.h>
-#include <chain.h>
#include <hash.h>
#include <serialize.h>
#include <validation.h>
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 7e8291ddc8..7783671a6c 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -6,7 +6,6 @@
#include <consensus/validation.h>
#include <net.h>
#include <net_processing.h>
-#include <txmempool.h>
#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
diff --git a/src/node/transaction.h b/src/node/transaction.h
index cf64fc28d9..a3e56544a7 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -7,7 +7,6 @@
#include <attributes.h>
#include <primitives/transaction.h>
-#include <uint256.h>
#include <util/error.h>
/**
diff --git a/src/noui.cpp b/src/noui.cpp
index c07939cc79..14d6183d24 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -8,8 +8,6 @@
#include <ui_interface.h>
#include <util/system.h>
-#include <cstdio>
-#include <stdint.h>
#include <string>
#include <boost/signals2/connection.hpp>
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index bcaa05f4b6..5cc43898a7 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -10,6 +10,7 @@
#include <script/sign.h>
#include <script/signingprovider.h>
#include <script/standard.h>
+#include <util/vector.h>
#include <assert.h>
#include <string>
@@ -65,12 +66,13 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
{
PKHash keyid(key);
+ CTxDestination p2pkh{keyid};
if (key.IsCompressed()) {
CTxDestination segwit = WitnessV0KeyHash(keyid);
CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit));
- return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)};
+ return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit));
} else {
- return std::vector<CTxDestination>{std::move(keyid)};
+ return Vector(std::move(p2pkh));
}
}
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 5d538606c2..8154bf105e 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -6,7 +6,6 @@
#include <policy/fees.h>
#include <clientversion.h>
-#include <primitives/transaction.h>
#include <streams.h>
#include <txmempool.h>
#include <util/system.h>
diff --git a/src/prevector.h b/src/prevector.h
index 9d576321b6..d307495fbe 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -12,7 +12,6 @@
#include <algorithm>
#include <cstddef>
-#include <iterator>
#include <type_traits>
#pragma pack(push, 1)
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 60c7c2d160..0c84ed6da2 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -7,7 +7,6 @@
#include <hash.h>
#include <tinyformat.h>
-#include <crypto/common.h>
uint256 CBlockHeader::GetHash() const
{
diff --git a/src/protocol.h b/src/protocol.h
index e6b25ffa25..3032310fa1 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -15,7 +15,6 @@
#include <uint256.h>
#include <version.h>
-#include <atomic>
#include <stdint.h>
#include <string>
diff --git a/src/psbt.cpp b/src/psbt.cpp
index fe74002e82..c306079b1e 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -5,7 +5,6 @@
#include <psbt.h>
#include <util/strencodings.h>
-#include <numeric>
PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx)
{
diff --git a/src/pubkey.h b/src/pubkey.h
index 089324ffda..fd815a871b 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -222,31 +222,6 @@ struct CExtPubKey {
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
-
- void Serialize(CSizeComputer& s) const
- {
- // Optimized implementation for ::GetSerializeSize that avoids copying.
- s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
- }
- template <typename Stream>
- void Serialize(Stream& s) const
- {
- unsigned int len = BIP32_EXTKEY_SIZE;
- ::WriteCompactSize(s, len);
- unsigned char code[BIP32_EXTKEY_SIZE];
- Encode(code);
- s.write((const char *)&code[0], len);
- }
- template <typename Stream>
- void Unserialize(Stream& s)
- {
- unsigned int len = ::ReadCompactSize(s);
- unsigned char code[BIP32_EXTKEY_SIZE];
- if (len != BIP32_EXTKEY_SIZE)
- throw std::runtime_error("Invalid extended key size\n");
- s.read((char *)&code[0], len);
- Decode(code);
- }
};
/** Users of this module must hold an ECCVerifyHandle. The constructor and
diff --git a/src/qt/README.md b/src/qt/README.md
index 0eb18f7cd5..30c68db15b 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -50,7 +50,7 @@ Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt
### paymentserver.(h/cpp)
-Used to process BIP21 and BIP70 (see https://github.com/bitcoin/bitcoin/pull/11622) payment URI / requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser).
+Used to process BIP21 payment URI requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser).
### walletview.(h/cpp)
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index efc726e09e..ae11b80347 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -7,8 +7,6 @@
#include <qt/clientmodel.h>
#include <interfaces/node.h>
-#include <sync.h>
-#include <util/time.h>
#include <algorithm>
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 86f4dc91a1..02a2a01bdd 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -10,7 +10,6 @@
#include <qt/bitcoingui.h>
#include <chainparams.h>
-#include <fs.h>
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
@@ -338,10 +337,6 @@ void BitcoinApplication::initializeResult(bool success)
window->setWalletController(m_wallet_controller);
if (paymentServer) {
paymentServer->setOptionsModel(optionsModel);
-#ifdef ENABLE_BIP70
- PaymentServer::LoadRootCAs();
- connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK);
-#endif
}
}
#endif // ENABLE_WALLET
@@ -397,14 +392,10 @@ WId BitcoinApplication::getMainWinId() const
static void SetupUIArgs()
{
-#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
- gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
-#endif
gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
- gArgs.AddArg("-rootcertificates=<file>", "Set SSL root certificates for payment request (default: -system-)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
}
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 9fa49b87fa..23df1c929a 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -102,7 +102,7 @@ public:
CAmount val = value(&valid);
currentUnit = unit;
-
+ lineEdit()->setPlaceholderText(BitcoinUnits::format(currentUnit, m_min_amount, false, BitcoinUnits::separatorAlways));
if(valid)
setValue(val);
else
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 2878a8eb14..2aeba6d82c 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -199,12 +199,12 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK);
});
- modalOverlay = new ModalOverlay(this->centralWidget());
+ modalOverlay = new ModalOverlay(enableWallet, this->centralWidget());
+ connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay);
+ connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay);
#ifdef ENABLE_WALLET
if(enableWallet) {
connect(walletFrame, &WalletFrame::requestedSyncWarningInfo, this, &BitcoinGUI::showModalOverlay);
- connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay);
- connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay);
}
#endif
@@ -330,7 +330,7 @@ void BitcoinGUI::createActions()
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
openAction = new QAction(tr("Open &URI..."), this);
- openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
+ openAction->setStatusTip(tr("Open a bitcoin: URI"));
m_open_wallet_action = new QAction(tr("Open Wallet"), this);
m_open_wallet_action->setEnabled(false);
@@ -796,7 +796,7 @@ void BitcoinGUI::showDebugWindow()
void BitcoinGUI::showDebugWindowActivateConsole()
{
- rpcConsole->setTabFocus(RPCConsole::TAB_CONSOLE);
+ rpcConsole->setTabFocus(RPCConsole::TabTypes::CONSOLE);
showDebugWindow();
}
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 238be08480..5b216b2705 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <QDebug>
+#include <QThread>
#include <QTimer>
static int64_t nLastHeaderTipUpdateNotification = 0;
@@ -30,15 +31,26 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
optionsModel(_optionsModel),
peerTableModel(nullptr),
banTableModel(nullptr),
- pollTimer(nullptr)
+ m_thread(new QThread(this))
{
cachedBestHeaderHeight = -1;
cachedBestHeaderTime = -1;
peerTableModel = new PeerTableModel(m_node, this);
banTableModel = new BanTableModel(m_node, this);
- pollTimer = new QTimer(this);
- connect(pollTimer, &QTimer::timeout, this, &ClientModel::updateTimer);
- pollTimer->start(MODEL_UPDATE_DELAY);
+
+ QTimer* timer = new QTimer;
+ timer->setInterval(MODEL_UPDATE_DELAY);
+ connect(timer, &QTimer::timeout, [this] {
+ // no locking required at this point
+ // the following calls will acquire the required lock
+ Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage());
+ Q_EMIT bytesChanged(m_node.getTotalBytesRecv(), m_node.getTotalBytesSent());
+ });
+ connect(m_thread, &QThread::finished, timer, &QObject::deleteLater);
+ connect(m_thread, &QThread::started, [timer] { timer->start(); });
+ // move timer to thread so that polling doesn't disturb main event loop
+ timer->moveToThread(m_thread);
+ m_thread->start();
subscribeToCoreSignals();
}
@@ -46,6 +58,9 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
ClientModel::~ClientModel()
{
unsubscribeFromCoreSignals();
+
+ m_thread->quit();
+ m_thread->wait();
}
int ClientModel::getNumConnections(unsigned int flags) const
@@ -90,14 +105,6 @@ int64_t ClientModel::getHeaderTipTime() const
return cachedBestHeaderTime;
}
-void ClientModel::updateTimer()
-{
- // no locking required at this point
- // the following calls will acquire the required lock
- Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage());
- Q_EMIT bytesChanged(m_node.getTotalBytesRecv(), m_node.getTotalBytesSent());
-}
-
void ClientModel::updateNumConnections(int numConnections)
{
Q_EMIT numConnectionsChanged(numConnections);
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 95f4521f06..d3a95d531e 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -90,7 +90,8 @@ private:
PeerTableModel *peerTableModel;
BanTableModel *banTableModel;
- QTimer *pollTimer;
+ //! A thread to interact with m_node asynchronously
+ QThread* const m_thread;
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
@@ -110,7 +111,6 @@ Q_SIGNALS:
void showProgress(const QString &title, int nProgress);
public Q_SLOTS:
- void updateTimer();
void updateNumConnections(int numConnections);
void updateNetworkActive(bool networkActive);
void updateAlert();
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 03d18d2845..f928f1ca2a 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -19,7 +19,6 @@
#include <wallet/coincontrol.h>
#include <interfaces/node.h>
#include <key_io.h>
-#include <policy/fees.h>
#include <policy/policy.h>
#include <wallet/wallet.h>
diff --git a/src/qt/forms/openuridialog.ui b/src/qt/forms/openuridialog.ui
index 0e1048bc07..2acec314fd 100644
--- a/src/qt/forms/openuridialog.ui
+++ b/src/qt/forms/openuridialog.ui
@@ -11,17 +11,10 @@
</rect>
</property>
<property name="windowTitle">
- <string>Open URI</string>
+ <string>Open bitcoin URI</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Open payment request from URI or file</string>
- </property>
- </widget>
- </item>
- <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
@@ -33,19 +26,6 @@
<item>
<widget class="QValidatedLineEdit" name="uriEdit"/>
</item>
- <item>
- <widget class="QPushButton" name="selectFileButton">
- <property name="toolTip">
- <string>Select payment request file</string>
- </property>
- <property name="text">
- <string notr="true">…</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
</layout>
</item>
<item>
diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index 3c699abc6a..843d909f68 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -17,9 +17,6 @@
<bool>false</bool>
</property>
<widget class="QFrame" name="SendCoins">
- <property name="toolTip">
- <string>This is a normal payment.</string>
- </property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
@@ -165,7 +162,11 @@
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1,0">
<item>
- <widget class="BitcoinAmountField" name="payAmount"/>
+ <widget class="BitcoinAmountField" name="payAmount">
+ <property name="toolTip">
+ <string>The amount to send in the selected unit</string>
+ </property>
+ </widget>
</item>
<item>
<widget class="QCheckBox" name="checkboxSubtractFeeFromAmount">
diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui
index c9ddd757c1..202edf27d4 100644
--- a/src/qt/forms/signverifymessagedialog.ui
+++ b/src/qt/forms/signverifymessagedialog.ui
@@ -99,6 +99,9 @@
<property name="toolTip">
<string>Enter the message you want to sign here</string>
</property>
+ <property name="placeholderText">
+ <string>Enter the message you want to sign here</string>
+ </property>
</widget>
</item>
<item>
@@ -285,10 +288,24 @@
</layout>
</item>
<item>
- <widget class="QPlainTextEdit" name="messageIn_VM"/>
+ <widget class="QPlainTextEdit" name="messageIn_VM">
+ <property name="toolTip">
+ <string>The signed message to verify</string>
+ </property>
+ <property name="placeholderText">
+ <string>The signed message to verify</string>
+ </property>
+ </widget>
</item>
<item>
- <widget class="QValidatedLineEdit" name="signatureIn_VM"/>
+ <widget class="QValidatedLineEdit" name="signatureIn_VM">
+ <property name="toolTip">
+ <string>The signature given when the message was signed</string>
+ </property>
+ <property name="placeholderText">
+ <string>The signature given when the message was signed</string>
+ </property>
+ </widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2_VM">
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index 8ecc33da84..efdd494d9f 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -12,7 +12,7 @@
#include <QResizeEvent>
#include <QPropertyAnimation>
-ModalOverlay::ModalOverlay(QWidget *parent) :
+ModalOverlay::ModalOverlay(bool enable_wallet, QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
@@ -29,6 +29,10 @@ userClosed(false)
blockProcessTime.clear();
setVisible(false);
+ if (!enable_wallet) {
+ ui->infoText->setVisible(false);
+ ui->infoTextStrong->setText(tr("Bitcoin Core is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain."));
+ }
}
ModalOverlay::~ModalOverlay()
diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h
index cf8b53f2b3..c075a89f94 100644
--- a/src/qt/modaloverlay.h
+++ b/src/qt/modaloverlay.h
@@ -21,7 +21,7 @@ class ModalOverlay : public QWidget
Q_OBJECT
public:
- explicit ModalOverlay(QWidget *parent);
+ explicit ModalOverlay(bool enable_wallet, QWidget *parent);
~ModalOverlay();
public Q_SLOTS:
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index 48db95679f..199804f84d 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -39,12 +39,3 @@ void OpenURIDialog::accept()
ui->uriEdit->setValid(false);
}
}
-
-void OpenURIDialog::on_selectFileButton_clicked()
-{
- QString filename = GUIUtil::getOpenFileName(this, tr("Select payment request file to open"), "", "", nullptr);
- if(filename.isEmpty())
- return;
- QUrl fileUri = QUrl::fromLocalFile(filename);
- ui->uriEdit->setText("bitcoin:?r=" + QUrl::toPercentEncoding(fileUri.toString()));
-}
diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h
index e94593d5bb..8438f22bd7 100644
--- a/src/qt/openuridialog.h
+++ b/src/qt/openuridialog.h
@@ -24,9 +24,6 @@ public:
protected Q_SLOTS:
void accept();
-private Q_SLOTS:
- void on_selectFileButton_clicked();
-
private:
Ui::OpenURIDialog *ui;
};
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index d047a82475..d74d0dbfeb 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -18,7 +18,7 @@
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
-#include <QNetworkProxy>
+#include <QDebug>
#include <QSettings>
#include <QStringList>
@@ -483,24 +483,6 @@ void OptionsModel::setDisplayUnit(const QVariant &value)
}
}
-bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
-{
- // Directly query current base proxy, because
- // GUI settings can be overridden with -proxy.
- proxyType curProxy;
- if (m_node.getProxy(NET_IPV4, curProxy)) {
- proxy.setType(QNetworkProxy::Socks5Proxy);
- proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
- proxy.setPort(curProxy.proxy.GetPort());
-
- return true;
- }
- else
- proxy.setType(QNetworkProxy::NoProxy);
-
- return false;
-}
-
void OptionsModel::setRestartRequired(bool fRequired)
{
QSettings settings;
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index b1231b7c7d..5791b47f28 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -13,10 +13,6 @@ namespace interfaces {
class Node;
}
-QT_BEGIN_NAMESPACE
-class QNetworkProxy;
-QT_END_NAMESPACE
-
extern const char *DEFAULT_GUI_PROXY_HOST;
static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050;
@@ -73,7 +69,6 @@ public:
bool getMinimizeOnClose() const { return fMinimizeOnClose; }
int getDisplayUnit() const { return nDisplayUnit; }
QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; }
- bool getProxySettings(QNetworkProxy& proxy) const;
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
diff --git a/src/qt/paymentrequest.proto b/src/qt/paymentrequest.proto
deleted file mode 100644
index d2721a34bd..0000000000
--- a/src/qt/paymentrequest.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Simple Bitcoin Payment Protocol messages
-//
-// Use fields 100+ for extensions;
-// to avoid conflicts, register extensions at:
-// https://en.bitcoin.it/wiki/Payment_Request
-//
-
-syntax = "proto2";
-
-package payments;
-option java_package = "org.bitcoin.protocols.payments";
-option java_outer_classname = "Protos";
-
-// Generalized form of "send payment to this/these bitcoin addresses"
-message Output {
- optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis
- required bytes script = 2; // usually one of the standard Script forms
-}
-message PaymentDetails {
- optional string network = 1 [default = "main"]; // "main" or "test"
- repeated Output outputs = 2; // Where payment should be sent
- required uint64 time = 3; // Timestamp; when payment request created
- optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
- optional string memo = 5; // Human-readable description of request for the customer
- optional string payment_url = 6; // URL to send Payment and get PaymentACK
- optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message
-}
-message PaymentRequest {
- optional uint32 payment_details_version = 1 [default = 1];
- optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1
- optional bytes pki_data = 3; // depends on pki_type
- required bytes serialized_payment_details = 4; // PaymentDetails
- optional bytes signature = 5; // pki-dependent signature
-}
-message X509Certificates {
- repeated bytes certificate = 1; // DER-encoded X.509 certificate chain
-}
-message Payment {
- optional bytes merchant_data = 1; // From PaymentDetails.merchant_data
- repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs
- repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary
- optional string memo = 4; // Human-readable message for the merchant
-}
-message PaymentACK {
- required Payment payment = 1; // Payment message that triggered this ACK
- optional string memo = 2; // human-readable message for customer
-}
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
deleted file mode 100644
index b962ab1ef2..0000000000
--- a/src/qt/paymentrequestplus.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-//
-// Wraps dumb protocol buffer paymentRequest
-// with some extra methods
-//
-
-#include <qt/paymentrequestplus.h>
-
-#include <util/system.h>
-
-#include <stdexcept>
-
-#include <openssl/x509_vfy.h>
-
-#include <QDateTime>
-#include <QDebug>
-#include <QSslCertificate>
-
-class SSLVerifyError : public std::runtime_error
-{
-public:
- explicit SSLVerifyError(std::string err) : std::runtime_error(err) { }
-};
-
-bool PaymentRequestPlus::parse(const QByteArray& data)
-{
- bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
- if (!parseOK) {
- qWarning() << "PaymentRequestPlus::parse: Error parsing payment request";
- return false;
- }
- if (paymentRequest.payment_details_version() > 1) {
- qWarning() << "PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version();
- return false;
- }
-
- parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
- if (!parseOK)
- {
- qWarning() << "PaymentRequestPlus::parse: Error parsing payment details";
- paymentRequest.Clear();
- return false;
- }
- return true;
-}
-
-bool PaymentRequestPlus::SerializeToString(std::string* output) const
-{
- return paymentRequest.SerializeToString(output);
-}
-
-bool PaymentRequestPlus::IsInitialized() const
-{
- return paymentRequest.IsInitialized();
-}
-
-bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
-{
- merchant.clear();
-
- if (!IsInitialized())
- return false;
-
- // One day we'll support more PKI types, but just
- // x509 for now:
- const EVP_MD* digestAlgorithm = nullptr;
- if (paymentRequest.pki_type() == "x509+sha256") {
- digestAlgorithm = EVP_sha256();
- }
- else if (paymentRequest.pki_type() == "x509+sha1") {
- digestAlgorithm = EVP_sha1();
- }
- else if (paymentRequest.pki_type() == "none") {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: pki_type == none";
- return false;
- }
- else {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
- return false;
- }
-
- payments::X509Certificates certChain;
- if (!certChain.ParseFromString(paymentRequest.pki_data())) {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data";
- return false;
- }
-
- std::vector<X509*> certs;
- const QDateTime currentTime = QDateTime::currentDateTime();
- for (int i = 0; i < certChain.certificate_size(); i++) {
- QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
- QSslCertificate qCert(certData, QSsl::Der);
- if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
- return false;
- }
- if (qCert.isBlacklisted()) {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
- return false;
- }
- const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
- X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size());
- if (cert)
- certs.push_back(cert);
- }
- if (certs.empty()) {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: empty certificate chain";
- return false;
- }
-
- // The first cert is the signing cert, the rest are untrusted certs that chain
- // to a valid root authority. OpenSSL needs them separately.
- STACK_OF(X509) *chain = sk_X509_new_null();
- for (int i = certs.size() - 1; i > 0; i--) {
- sk_X509_push(chain, certs[i]);
- }
- X509 *signing_cert = certs[0];
-
- // Now create a "store context", which is a single use object for checking,
- // load the signing cert into it and verify.
- X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
- if (!store_ctx) {
- qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX";
- return false;
- }
-
- char *website = nullptr;
- bool fResult = true;
- try
- {
- if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
- {
- int error = X509_STORE_CTX_get_error(store_ctx);
- throw SSLVerifyError(X509_verify_cert_error_string(error));
- }
-
- // Now do the verification!
- int result = X509_verify_cert(store_ctx);
- if (result != 1) {
- int error = X509_STORE_CTX_get_error(store_ctx);
- // For testing payment requests, we allow self signed root certs!
- if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) {
- throw SSLVerifyError(X509_verify_cert_error_string(error));
- } else {
- qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
- }
- }
- X509_NAME *certname = X509_get_subject_name(signing_cert);
-
- // Valid cert; check signature:
- payments::PaymentRequest rcopy(paymentRequest); // Copy
- rcopy.set_signature(std::string(""));
- std::string data_to_verify; // Everything but the signature
- rcopy.SerializeToString(&data_to_verify);
-
-#if HAVE_DECL_EVP_MD_CTX_NEW
- EVP_MD_CTX *ctx = EVP_MD_CTX_new();
- if (!ctx) throw SSLVerifyError("Error allocating OpenSSL context.");
-#else
- EVP_MD_CTX _ctx;
- EVP_MD_CTX *ctx;
- ctx = &_ctx;
-#endif
- EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
- EVP_MD_CTX_init(ctx);
- if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, nullptr) ||
- !EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) ||
- !EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) {
- throw SSLVerifyError("Bad signature, invalid payment request.");
- }
-#if HAVE_DECL_EVP_MD_CTX_NEW
- EVP_MD_CTX_free(ctx);
-#endif
-
- // OpenSSL API for getting human printable strings from certs is baroque.
- int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, nullptr, 0);
- website = new char[textlen + 1];
- if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
- merchant = website;
- }
- else {
- throw SSLVerifyError("Bad certificate, missing common name.");
- }
- // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
- }
- catch (const SSLVerifyError& err) {
- fResult = false;
- qWarning() << "PaymentRequestPlus::getMerchant: SSL error: " << err.what();
- }
-
- delete[] website;
- X509_STORE_CTX_free(store_ctx);
- for (unsigned int i = 0; i < certs.size(); i++)
- X509_free(certs[i]);
-
- return fResult;
-}
-
-QList<std::pair<CScript,CAmount> > PaymentRequestPlus::getPayTo() const
-{
- QList<std::pair<CScript,CAmount> > result;
- for (int i = 0; i < details.outputs_size(); i++)
- {
- const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data();
- CScript s(scriptStr, scriptStr+details.outputs(i).script().size());
-
- result.append(std::make_pair(s, details.outputs(i).amount()));
- }
- return result;
-}
diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h
deleted file mode 100644
index 3014628807..0000000000
--- a/src/qt/paymentrequestplus.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_QT_PAYMENTREQUESTPLUS_H
-#define BITCOIN_QT_PAYMENTREQUESTPLUS_H
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#include <qt/paymentrequest.pb.h>
-#pragma GCC diagnostic pop
-
-#include <amount.h>
-#include <script/script.h>
-
-#include <openssl/x509.h>
-
-#include <QByteArray>
-#include <QList>
-#include <QString>
-
-static const bool DEFAULT_SELFSIGNED_ROOTCERTS = false;
-
-//
-// Wraps dumb protocol buffer paymentRequest
-// with extra methods
-//
-
-class PaymentRequestPlus
-{
-public:
- PaymentRequestPlus() { }
-
- bool parse(const QByteArray& data);
- bool SerializeToString(std::string* output) const;
-
- bool IsInitialized() const;
- // Returns true if merchant's identity is authenticated, and
- // returns human-readable merchant identity in merchant
- bool getMerchant(X509_STORE* certStore, QString& merchant) const;
-
- // Returns list of outputs, amount
- QList<std::pair<CScript,CAmount> > getPayTo() const;
-
- const payments::PaymentDetails& getDetails() const { return details; }
-
-private:
- payments::PaymentRequest paymentRequest;
- payments::PaymentDetails details;
-};
-
-#endif // BITCOIN_QT_PAYMENTREQUESTPLUS_H
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 806cc3c41e..6ad219ca2d 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -23,8 +23,6 @@
#include <cstdlib>
#include <memory>
-#include <openssl/x509_vfy.h>
-
#include <QApplication>
#include <QByteArray>
#include <QDataStream>
@@ -36,28 +34,11 @@
#include <QList>
#include <QLocalServer>
#include <QLocalSocket>
-#include <QNetworkAccessManager>
-#include <QNetworkProxy>
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QSslCertificate>
-#include <QSslConfiguration>
-#include <QSslError>
#include <QStringList>
-#include <QTextDocument>
#include <QUrlQuery>
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
-#ifdef ENABLE_BIP70
-// BIP70 payment protocol messages
-const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK";
-const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
-// BIP71 payment protocol media types
-const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment";
-const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack";
-const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest";
-#endif
//
// Create a name that is unique for:
@@ -125,32 +106,6 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
}
}
}
-#ifdef ENABLE_BIP70
- else if (QFile::exists(arg)) // Filename
- {
- if (savedPaymentRequests.contains(arg)) continue;
- savedPaymentRequests.insert(arg);
-
- PaymentRequestPlus request;
- if (readPaymentRequestFromFile(arg, request))
- {
- if (request.getDetails().network() == "main")
- {
- node.selectParams(CBaseChainParams::MAIN);
- }
- else if (request.getDetails().network() == "test")
- {
- node.selectParams(CBaseChainParams::TESTNET);
- }
- }
- }
- else
- {
- // Printing to debug.log is about the best we can do here, the
- // GUI hasn't started yet so we can't pop up a message box.
- qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
- }
-#endif
}
}
@@ -198,16 +153,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
saveURIs(true),
uriServer(nullptr),
optionsModel(nullptr)
-#ifdef ENABLE_BIP70
- ,netManager(nullptr)
-#endif
{
-#ifdef ENABLE_BIP70
- // Verify that the version of the library that we linked against is
- // compatible with the version of the headers we compiled against.
- GOOGLE_PROTOBUF_VERIFY_VERSION;
-#endif
-
// Install global event filter to catch QFileOpenEvents
// on Mac: sent when you click bitcoin: links
// other OSes: helpful when dealing with payment request files
@@ -230,24 +176,16 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
}
else {
connect(uriServer, &QLocalServer::newConnection, this, &PaymentServer::handleURIConnection);
-#ifdef ENABLE_BIP70
- connect(this, &PaymentServer::receivedPaymentACK, this, &PaymentServer::handlePaymentACK);
-#endif
}
}
}
PaymentServer::~PaymentServer()
{
-#ifdef ENABLE_BIP70
- google::protobuf::ShutdownProtobufLibrary();
-#endif
}
//
-// OSX-specific way of handling bitcoin: URIs and PaymentRequest mime types.
-// Also used by paymentservertests.cpp and when opening a payment request file
-// via "Open URI..." menu entry.
+// OSX-specific way of handling bitcoin: URIs
//
bool PaymentServer::eventFilter(QObject *object, QEvent *event)
{
@@ -266,10 +204,6 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
void PaymentServer::uiReady()
{
-#ifdef ENABLE_BIP70
- initNetManager();
-#endif
-
saveURIs = false;
for (const QString& s : savedPaymentRequests)
{
@@ -294,48 +228,19 @@ void PaymentServer::handleURIOrFile(const QString& s)
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
QUrlQuery uri((QUrl(s)));
-#ifdef ENABLE_BIP70
- if (uri.hasQueryItem("r")) // payment request URI
- {
- Q_EMIT message(tr("URI handling"),
- tr("You are using a BIP70 URL which will be unsupported in the future."),
- CClientUIInterface::ICON_WARNING);
- QByteArray temp;
- temp.append(uri.queryItemValue("r"));
- QString decoded = QUrl::fromPercentEncoding(temp);
- QUrl fetchUrl(decoded, QUrl::StrictMode);
-
- if (fetchUrl.isValid())
- {
- qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
- fetchRequest(fetchUrl);
- }
- else
- {
- qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
- Q_EMIT message(tr("URI handling"),
- tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
- CClientUIInterface::ICON_WARNING);
- }
- return;
- }
- else
-#endif
// normal URI
{
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
{
if (!IsValidDestinationString(recipient.address.toStdString())) {
-#ifndef ENABLE_BIP70
if (uri.hasQueryItem("r")) { // payment request
Q_EMIT message(tr("URI handling"),
- tr("Cannot process payment request because BIP70 support was not compiled in.")+
+ tr("Cannot process payment request because BIP70 is not supported.")+
tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
}
-#endif
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
@@ -353,26 +258,11 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (QFile::exists(s)) // payment request file
{
-#ifdef ENABLE_BIP70
- PaymentRequestPlus request;
- SendCoinsRecipient recipient;
- if (!readPaymentRequestFromFile(s, request))
- {
- Q_EMIT message(tr("Payment request file handling"),
- tr("Payment request file cannot be read! This can be caused by an invalid payment request file."),
- CClientUIInterface::ICON_WARNING);
- }
- else if (processPaymentRequest(request, recipient))
- Q_EMIT receivedPaymentRequest(recipient);
-
- return;
-#else
Q_EMIT message(tr("Payment request file handling"),
- tr("Cannot process payment request because BIP70 support was not compiled in.")+
+ tr("Cannot process payment request because BIP70 is not supported.")+
tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
CClientUIInterface::ICON_WARNING);
-#endif
}
}
@@ -400,440 +290,3 @@ void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
{
this->optionsModel = _optionsModel;
}
-
-#ifdef ENABLE_BIP70
-struct X509StoreDeleter {
- void operator()(X509_STORE* b) {
- X509_STORE_free(b);
- }
-};
-
-struct X509Deleter {
- void operator()(X509* b) { X509_free(b); }
-};
-
-namespace // Anon namespace
-{
- std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
-}
-
-static void ReportInvalidCertificate(const QSslCertificate& cert)
-{
- qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-}
-
-//
-// Load OpenSSL's list of root certificate authorities
-//
-void PaymentServer::LoadRootCAs(X509_STORE* _store)
-{
- // Unit tests mostly use this, to pass in fake root CAs:
- if (_store)
- {
- certStore.reset(_store);
- return;
- }
-
- // Normal execution, use either -rootcertificates or system certs:
- certStore.reset(X509_STORE_new());
-
- // Note: use "-system-" default here so that users can pass -rootcertificates=""
- // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
- QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-"));
-
- // Empty store
- if (certFile.isEmpty()) {
- qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__);
- return;
- }
-
- QList<QSslCertificate> certList;
-
- if (certFile != "-system-") {
- qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile);
-
- certList = QSslCertificate::fromPath(certFile);
- // Use those certificates when fetching payment requests, too:
- QSslConfiguration::defaultConfiguration().setCaCertificates(certList);
- } else
- certList = QSslConfiguration::systemCaCertificates();
-
- int nRootCerts = 0;
- const QDateTime currentTime = QDateTime::currentDateTime();
-
- for (const QSslCertificate& cert : certList) {
- // Don't log NULL certificates
- if (cert.isNull())
- continue;
-
- // Not yet active/valid, or expired certificate
- if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) {
- ReportInvalidCertificate(cert);
- continue;
- }
-
- // Blacklisted certificate
- if (cert.isBlacklisted()) {
- ReportInvalidCertificate(cert);
- continue;
- }
-
- QByteArray certData = cert.toDer();
- const unsigned char *data = (const unsigned char *)certData.data();
-
- std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
- if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
- {
- // Note: X509_STORE increases the reference count to the X509 object,
- // we still have to release our reference to it.
- ++nRootCerts;
- }
- else
- {
- ReportInvalidCertificate(cert);
- continue;
- }
- }
- qInfo() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
-
- // Project for another day:
- // Fetch certificate revocation lists, and add them to certStore.
- // Issues to consider:
- // performance (start a thread to fetch in background?)
- // privacy (fetch through tor/proxy so IP address isn't revealed)
- // would it be easier to just use a compiled-in blacklist?
- // or use Qt's blacklist?
- // "certificate stapling" with server-side caching is more efficient
-}
-
-void PaymentServer::initNetManager()
-{
- if (!optionsModel)
- return;
- delete netManager;
-
- // netManager is used to fetch paymentrequests given in bitcoin: URIs
- netManager = new QNetworkAccessManager(this);
-
- QNetworkProxy proxy;
-
- // Query active SOCKS5 proxy
- if (optionsModel->getProxySettings(proxy)) {
- netManager->setProxy(proxy);
-
- qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
- }
- else
- qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
-
- connect(netManager, &QNetworkAccessManager::finished, this, &PaymentServer::netRequestFinished);
- connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors);
-}
-
-//
-// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
-// so don't use "Q_EMIT message()", but "QMessageBox::"!
-//
-bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request)
-{
- QFile f(filename);
- if (!f.open(QIODevice::ReadOnly)) {
- qWarning() << QString("PaymentServer::%1: Failed to open %2").arg(__func__).arg(filename);
- return false;
- }
-
- // BIP70 DoS protection
- if (!verifySize(f.size())) {
- return false;
- }
-
- QByteArray data = f.readAll();
-
- return request.parse(data);
-}
-
-bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient)
-{
- if (!optionsModel)
- return false;
-
- if (request.IsInitialized()) {
- // Payment request network matches client network?
- if (!verifyNetwork(optionsModel->node(), request.getDetails())) {
- Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."),
- CClientUIInterface::MSG_ERROR);
-
- return false;
- }
-
- // Make sure any payment requests involved are still valid.
- // This is re-checked just before sending coins in WalletModel::sendCoins().
- if (verifyExpired(request.getDetails())) {
- Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."),
- CClientUIInterface::MSG_ERROR);
-
- return false;
- }
- } else {
- Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."),
- CClientUIInterface::MSG_ERROR);
-
- return false;
- }
-
- recipient.paymentRequest = request;
- recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
-
- request.getMerchant(certStore.get(), recipient.authenticatedMerchant);
-
- QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo();
- QStringList addresses;
-
- for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
- // Extract and check destination addresses
- CTxDestination dest;
- if (ExtractDestination(sendingTo.first, dest)) {
- // Append destination address
- addresses.append(QString::fromStdString(EncodeDestination(dest)));
- }
- else if (!recipient.authenticatedMerchant.isEmpty()) {
- // Unauthenticated payment requests to custom bitcoin addresses are not supported
- // (there is no good way to tell the user where they are paying in a way they'd
- // have a chance of understanding).
- Q_EMIT message(tr("Payment request rejected"),
- tr("Unverified payment requests to custom payment scripts are unsupported."),
- CClientUIInterface::MSG_ERROR);
- return false;
- }
-
- // Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto),
- // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range
- // and no overflow has happened.
- if (!verifyAmount(sendingTo.second)) {
- Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
- return false;
- }
-
- // Extract and check amounts
- CTxOut txOut(sendingTo.second, sendingTo.first);
- if (IsDust(txOut, optionsModel->node().getDustRelayFee())) {
- Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
- .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
- CClientUIInterface::MSG_ERROR);
-
- return false;
- }
-
- recipient.amount += sendingTo.second;
- // Also verify that the final amount is still in a valid range after adding additional amounts.
- if (!verifyAmount(recipient.amount)) {
- Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
- return false;
- }
- }
- // Store addresses and format them to fit nicely into the GUI
- recipient.address = addresses.join("<br />");
-
- if (!recipient.authenticatedMerchant.isEmpty()) {
- qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant;
- }
- else {
- qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", ");
- }
-
- return true;
-}
-
-void PaymentServer::fetchRequest(const QUrl& url)
-{
- QNetworkRequest netRequest;
- netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTREQUEST);
- netRequest.setUrl(url);
- netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
- netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTREQUEST);
- netManager->get(netRequest);
-}
-
-void PaymentServer::fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction)
-{
- const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
- if (!details.has_payment_url())
- return;
-
- QNetworkRequest netRequest;
- netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTACK);
- netRequest.setUrl(QString::fromStdString(details.payment_url()));
- netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BIP71_MIMETYPE_PAYMENT);
- netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
- netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTACK);
-
- payments::Payment payment;
- payment.set_merchant_data(details.merchant_data());
- payment.add_transactions(transaction.data(), transaction.size());
-
- // Create a new refund address, or re-use:
- CTxDestination dest;
- const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::CHANGE_AUTO ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType();
- if (walletModel->wallet().getNewDestination(change_type, "", dest)) {
- // BIP70 requests encode the scriptPubKey directly, so we are not restricted to address
- // types supported by the receiver. As a result, we choose the address format we also
- // use for change. Despite an actual payment and not change, this is a close match:
- // it's the output type we use subject to privacy issues, but not restricted by what
- // other software supports.
- std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString();
- walletModel->wallet().setAddressBook(dest, label, "refund");
-
- CScript s = GetScriptForDestination(dest);
- payments::Output* refund_to = payment.add_refund_to();
- refund_to->set_script(&s[0], s.size());
- } else {
- // This should never happen, because sending coins should have
- // just unlocked the wallet and refilled the keypool.
- qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set";
- }
-
- int length = payment.ByteSize();
- netRequest.setHeader(QNetworkRequest::ContentLengthHeader, length);
- QByteArray serData(length, '\0');
- if (payment.SerializeToArray(serData.data(), length)) {
- netManager->post(netRequest, serData);
- }
- else {
- // This should never happen, either.
- qWarning() << "PaymentServer::fetchPaymentACK: Error serializing payment message";
- }
-}
-
-void PaymentServer::netRequestFinished(QNetworkReply* reply)
-{
- reply->deleteLater();
-
- // BIP70 DoS protection
- if (!verifySize(reply->size())) {
- Q_EMIT message(tr("Payment request rejected"),
- tr("Payment request %1 is too large (%2 bytes, allowed %3 bytes).")
- .arg(reply->request().url().toString())
- .arg(reply->size())
- .arg(BIP70_MAX_PAYMENTREQUEST_SIZE),
- CClientUIInterface::MSG_ERROR);
- return;
- }
-
- if (reply->error() != QNetworkReply::NoError) {
- QString msg = tr("Error communicating with %1: %2")
- .arg(reply->request().url().toString())
- .arg(reply->errorString());
-
- qWarning() << "PaymentServer::netRequestFinished: " << msg;
- Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
- return;
- }
-
- QByteArray data = reply->readAll();
-
- QString requestType = reply->request().attribute(QNetworkRequest::User).toString();
- if (requestType == BIP70_MESSAGE_PAYMENTREQUEST)
- {
- PaymentRequestPlus request;
- SendCoinsRecipient recipient;
- if (!request.parse(data))
- {
- qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request";
- Q_EMIT message(tr("Payment request error"),
- tr("Payment request cannot be parsed!"),
- CClientUIInterface::MSG_ERROR);
- }
- else if (processPaymentRequest(request, recipient))
- Q_EMIT receivedPaymentRequest(recipient);
-
- return;
- }
- else if (requestType == BIP70_MESSAGE_PAYMENTACK)
- {
- payments::PaymentACK paymentACK;
- if (!paymentACK.ParseFromArray(data.data(), data.size()))
- {
- QString msg = tr("Bad response from server %1")
- .arg(reply->request().url().toString());
-
- qWarning() << "PaymentServer::netRequestFinished: " << msg;
- Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
- }
- else
- {
- Q_EMIT receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo()));
- }
- }
-}
-
-void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs)
-{
- Q_UNUSED(reply);
-
- QString errString;
- for (const QSslError& err : errs) {
- qWarning() << "PaymentServer::reportSslErrors: " << err;
- errString += err.errorString() + "\n";
- }
- Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
-}
-
-void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
-{
- // currently we don't further process or store the paymentACK message
- Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
-}
-
-bool PaymentServer::verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails)
-{
- bool fVerified = requestDetails.network() == node.getNetwork();
- if (!fVerified) {
- qWarning() << QString("PaymentServer::%1: Payment request network \"%2\" doesn't match client network \"%3\".")
- .arg(__func__)
- .arg(QString::fromStdString(requestDetails.network()))
- .arg(QString::fromStdString(node.getNetwork()));
- }
- return fVerified;
-}
-
-bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails)
-{
- bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime());
- if (fVerified) {
- const QString requestExpires = QString::fromStdString(FormatISO8601DateTime((int64_t)requestDetails.expires()));
- qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".")
- .arg(__func__)
- .arg(requestExpires);
- }
- return fVerified;
-}
-
-bool PaymentServer::verifySize(qint64 requestSize)
-{
- bool fVerified = (requestSize <= BIP70_MAX_PAYMENTREQUEST_SIZE);
- if (!fVerified) {
- qWarning() << QString("PaymentServer::%1: Payment request too large (%2 bytes, allowed %3 bytes).")
- .arg(__func__)
- .arg(requestSize)
- .arg(BIP70_MAX_PAYMENTREQUEST_SIZE);
- }
- return fVerified;
-}
-
-bool PaymentServer::verifyAmount(const CAmount& requestAmount)
-{
- bool fVerified = MoneyRange(requestAmount);
- if (!fVerified) {
- qWarning() << QString("PaymentServer::%1: Payment request amount out of allowed range (%2, allowed 0 - %3).")
- .arg(__func__)
- .arg(requestAmount)
- .arg(MAX_MONEY);
- }
- return fVerified;
-}
-
-X509_STORE* PaymentServer::getCertStore()
-{
- return certStore.get();
-}
-#endif
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index 30b5bc3b6d..8b2533508d 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -36,9 +36,6 @@
#include <config/bitcoin-config.h>
#endif
-#ifdef ENABLE_BIP70
-#include <qt/paymentrequestplus.h>
-#endif
#include <qt/walletmodel.h>
#include <QObject>
@@ -50,15 +47,9 @@ QT_BEGIN_NAMESPACE
class QApplication;
class QByteArray;
class QLocalServer;
-class QNetworkAccessManager;
-class QNetworkReply;
-class QSslError;
class QUrl;
QT_END_NAMESPACE
-// BIP70 max payment request size in bytes (DoS protection)
-static const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
-
class PaymentServer : public QObject
{
Q_OBJECT
@@ -82,27 +73,6 @@ public:
// OptionsModel is used for getting proxy settings and display unit
void setOptionsModel(OptionsModel *optionsModel);
-#ifdef ENABLE_BIP70
- // Load root certificate authorities. Pass nullptr (default)
- // to read from the file specified in the -rootcertificates setting,
- // or, if that's not set, to use the system default root certificates.
- // If you pass in a store, you should not X509_STORE_free it: it will be
- // freed either at exit or when another set of CAs are loaded.
- static void LoadRootCAs(X509_STORE* store = nullptr);
-
- // Return certificate store
- static X509_STORE* getCertStore();
-
- // Verify that the payment request network matches the client network
- static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails);
- // Verify if the payment request is expired
- static bool verifyExpired(const payments::PaymentDetails& requestDetails);
- // Verify the payment request size is valid as per BIP70
- static bool verifySize(qint64 requestSize);
- // Verify the payment request amount is valid
- static bool verifyAmount(const CAmount& requestAmount);
-#endif
-
Q_SIGNALS:
// Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient);
@@ -110,11 +80,6 @@ Q_SIGNALS:
// Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style);
-#ifdef ENABLE_BIP70
- // Fired when a valid PaymentACK is received
- void receivedPaymentACK(const QString &paymentACKMsg);
-#endif
-
public Q_SLOTS:
// Signal this when the main window's UI is ready
// to display payment requests to the user
@@ -123,18 +88,8 @@ public Q_SLOTS:
// Handle an incoming URI, URI with local file scheme or file
void handleURIOrFile(const QString& s);
-#ifdef ENABLE_BIP70
- // Submit Payment message to a merchant, get back PaymentACK:
- void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
-#endif
-
private Q_SLOTS:
void handleURIConnection();
-#ifdef ENABLE_BIP70
- void netRequestFinished(QNetworkReply*);
- void reportSslErrors(QNetworkReply*, const QList<QSslError> &);
- void handlePaymentACK(const QString& paymentACKMsg);
-#endif
protected:
// Constructor registers this on the parent QApplication to
@@ -145,16 +100,6 @@ private:
bool saveURIs; // true during startup
QLocalServer* uriServer;
OptionsModel *optionsModel;
-
-#ifdef ENABLE_BIP70
- static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
- bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient);
- void fetchRequest(const QUrl& url);
-
- // Setup networking
- void initNetManager();
- QNetworkAccessManager* netManager; // Used to fetch payment requests
-#endif
};
#endif // BITCOIN_QT_PAYMENTSERVER_H
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 99a9a12fe2..af2a1bb0e5 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -9,7 +9,6 @@
#include <qt/guiutil.h>
#include <interfaces/node.h>
-#include <sync.h>
#include <algorithm>
diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp
index bf1baf5470..2332d52b9a 100644
--- a/src/qt/qrimagewidget.cpp
+++ b/src/qt/qrimagewidget.cpp
@@ -71,6 +71,7 @@ bool QRImageWidget::setQR(const QString& data, const QString& text)
if (!text.isEmpty()) {
QFont font = GUIUtil::fixedPitchFont();
+ font.setStyleStrategy(QFont::NoAntialias);
QRect paddedRect = qrAddrImage.rect();
// calculate ideal font size
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4f6629bfe1..3dd64c5273 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1268,22 +1268,24 @@ void RPCConsole::showOrHideBanTableIfRequired()
void RPCConsole::setTabFocus(enum TabTypes tabType)
{
- ui->tabWidget->setCurrentIndex(tabType);
+ ui->tabWidget->setCurrentIndex(int(tabType));
}
QString RPCConsole::tabTitle(TabTypes tab_type) const
{
- return ui->tabWidget->tabText(tab_type);
+ return ui->tabWidget->tabText(int(tab_type));
}
QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const
{
switch (tab_type) {
- case TAB_INFO: return QKeySequence(Qt::CTRL + Qt::Key_I);
- case TAB_CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T);
- case TAB_GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N);
- case TAB_PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P);
- }
+ case TabTypes::INFO: return QKeySequence(Qt::CTRL + Qt::Key_I);
+ case TabTypes::CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T);
+ case TabTypes::GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N);
+ case TabTypes::PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P);
+ } // no default case, so the compiler can warn about missing cases
+
+ assert(false);
}
void RPCConsole::updateAlerts(const QString& warnings)
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 6b0f07baf1..f586d04022 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -58,14 +58,14 @@ public:
CMD_ERROR
};
- enum TabTypes {
- TAB_INFO = 0,
- TAB_CONSOLE = 1,
- TAB_GRAPH = 2,
- TAB_PEERS = 3
+ enum class TabTypes {
+ INFO,
+ CONSOLE,
+ GRAPH,
+ PEERS
};
- std::vector<TabTypes> tabs() const { return {TAB_INFO, TAB_CONSOLE, TAB_GRAPH, TAB_PEERS}; }
+ std::vector<TabTypes> tabs() const { return {TabTypes::INFO, TabTypes::CONSOLE, TabTypes::GRAPH, TabTypes::PEERS}; }
QString tabTitle(TabTypes tab_type) const;
QKeySequence tabShortcut(TabTypes tab_type) const;
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 003a31b248..8edcca684d 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -291,9 +291,6 @@ void SendCoinsDialog::on_sendButton_clicked()
QString recipientElement;
-#ifdef ENABLE_BIP70
- if (!rcp.paymentRequest.IsInitialized()) // normal payment
-#endif
{
if(rcp.label.length() > 0) // label with address
{
@@ -305,17 +302,6 @@ void SendCoinsDialog::on_sendButton_clicked()
recipientElement.append(tr("%1 to %2").arg(amount, address));
}
}
-#ifdef ENABLE_BIP70
- else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request
- {
- recipientElement.append(tr("%1 to '%2'").arg(amount, rcp.authenticatedMerchant));
- }
- else // unauthenticated payment request
- {
- recipientElement.append(tr("%1 to %2").arg(amount, address));
- }
-#endif
-
formatted.append(recipientElement);
}
@@ -558,8 +544,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.second = CClientUIInterface::MSG_WARNING;
// This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn.
- // WalletModel::TransactionCommitFailed is used only in WalletModel::sendCoins()
- // all others are used only in WalletModel::prepareTransaction()
+ // All status values are used only in WalletModel::prepareTransaction()
switch(sendCoinsReturn.status)
{
case WalletModel::InvalidAddress:
@@ -581,10 +566,6 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.first = tr("Transaction creation failed!");
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
- case WalletModel::TransactionCommitFailed:
- msgParams.first = tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed);
- msgParams.second = CClientUIInterface::MSG_ERROR;
- break;
case WalletModel::AbsurdFee:
msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getDefaultMaxTxFee()));
break;
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 7324d759fb..be417655b4 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -137,12 +137,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
// Check input validity
bool retval = true;
-#ifdef ENABLE_BIP70
- // Skip checks for payment request
- if (recipient.paymentRequest.IsInitialized())
- return retval;
-#endif
-
if (!model->validateAddress(ui->payTo->text()))
{
ui->payTo->setValid(false);
@@ -172,13 +166,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
SendCoinsRecipient SendCoinsEntry::getValue()
{
-#ifdef ENABLE_BIP70
- // Payment request
- if (recipient.paymentRequest.IsInitialized())
- return recipient;
-#endif
-
- // Normal payment
recipient.address = ui->payTo->text();
recipient.label = ui->addAsLabel->text();
recipient.amount = ui->payAmount->value();
@@ -203,29 +190,6 @@ QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
recipient = value;
-
-#ifdef ENABLE_BIP70
- if (recipient.paymentRequest.IsInitialized()) // payment request
- {
- if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated
- {
- ui->payTo_is->setText(recipient.address);
- ui->memoTextLabel_is->setText(recipient.message);
- ui->payAmount_is->setValue(recipient.amount);
- ui->payAmount_is->setReadOnly(true);
- setCurrentWidget(ui->SendCoins_UnauthenticatedPaymentRequest);
- }
- else // authenticated
- {
- ui->payTo_s->setText(recipient.authenticatedMerchant);
- ui->memoTextLabel_s->setText(recipient.message);
- ui->payAmount_s->setValue(recipient.amount);
- ui->payAmount_s->setReadOnly(true);
- setCurrentWidget(ui->SendCoins_AuthenticatedPaymentRequest);
- }
- }
- else // normal payment
-#endif
{
// message
ui->messageTextLabel->setText(recipient.message);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 71f5f2ae75..1d0e1323bc 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -14,7 +14,6 @@
#include <util/validation.h> // For strMessageMagic
#include <wallet/wallet.h>
-#include <string>
#include <vector>
#include <QClipboard>
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 0e5abb89f3..26c9fe7ad4 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -17,7 +17,6 @@
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
-#include <version.h>
#include <QApplication>
#include <QCloseEvent>
diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp
index 6750c543da..cf86a5bc1e 100644
--- a/src/qt/test/compattests.cpp
+++ b/src/qt/test/compattests.cpp
@@ -6,10 +6,6 @@
#include <config/bitcoin-config.h>
#endif
-#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
-#include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos
-#endif
-
#include <qt/test/compattests.h>
#include <compat/byteswap.h>
diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h
deleted file mode 100644
index 7f45d30973..0000000000
--- a/src/qt/test/paymentrequestdata.h
+++ /dev/null
@@ -1,465 +0,0 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
-#define BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
-
-//
-// Data for paymentservertests.cpp
-//
-
-// Base64/DER-encoded fake certificate authority certificates.
-// Convert pem to base64/der with:
-// openssl x509 -in cert.pem -inform PEM -outform DER | openssl enc -base64
-
-// Serial Number: 10302349811211485352 (0x8ef94c91b112c0a8)
-// Issuer: CN=PaymentRequest Test CA
-// Subject: CN=PaymentRequest Test CA
-// Not Valid After : Dec 8 16:37:24 2022 GMT
-//
-const char* caCert1_BASE64 =
-"\
-MIIB0DCCATmgAwIBAgIJAI75TJGxEsCoMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
-BAMTFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTIxMjEwMTYzNzI0WhcNMjIx\
-MjA4MTYzNzI0WjAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMIGf\
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvua59nX9radoqDYyplcns5qdVDTN1\
-7tmcGixmMYOYU3UYMU55VSsJs0dWKnMm3COQDY+N63c0XSbRqarBcsLTkaNASuPX\
-FCv1VWuEKSyy5xe4zeoDU7CVSzlxtQD9wbZW/s3ISjgaXBpwn6eVmntb0JwYxxPc\
-M1u/hrMD8BDbSQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA\
-A4GBADSaRgK5xe47XxycXBhHhr0Wgl4pAsFsufqA9aB9r8KNEHJ0yUvvbD/jaJJM\
-RtQcf0AJ9olzUMY4syehxbzUJP6aeXhZEYiMvdvcv9D55clq6+WLLlNT3jBgAaVn\
-p3waRjPD4bUX3nv+ojz5s4puw7Qq5QUZlhGsMzPvwDGCmZkL\
-";
-
-// Serial Number: f0:da:97:e4:38:d7:64:16
-// Issuer: CN=PaymentRequest Test CA
-// Subject: CN=PaymentRequest Test CA
-// Not Valid After : Jan 8 18:21:06 2025 GMT
-//
-const char* caCert2_BASE64 =
-"\
-MIIC1TCCAb2gAwIBAgIJAPDal+Q412QWMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
-BAMMFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTUwMTExMTgyMTA2WhcNMjUw\
-MTA4MTgyMTA2WjAhMR8wHQYDVQQDDBZQYXltZW50UmVxdWVzdCBUZXN0IENBMIIB\
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1S9wVLfTplJuT/1OaaBgl/Mb\
-I392v8S9kHbzYz7B4OTMslaO7piz0v3SO3TKMh0dswjiRdHrIgpO7XdIUQiU/ugg\
-xDw0kuNehfz1ycaGedlFFtFHTNXqLyIUF3dlwHhQwaomM6RXoJmxLny5BhYHEcmk\
-yWwr3Cdjd9gAZpblugVJB9C1e40uyL8ao4PHdLzOqO27iSe6riP8SwwisJZEbMaz\
-AZpgNEEMbIXPJEFvm5HTRXSMtQCOTSZYMFF0M2yrtmlECnz7hWP19b9bcoDzZQB4\
-ylIsFG/7q2jV7MC/e2STZv+niJiHL08RUdoFpAgzaxMgqj63C7B55HgNDNHJYQID\
-AQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBGejPxLxj9\
-+crv6gUeEBMZPiUx7pUgcI22Wm5yymP96B4fwI3Y0DBehq20d76vbWGPN17Z6pH3\
-ge7PVY1SYqXtS6hXTo4olCm/BZADli+2Bs2xCiaa+Ltve4ufVej+bKJXN/YnrhvO\
-Kq+klQkuuHywU+GJV/NQeBqToIrSOBgi477NgLFCCCmmx2QWsxHoCFGfuRCBVseT\
-z2k/tMuALCDXGeZBRPTsGHu1y4cj84swAeoDK5QSQcI+Ub7GKc+zkoj02sdDLiMo\
-3wokYPcIy47oclhmb4xubHc+y7nF610yZBoC/zgbhbawnZ65hDDWkdQ/SVAnWZD7\
-9PFfmNnYPTQH\
-";
-
-//
-// This payment request validates directly against the
-// caCert1 certificate authority.
-//
-const char* paymentrequest1_cert1_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMjEyMTAx\
-NjM3MjRaFw0yMjEyMDgxNjM3MjRaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\
-cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHkMy8W1u6HsWlSqdWTmMKf54gICxNfxbY\
-+rcMtAftr62hCYx2d2QiSRd1pCUzmo12IiSX3WxSHwaTnT3MFD6jRx6+zM6XdGar\
-I2zpYle11ANzu4gAthN17uRQHV2O5QxVtzNaMdKeJLXT2L9tfEdyL++9ZUqoQmdA\
-YG9ix330hQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
-AIkyO99KC68bi9PFRyQQ7nvn5GlQEb3Ca1bRG5+AKN9N5vc8rZ9G2hejtM8wEXni\
-eGBP+chVMsbTPEHKLrwREn7IvcyCcbAStaklPC3w0B/2idQSHskb6P3X13OR2bTH\
-a2+6wuhsOZRUrVNr24rM95DKx/eCC6JN1VW+qRPU6fqzIjQSHwiw2wYSGXapFJVg\
-igPI+6XpExtNLO/i1WFV8ZmoiKwYsuHFiwUqC1VuaXRUZXN0T25lKoABS0j59iMU\
-Uc9MdIfwsO1BskIET0eJSGNZ7eXb9N62u+qf831PMpEHkmlGpk8rHy92nPcgua/U\
-Yt8oZMn3QaTZ5A6HjJbc3A73eLylp1a0SwCl+KDMEvDQhqMn1jAVu2v92AH3uB7n\
-SiWVbw0tX/68iSQEGGfh9n6ee/8Myb3ICdw=\
-";
-
-//
-// Signed, but expired, merchant cert in the request
-//
-const char* paymentrequest2_cert1_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrsAwrpAzCCAeUwggFOoAMCAQICAQMwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzAyMjMy\
-MTI2NDNaFw0xMzAyMjQyMTI2NDNaMD4xHDAaBgNVBAMME2V4cGlyZWRtZXJjaGFu\
-dC5vcmcxHjAcBgNVBAoMFUV4cGlyZWQgVGVzdCBNZXJjaGFudDCBnzANBgkqhkiG\
-9w0BAQEFAAOBjQAwgYkCgYEAx5DMvFtbuh7FpUqnVk5jCn+eICAsTX8W2Pq3DLQH\
-7a+toQmMdndkIkkXdaQlM5qNdiIkl91sUh8Gk509zBQ+o0cevszOl3RmqyNs6WJX\
-tdQDc7uIALYTde7kUB1djuUMVbczWjHSniS109i/bXxHci/vvWVKqEJnQGBvYsd9\
-9IUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaU137\
-j53rvSjlmYZpZ4RWTP7EdD6fl5ZxBeXHytN6DQL33H0eD7OFHt+ofc7E6D7keubl\
-UfCu+jOvt/MvvPUmtCI9yXZ0dNC4sjyETv+wQpxO0UNZwOM4uegdCzlo6Bi3pD4/\
-KKLdMkWuUfuPBmoammny74lZaOVr5deKXztTuCI0Eh8IsNsGEhl2qRSVYIoDyPul\
-6RMbTSzv4tVhVfGZqIisGLLhxYsFKgtVbml0VGVzdFR3byqAAXHuo4nZEPniLpkd\
-y30TkwBxVgprWJ18a9z/7Py35Qss/JMbOXbnBhJtmJCdIowHRI0aa+zqt3KKKAXi\
-mm+V4seMgxTcxMS+eDDkiTcB/RtWWSyRcS2ANjFeY0T4SLMwiCL9qWPi03hr8j96\
-tejrSPOBNSJ3Mi/q5u2Yl4gJZY2b\
-";
-
-//
-// 10-long certificate chain, all intermediates valid
-//
-const char* paymentrequest3_cert1_BASE64 =
-"\
-Egt4NTA5K3NoYTI1Nhq8JAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
-dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\
-MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\
-IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\
-TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\
-hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\
-URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\
-DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\
-nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\
-cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\
-n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\
-C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\
-YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\
-DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\
-aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\
-dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\
-25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\
-plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\
-SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\
-MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\
-KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\
-MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\
-Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\
-MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\
-dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\
-NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\
-W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\
-C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\
-JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\
-AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\
-X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\
-91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\
-ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\
-cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\
-MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\
-b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\
-SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\
-9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\
-4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\
-gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\
-xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\
-IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoKiAQwggIEMIIBbaAD\
-AgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTQub3JnMScw\
-JQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDQwHhcNMTMwMjIz\
-MjI0MjMwWhcNMjMwMjIxMjI0MjMwWjA/MRQwEgYDVQQDDAt0ZXN0Y2E1Lm9yZzEn\
-MCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA1MIGfMA0GCSqG\
-SIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr/xij3k58s8d/BPA0R6D5RXTV\
-vmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tVlRNMdl9EcFsxa8XGEL4eAZa+\
-H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ecuD0NAViqyMrgmaiFmsLoQZpE\
-GepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEdJ\
-Ss8jWiooja3WZzHXeF95QkBJNjIlpDLGcpl4opOYLSuEl9Uxp//LaQQiXuzpj4/I\
-pkWGQmMy5HOyH1lqDyiMgXpcG8PE0jEQAoEUGZ0QEqB1mZ6BCrYvmUuf/5aSVd8Y\
-6lKMR3WzFDYU9Zy0nzuHB/3nvp6MeDRQeRMtYvz4CogEMIICBDCCAW2gAwIBAgIB\
-AjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0Y2EzLm9yZzEnMCUGA1UE\
-CgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAzMB4XDTEzMDIyMzIyNDIy\
-OVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwLdGVzdGNhNC5vcmcxJzAlBgNV\
-BAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNDCBnzANBgkqhkiG9w0B\
-AQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4QgwN/vgreTkiW122Ep/z2TiDrhV\
-MhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSyna5hL0zPTRJxSKmTVrXRsWtp\
-dCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk7gMCpy+yM8f6I043jTlmGb0C\
-AwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDU+IQxt3Oh\
-KqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR2Fs3qw53raHES4SIhpGT9l9l\
-rppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7zlMTQ9OfmZ6v07IpyFbsQDtR\
-hpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCCAgQwggFtoAMCAQICAQIwDQYJ\
-KoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhMi5vcmcxJzAlBgNVBAoMHlBh\
-eW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAeFw0xMzAyMjMyMjQyMjlaFw0y\
-MzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3RjYTMub3JnMScwJQYDVQQKDB5Q\
-YXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMwgZ8wDQYJKoZIhvcNAQEBBQAD\
-gY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7NTBRRsYnBvb/TSWipvMQaCYuE\
-yk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9GQ5PrFLLsOFv7L1tpzXHh2dOB\
-IW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoXh3cavaVeHX1G+IrlAgMBAAGj\
-EDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEASTwg84cX+1UhOG9s\
-ejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDSwqVAv4ch2wi3c2s4e8J7AXyL\
-tzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85+I29uFA6Zj2d9oAhQv2qkHhc\
-6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3\
-DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3JnMScwJQYDVQQKDB5QYXltZW50\
-IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMwMjIzMjI0MjI5WhcNMjMwMjIx\
-MjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9yZzEnMCUGA1UECgweUGF5bWVu\
-dCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\
-iQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxUkvQneQQPH3uZzCyk3A6q72ip\
-TtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfCl1PqXjEZbDobbAQ5hxLGOTyL\
-RQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygvK+9sMbCp/wIDAQABoxAwDjAM\
-BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBACvYyE+PPmWFkbjyRu9LAt8D\
-crtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTqr6LnCIIIwYdXN+4wxugmw4cn\
-PIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTGNgxLdGu1btt7DOFL4zTbeSJM\
-b8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIBAgIBBTANBgkqhkiG9w0BAQsF\
-ADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMB4XDTEzMDIyMzIy\
-NDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UEAwwLdGVzdGNhMS5vcmcxJzAl\
-BgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMTCBnzANBgkqhkiG\
-9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5Ap89yfVNSiTay/LYCaB0eALpc\
-U690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjlYXW1ucQTxWKyT+liu0D25mGX\
-X27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDIIS9y0vYu8eArpjh7m4thrVgI\
-RtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQB9LKcV\
-JK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlKjZ+InsmmyRVGjDoZi9GrqG9P\
-VHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLepM7aDaxDdTHVhSUk4lgNAvi2\
-6dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI2Eh8IsNsGEhl2qRSVYIoDyPul\
-6RMbTSzv4tVhVfGZqIisGLLhxYsFKg1Vbml0VGVzdFRocmVlKoABn2HTsUQtMNI4\
-yNvkfkFNka3pRvTUTydJrvyfmEeLzImfM1BWddZjnywku9RToNFZZNgow5QnljmF\
-chhR/aHOuEMTxmc12K4rNlgYtHCsxLP9zd+6u0cva3TucZ6EzS8PKEib/+r12/52\
-664NuWA9WtsK7QCFrK2K95PnVCRmWl0=\
-";
-
-//
-// Long certificate chain, with an expired certificate in the middle
-//
-const char* paymentrequest4_cert1_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhqeJAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
-dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\
-MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\
-IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\
-TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\
-hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\
-URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\
-DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\
-nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\
-cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\
-n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\
-C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\
-YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\
-DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\
-aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\
-dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\
-25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\
-plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\
-SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\
-MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\
-KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\
-MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\
-Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\
-MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\
-dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\
-NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\
-W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\
-C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\
-JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\
-AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\
-X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\
-91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\
-ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\
-cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\
-MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\
-b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\
-DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\
-SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\
-9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\
-4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\
-gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\
-xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\
-IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoK6gMwggHmMIIBT6AD\
-AgECAgEGMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwHhcNMTMwMjIzMjI1OTUxWhcNMTMwMjI0MjI1OTUxWjA/MRQwEgYD\
-VQQDDAt0ZXN0Y2E1Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVy\
-bWVkaWF0ZSA1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr\
-/xij3k58s8d/BPA0R6D5RXTVvmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tV\
-lRNMdl9EcFsxa8XGEL4eAZa+H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ec\
-uD0NAViqyMrgmaiFmsLoQZpEGepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G\
-CSqGSIb3DQEBCwUAA4GBAEmcUEnhua/oiXy1fwScLgMqt+jk9mHRpE6SVsIop23Q\
-CY2JfpG6RxhMMzzzhGklEGN6cxG0HCi6B3HJx6PYrFEfTB0rW4K6m0Tvx3WpS9mN\
-uoEuJHLy18ausI/sYAPDHCL+SfBVcqorpaIG2sSpZouRBjRHAyqFAYlwlW87uq5n\
-CogEMIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0\
-ZXN0Y2EzLm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0\
-ZSAzMB4XDTEzMDIyMzIyNDIyOVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwL\
-dGVzdGNhNC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlh\
-dGUgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4Qgw\
-N/vgreTkiW122Ep/z2TiDrhVMhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSy\
-na5hL0zPTRJxSKmTVrXRsWtpdCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk\
-7gMCpy+yM8f6I043jTlmGb0CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG\
-9w0BAQsFAAOBgQDU+IQxt3OhKqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR\
-2Fs3qw53raHES4SIhpGT9l9lrppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7\
-zlMTQ9OfmZ6v07IpyFbsQDtRhpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCC\
-AgQwggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNh\
-Mi5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAe\
-Fw0xMzAyMjMyMjQyMjlaFw0yMzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3Rj\
-YTMub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMw\
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7N\
-TBRRsYnBvb/TSWipvMQaCYuEyk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9G\
-Q5PrFLLsOFv7L1tpzXHh2dOBIW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoX\
-h3cavaVeHX1G+IrlAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL\
-BQADgYEASTwg84cX+1UhOG9sejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDS\
-wqVAv4ch2wi3c2s4e8J7AXyLtzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85\
-+I29uFA6Zj2d9oAhQv2qkHhc6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIB\
-baADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3Jn\
-MScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMw\
-MjIzMjI0MjI5WhcNMjMwMjIxMjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9y\
-ZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0G\
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxU\
-kvQneQQPH3uZzCyk3A6q72ipTtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfC\
-l1PqXjEZbDobbAQ5hxLGOTyLRQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygv\
-K+9sMbCp/wIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
-ACvYyE+PPmWFkbjyRu9LAt8DcrtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTq\
-r6LnCIIIwYdXN+4wxugmw4cnPIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTG\
-NgxLdGu1btt7DOFL4zTbeSJMb8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIB\
-AgIBBTANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBU\
-ZXN0IENBMB4XDTEzMDIyMzIyNDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UE\
-AwwLdGVzdGNhMS5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1l\
-ZGlhdGUgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5A\
-p89yfVNSiTay/LYCaB0eALpcU690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjl\
-YXW1ucQTxWKyT+liu0D25mGXX27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDI\
-IS9y0vYu8eArpjh7m4thrVgIRtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq\
-hkiG9w0BAQsFAAOBgQB9LKcVJK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlK\
-jZ+InsmmyRVGjDoZi9GrqG9PVHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLe\
-pM7aDaxDdTHVhSUk4lgNAvi26dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI1\
-Eh8IsNsGEhl2qRSVYIoDyPul6RMbTSzv4tVhVfGZqIisGLLhxYsFKgxVbml0VGVz\
-dEZvdXIqgAEBE1PP93Tkpif35F+dYmXn9kLA/1djcPjCs2o2rwRMM4Uk356O5dgu\
-HXQjsfdR58qZQS9CS5DAtRUf0R8+43/wijO/hb49VNaNXmY+/cPHMkahP2aV3tZi\
-FAyZblLik9A7ZvF+UsjeFQiHB5wzWQvbqk5wQ4yabHIXoYv/E0q+eQ==\
-";
-
-//
-// Validly signed, but by a CA not in our root CA list
-//
-const char* paymentrequest5_cert1_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzA0MTkx\
-NzIwMDZaFw0yMzA0MTcxNzIwMDZaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\
-cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhV6Yn47aEEmbl50YLvXoqGEJA51I/40wr\
-Z6VQGdXYaRqYktagrWDlgYY9h0JQ1bQhm8HgW7ju0R4NaDTXUqxg4HjprF0z3Mfm\
-/6mmebkLOOptfkVD7ceAteNI7cyuqWGIAZA7D9mV97mXoCAtTlBUycvkmoiClCCS\
-h0EpF/UTaQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
-AGIRwW7I0QvLga+RnJoJSZNZQbtu4rQW3xmoz8WfZMBYXX3QBYg5ftycbdK+/IbP\
-qozfjGW2AS6DNArvpveSPDTK9+GJBNo1paiNtVqwXkC3Ddscv5AIms1eZGiIOQNC\
-mUvdLkpoXo48WAer3EGsZ3B15GyNEELc0q9W5yUebba1IjUSHwiw2wYSGXapFJVg\
-igPI+6XpExtNLO/i1WFV8ZmoiKwYuPvFiwUqDFVuaXRUZXN0Rml2ZSqAAXdsMgdG\
-ssymvca1S/1KeM3n8Ydi2fi1JUzAAr59xPvNJRUeqCLP9upHn5z7br3P12Oz9A20\
-5/4wL4ClPRPVnOHgij0bEg+y0tGESqmF1rfOfXDszlo2U92wCxS07kq79YAZJ1Zo\
-XYh860/Q4wvc7lfiTe+dXBzPKAKhMy91yETY\
-";
-
-//
-// Contains a testnet paytoaddress, so payment request network doesn't match client network
-//
-const char* paymentrequest1_cert2_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
-ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
-mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
-wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
-RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
-KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
-+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
-3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
-tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
-yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
-dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iPQoEdGVzdBIhCIDWwowE\
-Ehl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGNeMy6UFKgxKdXN0IFRlc3Rpbmcq\
-gAFwThsozZxkZxzCn4R8WxNiLFV6m0ye9fEtSbolfaW+EjBMpO03lr/dwNnrclhg\
-ew+A05xfZztrAt16XKEY7qKJ/eY2nLd0fVAIu/nIt+7/VYVXT83zLrWc150aRS7W\
-AdJbL3JOJLs6Eyp5zrPbfI8faRttFAdONKDrJgIpuW1E3g==\
-";
-
-//
-// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01)
-//
-const char* paymentrequest2_cert2_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
-ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
-mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
-wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
-RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
-KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
-+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
-3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
-tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
-yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
-dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iQgoEdGVzdBIgCICt4gQS\
-GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYiNLUpQUgASoQVGVzdGluZyB0ZXN0\
-bmV0ISqAATXq9A5nmJgtmee/bQTeHeif4w1YYFPBlKghwx6qbVgXTWnwBJtOQhhV\
-sZdzbTl95ENR7/Y7VJupW9kDWobCK7zUUhLAzUlwmLlcx6itHw8LTUF5HK+AwsZm\
-Zs85lISGvOS0NZW/ENa6l+oQRnL87oqVZr/EDGiuqjz6T0ThQi0l\
-";
-
-//
-// Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t)
-//
-const char* paymentrequest3_cert2_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
-ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
-mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
-wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
-RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
-KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
-+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
-3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
-tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
-yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
-dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSgoEdGVzdBIgCICt4gQS\
-GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYyNfZpQUg//////////9/KhBUZXN0\
-aW5nIHRlc3RuZXQhKoABNwi8WnMW4aMvbmvorTiiWJLFhofLFnsoWCJnj3rWLnLh\
-n3w6q/fZ26p50ERL/noxdTUfeFsKnlECkUu/fOcOrqyYDiwvxI0SZ034DleVyFU1\
-Z3T+X0zcL8oe7bX01Yf+s2V+5JXQXarKnKBrZCGgv2ARjFNSZe7E7vGg5K4Q6Q8=\
-";
-
-//
-// Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64)
-//
-const char* paymentrequest4_cert2_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
-ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
-mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
-wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
-RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
-KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
-+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
-3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
-tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
-yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
-dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSwoEdGVzdBIgCICt4gQS\
-GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYt+HZpQUggICAgICAgICAASoQVGVz\
-dGluZyB0ZXN0bmV0ISqAAXSQG8+GFA18VaKarlYrOz293rNMIub0swKGcQm8jAGX\
-HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\
-d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\
-";
-
-//
-// Payment request with amount overflow (amount is set to 21000001 BTC)
-//
-const char* paymentrequest5_cert2_BASE64 =
-"\
-Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
-BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
-ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
-IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
-mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
-wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
-RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
-KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
-+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
-3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
-tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
-yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
-dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iTAoEdGVzdBIkCIDC9P+F\
-vt0DEhl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGLzcrKYFKhhUZXN0aW5nIGFt\
-b3VudCBvdmVyZmxvdyEqgAG8S7WEDUC6tCL6q2CTBjop/AitgEy31RL9IqYruytR\
-iEBFUrBDJZU+UEezGwr7/zoECjo5ZY3PmtZcM2sILNjyweJF6XVzGqTxUw6pN6sW\
-XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\
-YQ==\
-";
-
-#endif // BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
deleted file mode 100644
index eca468a6ab..0000000000
--- a/src/qt/test/paymentservertests.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <qt/test/paymentservertests.h>
-
-#include <qt/optionsmodel.h>
-#include <qt/test/paymentrequestdata.h>
-
-#include <amount.h>
-#include <chainparams.h>
-#include <interfaces/node.h>
-#include <random.h>
-#include <script/script.h>
-#include <script/standard.h>
-#include <test/setup_common.h>
-#include <util/strencodings.h>
-
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-#include <openssl/x509_vfy.h>
-
-#include <QFileOpenEvent>
-#include <QTemporaryFile>
-
-X509 *parse_b64der_cert(const char* cert_data)
-{
- std::vector<unsigned char> data = DecodeBase64(cert_data);
- assert(data.size() > 0);
- const unsigned char* dptr = data.data();
- X509 *cert = d2i_X509(nullptr, &dptr, data.size());
- assert(cert);
- return cert;
-}
-
-//
-// Test payment request handling
-//
-
-static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
-{
- RecipientCatcher sigCatcher;
- QObject::connect(server, &PaymentServer::receivedPaymentRequest,
- &sigCatcher, &RecipientCatcher::getRecipient);
-
- // Write data to a temp file:
- QTemporaryFile f;
- f.open();
- f.write((const char*)data.data(), data.size());
- f.close();
-
- // Create a QObject, install event filter from PaymentServer
- // and send a file open event to the object
- QObject object;
- object.installEventFilter(server);
- QFileOpenEvent event(f.fileName());
- // If sending the event fails, this will cause sigCatcher to be empty,
- // which will lead to a test failure anyway.
- QCoreApplication::sendEvent(&object, &event);
-
- QObject::disconnect(server, &PaymentServer::receivedPaymentRequest,
- &sigCatcher, &RecipientCatcher::getRecipient);
-
- // Return results from sigCatcher
- return sigCatcher.recipient;
-}
-
-void PaymentServerTests::paymentServerTests()
-{
- SSL_library_init();
- BasicTestingSetup testing_setup(CBaseChainParams::MAIN);
- auto node = interfaces::MakeNode();
- OptionsModel optionsModel(*node);
- PaymentServer* server = new PaymentServer(nullptr, false);
- X509_STORE* caStore = X509_STORE_new();
- X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
- PaymentServer::LoadRootCAs(caStore);
- server->setOptionsModel(&optionsModel);
- server->uiReady();
-
- std::vector<unsigned char> data;
- SendCoinsRecipient r;
- QString merchant;
-
- // Now feed PaymentRequests to server, and observe signals it produces
-
- // This payment request validates directly against the
- // caCert1 certificate authority:
- data = DecodeBase64(paymentrequest1_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString("testmerchant.org"));
-
- // Signed, but expired, merchant cert in the request:
- data = DecodeBase64(paymentrequest2_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString(""));
-
- // 10-long certificate chain, all intermediates valid:
- data = DecodeBase64(paymentrequest3_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString("testmerchant8.org"));
-
- // Long certificate chain, with an expired certificate in the middle:
- data = DecodeBase64(paymentrequest4_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString(""));
-
- // Validly signed, but by a CA not in our root CA list:
- data = DecodeBase64(paymentrequest5_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString(""));
-
- // Try again with no root CA's, verifiedMerchant should be empty:
- caStore = X509_STORE_new();
- PaymentServer::LoadRootCAs(caStore);
- data = DecodeBase64(paymentrequest1_cert1_BASE64);
- r = handleRequest(server, data);
- r.paymentRequest.getMerchant(caStore, merchant);
- QCOMPARE(merchant, QString(""));
-
- // Load second root certificate
- caStore = X509_STORE_new();
- X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
- PaymentServer::LoadRootCAs(caStore);
-
- QByteArray byteArray;
-
- // For the tests below we just need the payment request data from
- // paymentrequestdata.h parsed + stored in r.paymentRequest.
- //
- // These tests require us to bypass the following normal client execution flow
- // shown below to be able to explicitly just trigger a certain condition!
- //
- // handleRequest()
- // -> PaymentServer::eventFilter()
- // -> PaymentServer::handleURIOrFile()
- // -> PaymentServer::readPaymentRequestFromFile()
- // -> PaymentServer::processPaymentRequest()
-
- // Contains a testnet paytoaddress, so payment request network doesn't match client network:
- data = DecodeBase64(paymentrequest1_cert2_BASE64);
- byteArray = QByteArray((const char*)data.data(), data.size());
- r.paymentRequest.parse(byteArray);
- // Ensure the request is initialized, because network "main" is default, even for
- // uninitialized payment requests and that will fail our test here.
- QVERIFY(r.paymentRequest.IsInitialized());
- QCOMPARE(PaymentServer::verifyNetwork(*node, r.paymentRequest.getDetails()), false);
-
- // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
- data = DecodeBase64(paymentrequest2_cert2_BASE64);
- byteArray = QByteArray((const char*)data.data(), data.size());
- r.paymentRequest.parse(byteArray);
- // Ensure the request is initialized
- QVERIFY(r.paymentRequest.IsInitialized());
- // compares 1 < GetTime() == false (treated as expired payment request)
- QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
-
- // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
- // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
- // -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
- data = DecodeBase64(paymentrequest3_cert2_BASE64);
- byteArray = QByteArray((const char*)data.data(), data.size());
- r.paymentRequest.parse(byteArray);
- // Ensure the request is initialized
- QVERIFY(r.paymentRequest.IsInitialized());
- // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
- QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);
-
- // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
- // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
- // 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
- data = DecodeBase64(paymentrequest4_cert2_BASE64);
- byteArray = QByteArray((const char*)data.data(), data.size());
- r.paymentRequest.parse(byteArray);
- // Ensure the request is initialized
- QVERIFY(r.paymentRequest.IsInitialized());
- // compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
- QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
-
- // Test BIP70 DoS protection:
- auto randdata = FastRandomContext().randbytes(BIP70_MAX_PAYMENTREQUEST_SIZE + 1);
-
- // Write data to a temp file:
- QTemporaryFile tempFile;
- tempFile.open();
- tempFile.write((const char*)randdata.data(), randdata.size());
- tempFile.close();
- // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
- QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);
-
- // Payment request with amount overflow (amount is set to 21000001 BTC):
- data = DecodeBase64(paymentrequest5_cert2_BASE64);
- byteArray = QByteArray((const char*)data.data(), data.size());
- r.paymentRequest.parse(byteArray);
- // Ensure the request is initialized
- QVERIFY(r.paymentRequest.IsInitialized());
- // Extract address and amount from the request
- QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
- for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
- CTxDestination dest;
- if (ExtractDestination(sendingTo.first, dest))
- QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
- }
-
- delete server;
-}
-
-void RecipientCatcher::getRecipient(const SendCoinsRecipient& r)
-{
- recipient = r;
-}
diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h
deleted file mode 100644
index 7ef7a0a641..0000000000
--- a/src/qt/test/paymentservertests.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
-#define BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
-
-#include <qt/paymentserver.h>
-
-#include <QObject>
-#include <QTest>
-
-class PaymentServerTests : public QObject
-{
- Q_OBJECT
-
-private Q_SLOTS:
- void paymentServerTests();
-};
-
-// Dummy class to receive paymentserver signals.
-// If SendCoinsRecipient was a proper QObject, then
-// we could use QSignalSpy... but it's not.
-class RecipientCatcher : public QObject
-{
- Q_OBJECT
-
-public Q_SLOTS:
- void getRecipient(const SendCoinsRecipient& r);
-
-public:
- SendCoinsRecipient recipient;
-};
-
-#endif // BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index c39266a397..f272627f96 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -16,9 +16,6 @@
#ifdef ENABLE_WALLET
#include <qt/test/addressbooktests.h>
-#ifdef ENABLE_BIP70
-#include <qt/test/paymentservertests.h>
-#endif // ENABLE_BIP70
#include <qt/test/wallettests.h>
#endif // ENABLE_WALLET
@@ -79,12 +76,6 @@ int main(int argc, char *argv[])
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
-#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
- PaymentServerTests test2;
- if (QTest::qExec(&test2) != 0) {
- fInvalid = true;
- }
-#endif
RPCNestedTests test3;
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 648fdb7673..318b0756c7 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -18,7 +18,6 @@
#include <key_io.h>
#include <validation.h>
#include <script/script.h>
-#include <timedata.h>
#include <util/system.h>
#include <policy/policy.h>
#include <wallet/ismine.h>
@@ -49,7 +48,6 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
}
}
-#ifndef ENABLE_BIP70
// Takes an encoded PaymentRequest as a string and tries to find the Common Name of the X.509 certificate
// used to sign the PaymentRequest.
bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)
@@ -77,7 +75,6 @@ bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)
}
return false;
}
-#endif
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
{
@@ -295,19 +292,11 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
if (r.first == "PaymentRequest")
{
QString merchant;
-#ifdef ENABLE_BIP70
- PaymentRequestPlus req;
- req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
- if (!req.getMerchant(PaymentServer::getCertStore(), merchant)) {
- merchant.clear();
- }
-#else
if (!GetPaymentRequestMerchant(r.second, merchant)) {
merchant.clear();
} else {
merchant += tr(" (Certificate was not verified)");
}
-#endif
if (!merchant.isNull()) {
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
}
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 6509a701f3..095c98d26f 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -11,9 +11,6 @@
#include <qt/forms/ui_helpmessagedialog.h>
#include <qt/bitcoingui.h>
-#ifdef ENABLE_BIP70
-#include <qt/paymentrequestplus.h>
-#endif
#include <clientversion.h>
#include <init.h>
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index fa6f9f3f16..4c253f8ddd 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -12,6 +12,7 @@
#include <interfaces/handler.h>
#include <interfaces/node.h>
+#include <util/string.h>
#include <algorithm>
@@ -108,6 +109,12 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
wallet_model->setParent(this);
m_wallets.push_back(wallet_model);
+ // WalletModel::startPollBalance needs to be called in a thread managed by
+ // Qt because of startTimer. Considering the current thread can be a RPC
+ // thread, better delegate the calling to Qt with Qt::AutoConnection.
+ const bool called = QMetaObject::invokeMethod(wallet_model, "startPollBalance");
+ assert(called);
+
connect(wallet_model, &WalletModel::unload, [this, wallet_model] {
// Defer removeAndDeleteWallet when no modal widget is active.
// TODO: remove this workaround by removing usage of QDiallog::exec.
@@ -226,7 +233,7 @@ void CreateWalletActivity::finish()
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message));
} else if (!m_warning_message.empty()) {
- QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(m_warning_message));
+ QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n")));
}
if (m_wallet_model) Q_EMIT created(m_wallet_model);
@@ -267,7 +274,7 @@ void OpenWalletActivity::finish()
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message));
} else if (!m_warning_message.empty()) {
- QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(m_warning_message));
+ QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n")));
}
if (m_wallet_model) Q_EMIT opened(m_wallet_model);
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
index fb37b7292c..e50dd5c7eb 100644
--- a/src/qt/walletcontroller.h
+++ b/src/qt/walletcontroller.h
@@ -100,7 +100,7 @@ protected:
QProgressDialog* m_progress_dialog{nullptr};
WalletModel* m_wallet_model{nullptr};
std::string m_error_message;
- std::string m_warning_message;
+ std::vector<std::string> m_warning_message;
};
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 94413547d4..d7f0617315 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -9,7 +9,6 @@
#include <qt/walletview.h>
#include <cassert>
-#include <cstdio>
#include <QHBoxLayout>
#include <QLabel>
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 49a13330ec..33801d3907 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -44,11 +44,6 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces:
transactionTableModel = new TransactionTableModel(platformStyle, this);
recentRequestsTableModel = new RecentRequestsTableModel(this);
- // This timer will be fired repeatedly to update the balance
- pollTimer = new QTimer(this);
- connect(pollTimer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged);
- pollTimer->start(MODEL_UPDATE_DELAY);
-
subscribeToCoreSignals();
}
@@ -57,6 +52,14 @@ WalletModel::~WalletModel()
unsubscribeFromCoreSignals();
}
+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::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
@@ -143,31 +146,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
if (rcp.fSubtractFeeFromAmount)
fSubtractFeeFromAmount = true;
-
-#ifdef ENABLE_BIP70
- if (rcp.paymentRequest.IsInitialized())
- { // PaymentRequest...
- CAmount subtotal = 0;
- const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
- for (int i = 0; i < details.outputs_size(); i++)
- {
- const payments::Output& out = details.outputs(i);
- if (out.amount() <= 0) continue;
- subtotal += out.amount();
- const unsigned char* scriptStr = (const unsigned char*)out.script().data();
- CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
- CAmount nAmount = out.amount();
- CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount};
- vecSend.push_back(recipient);
- }
- if (subtotal <= 0)
- {
- return InvalidAmount;
- }
- total += subtotal;
- }
- else
-#endif
{ // User-entered bitcoin address / amount:
if(!validateAddress(rcp.address))
{
@@ -240,29 +218,12 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
std::vector<std::pair<std::string, std::string>> vOrderForm;
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{
-#ifdef ENABLE_BIP70
- if (rcp.paymentRequest.IsInitialized())
- {
- // Make sure any payment requests involved are still valid.
- if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) {
- return PaymentRequestExpired;
- }
-
- // Store PaymentRequests in wtx.vOrderForm in wallet.
- std::string value;
- rcp.paymentRequest.SerializeToString(&value);
- vOrderForm.emplace_back("PaymentRequest", std::move(value));
- }
- else
-#endif
if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
vOrderForm.emplace_back("Message", rcp.message.toStdString());
}
auto& newTx = transaction.getWtx();
- std::string rejectReason;
- if (!wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm), rejectReason))
- return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason));
+ wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << *newTx;
@@ -273,10 +234,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
// and emit coinsSent signal for each recipient
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{
- // Don't touch the address book when we have a payment request
-#ifdef ENABLE_BIP70
- if (!rcp.paymentRequest.IsInitialized())
-#endif
{
std::string strAddress = rcp.address.toStdString();
CTxDestination dest = DecodeDestination(strAddress);
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 54428aec08..d21dec118a 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -5,24 +5,20 @@
#ifndef BITCOIN_QT_WALLETMODEL_H
#define BITCOIN_QT_WALLETMODEL_H
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <amount.h>
#include <key.h>
#include <serialize.h>
#include <script/standard.h>
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#ifdef ENABLE_BIP70
-#include <qt/paymentrequestplus.h>
-#endif
#include <qt/walletmodeltransaction.h>
#include <interfaces/wallet.h>
#include <support/allocators/secure.h>
-#include <map>
#include <vector>
#include <QObject>
@@ -68,15 +64,9 @@ public:
CAmount amount;
// If from a payment request, this is used for storing the memo
QString message;
-
-#ifdef ENABLE_BIP70
- // If from a payment request, paymentRequest.IsInitialized() will be true
- PaymentRequestPlus paymentRequest;
-#else
// If building with BIP70 is disabled, keep the payment request around as
// serialized string to ensure load/store is lossless
std::string sPaymentRequest;
-#endif
// Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant;
@@ -92,11 +82,6 @@ public:
std::string sAddress = address.toStdString();
std::string sLabel = label.toStdString();
std::string sMessage = message.toStdString();
-#ifdef ENABLE_BIP70
- std::string sPaymentRequest;
- if (!ser_action.ForRead() && paymentRequest.IsInitialized())
- paymentRequest.SerializeToString(&sPaymentRequest);
-#endif
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
READWRITE(this->nVersion);
@@ -112,10 +97,6 @@ public:
address = QString::fromStdString(sAddress);
label = QString::fromStdString(sLabel);
message = QString::fromStdString(sMessage);
-#ifdef ENABLE_BIP70
- if (!sPaymentRequest.empty())
- paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
-#endif
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
}
}
@@ -139,7 +120,6 @@ public:
AmountWithFeeExceedsBalance,
DuplicateAddress,
TransactionCreationFailed, // Error returned when wallet is still locked
- TransactionCommitFailed,
AbsurdFee,
PaymentRequestExpired
};
@@ -255,8 +235,6 @@ private:
EncryptionStatus cachedEncryptionStatus;
int cachedNumBlocks;
- QTimer *pollTimer;
-
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
void checkBalanceChanged(const interfaces::WalletBalances& new_balances);
@@ -292,6 +270,9 @@ Q_SIGNALS:
void canGetAddressesChanged();
public Q_SLOTS:
+ /* Starts a timer to periodically update the balance */
+ void startPollBalance();
+
/* Wallet status might have changed */
void updateStatus();
/* New transaction, or transaction changed status */
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index d00ccf70d9..eba95bd27c 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -48,25 +48,6 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
{
SendCoinsRecipient& rcp = (*it);
-
-#ifdef ENABLE_BIP70
- if (rcp.paymentRequest.IsInitialized())
- {
- CAmount subtotal = 0;
- const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
- for (int j = 0; j < details.outputs_size(); j++)
- {
- const payments::Output& out = details.outputs(j);
- if (out.amount() <= 0) continue;
- if (i == nChangePosRet)
- i++;
- subtotal += walletTransaction->vout[i].nValue;
- i++;
- }
- rcp.amount = subtotal;
- }
- else // normal recipient (no payment request)
-#endif
{
if (i == nChangePosRet)
i++;
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index a41d8f2457..242ba13897 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -7,7 +7,6 @@
#include <qt/walletmodel.h>
-#include <memory>
#include <amount.h>
#include <QObject>
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index b177b22b3f..c6eb133cbd 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -6,14 +6,11 @@
#if defined(Q_OS_WIN)
#include <shutdown.h>
-#include <util/system.h>
#include <windows.h>
#include <QDebug>
-#include <openssl/rand.h>
-
// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
@@ -22,16 +19,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM
MSG *pMsg = static_cast<MSG *>(pMessage);
- // Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
- if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
- // Warn only once as this is performance-critical
- static bool warned = false;
- if (!warned) {
- LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
- warned = true;
- }
- }
-
switch(pMsg->message)
{
case WM_QUERYENDSESSION:
diff --git a/src/random.cpp b/src/random.cpp
index 675b177af3..48d20d7d72 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -16,7 +16,6 @@
#include <util/time.h> // for GetTime()
#include <stdlib.h>
-#include <chrono>
#include <thread>
#include <support/allocators/secure.h>
@@ -41,7 +40,6 @@
#include <sys/sysctl.h>
#endif
-#include <mutex>
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
#include <cpuid.h>
@@ -113,7 +111,7 @@ static void InitHardwareRand()
static void ReportHardwareRand()
{
- // This must be done in a separate function, as HWRandInit() may be indirectly called
+ // This must be done in a separate function, as InitHardwareRand() may be indirectly called
// from global constructors, before logging is initialized.
if (g_rdseed_supported) {
LogPrintf("Using RdSeed as additional entropy source\n");
@@ -596,10 +594,6 @@ static void SeedSleep(CSHA512& hasher, RNGState& rng)
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
{
-#ifdef WIN32
- RAND_screen();
-#endif
-
// Gather 256 bits of hardware randomness, if available
SeedHardwareSlow(hasher);
diff --git a/src/rest.cpp b/src/rest.cpp
index 2c4d475542..228c122de3 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -3,7 +3,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <attributes.h>
#include <chain.h>
#include <chainparams.h>
#include <core_io.h>
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 3463145f75..fac6bcd60d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -10,11 +10,11 @@
#include <chain.h>
#include <chainparams.h>
#include <coins.h>
-#include <node/coinstats.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <hash.h>
#include <index/blockfilterindex.h>
+#include <node/coinstats.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -32,10 +32,8 @@
#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
-#include <versionbitsinfo.h>
#include <warnings.h>
-#include <assert.h>
#include <stdint.h>
#include <univalue.h>
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index c2714f9c83..32e18312e1 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -4,7 +4,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/client.h>
-#include <rpc/protocol.h>
#include <util/system.h>
#include <set>
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 1516007201..d73dd6e52d 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -3,16 +3,16 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <crypto/ripemd160.h>
-#include <key_io.h>
#include <httpserver.h>
+#include <key_io.h>
#include <outputtype.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/descriptor.h>
-#include <util/system.h>
+#include <util/check.h>
#include <util/strencodings.h>
+#include <util/system.h>
#include <util/validation.h>
#include <stdint.h>
@@ -541,6 +541,7 @@ static UniValue echo(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"echo|echojson ...",
"\nSimply echo back the input arguments. This command is for testing.\n"
+ "\nIt will return an internal bug report when exactly 100 arguments are passed.\n"
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
"bitcoin-cli and the GUI. There is no server-side difference.",
{},
@@ -549,6 +550,8 @@ static UniValue echo(const JSONRPCRequest& request)
}.ToString()
);
+ CHECK_NONFATAL(request.params.size() != 100);
+
return request.params;
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 7c4b3d0cc6..7b1507e4dc 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -11,7 +11,6 @@
#include <net_processing.h>
#include <net_permissions.h>
#include <netbase.h>
-#include <policy/policy.h>
#include <policy/settings.h>
#include <rpc/protocol.h>
#include <rpc/util.h>
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index f548d356cf..cdcf0c9971 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -5,7 +5,6 @@
#include <chain.h>
#include <coins.h>
-#include <compat/byteswap.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <index/txindex.h>
@@ -23,7 +22,6 @@
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/script.h>
-#include <script/script_error.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <script/standard.h>
@@ -610,7 +608,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
"\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
},
RPCExamples{
- HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]")
+ HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')")
},
}.Check(request);
@@ -858,7 +856,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
"Sign the transaction, and get back the hex\n"
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nTest acceptance of the transaction (signed hex)\n"
- + HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") +
+ + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
},
@@ -906,7 +904,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
result_0.pushKV("allowed", test_accept_res);
if (!test_accept_res) {
if (state.IsInvalid()) {
- result_0.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
+ result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
} else if (missing_inputs) {
result_0.pushKV("reject-reason", "missing-inputs");
} else {
@@ -1226,7 +1224,7 @@ UniValue combinepsbt(const JSONRPCRequest& request)
" \"psbt\" (string) The base64-encoded partially signed transaction\n"
},
RPCExamples{
- HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")
+ HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')")
},
}.Check(request);
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 3e5bb85c1c..91d3e1fca4 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -5,8 +5,6 @@
#include <rpc/server.h>
-#include <fs.h>
-#include <key_io.h>
#include <rpc/util.h>
#include <shutdown.h>
#include <sync.h>
diff --git a/src/rpc/server.h b/src/rpc/server.h
index b060db5bf9..be9c03bf6b 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -8,9 +8,7 @@
#include <amount.h>
#include <rpc/request.h>
-#include <uint256.h>
-#include <list>
#include <map>
#include <stdint.h>
#include <string>
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 72fc7b6286..ec36956c95 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -7,14 +7,15 @@
#include <node/transaction.h>
#include <outputtype.h>
-#include <pubkey.h>
#include <protocol.h>
+#include <pubkey.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/standard.h>
#include <univalue.h>
+#include <util/check.h>
#include <string>
#include <vector>
@@ -146,7 +147,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
- assert(type != Type::ARR && type != Type::OBJ);
+ CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ);
}
RPCArg(
@@ -165,7 +166,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
- assert(type == Type::ARR || type == Type::OBJ);
+ CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ);
}
bool IsOptional() const;
@@ -194,14 +195,14 @@ struct RPCResult {
explicit RPCResult(std::string result)
: m_cond{}, m_result{std::move(result)}
{
- assert(!m_result.empty());
+ CHECK_NONFATAL(!m_result.empty());
}
RPCResult(std::string cond, std::string result)
: m_cond{std::move(cond)}, m_result{std::move(result)}
{
- assert(!m_cond.empty());
- assert(!m_result.empty());
+ CHECK_NONFATAL(!m_cond.empty());
+ CHECK_NONFATAL(!m_result.empty());
}
};
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index ed1bd4cda9..536807e1d8 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -14,6 +14,7 @@
#include <util/spanparsing.h>
#include <util/system.h>
#include <util/strencodings.h>
+#include <util/vector.h>
#include <memory>
#include <string>
@@ -501,22 +502,13 @@ public:
}
};
-/** Construct a vector with one element, which is moved into it. */
-template<typename T>
-std::vector<T> Singleton(T elem)
-{
- std::vector<T> ret;
- ret.emplace_back(std::move(elem));
- return ret;
-}
-
/** A parsed addr(A) descriptor. */
class AddressDescriptor final : public DescriptorImpl
{
const CTxDestination m_destination;
protected:
std::string ToStringExtra() const override { return EncodeDestination(m_destination); }
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(m_destination)); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(m_destination)); }
public:
AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {}
bool IsSolvable() const final { return false; }
@@ -528,7 +520,7 @@ class RawDescriptor final : public DescriptorImpl
const CScript m_script;
protected:
std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); }
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(m_script); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(m_script); }
public:
RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
bool IsSolvable() const final { return false; }
@@ -538,9 +530,9 @@ public:
class PKDescriptor final : public DescriptorImpl
{
protected:
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForRawPubKey(keys[0])); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Vector(GetScriptForRawPubKey(keys[0])); }
public:
- PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pk") {}
+ PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pk") {}
};
/** A parsed pkh(P) descriptor. */
@@ -551,10 +543,10 @@ protected:
{
CKeyID id = keys[0].GetID();
out.pubkeys.emplace(id, keys[0]);
- return Singleton(GetScriptForDestination(PKHash(id)));
+ return Vector(GetScriptForDestination(PKHash(id)));
}
public:
- PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pkh") {}
+ PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "pkh") {}
};
/** A parsed wpkh(P) descriptor. */
@@ -565,10 +557,10 @@ protected:
{
CKeyID id = keys[0].GetID();
out.pubkeys.emplace(id, keys[0]);
- return Singleton(GetScriptForDestination(WitnessV0KeyHash(id)));
+ return Vector(GetScriptForDestination(WitnessV0KeyHash(id)));
}
public:
- WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "wpkh") {}
+ WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "wpkh") {}
};
/** A parsed combo(P) descriptor. */
@@ -591,7 +583,7 @@ protected:
return ret;
}
public:
- ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {}
+ ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {}
};
/** A parsed multi(...) or sortedmulti(...) descriptor */
@@ -605,9 +597,9 @@ protected:
if (m_sorted) {
std::vector<CPubKey> sorted_keys(keys);
std::sort(sorted_keys.begin(), sorted_keys.end());
- return Singleton(GetScriptForMultisig(m_threshold, sorted_keys));
+ return Vector(GetScriptForMultisig(m_threshold, sorted_keys));
}
- return Singleton(GetScriptForMultisig(m_threshold, keys));
+ return Vector(GetScriptForMultisig(m_threshold, keys));
}
public:
MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
@@ -617,7 +609,7 @@ public:
class SHDescriptor final : public DescriptorImpl
{
protected:
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(ScriptHash(*script))); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(ScriptHash(*script))); }
public:
SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
};
@@ -626,7 +618,7 @@ public:
class WSHDescriptor final : public DescriptorImpl
{
protected:
- std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Vector(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
public:
WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
};
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index 0195ca0939..5a1b55259a 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -11,22 +11,24 @@
#include <vector>
-// Descriptors are strings that describe a set of scriptPubKeys, together with
-// all information necessary to solve them. By combining all information into
-// one, they avoid the need to separately import keys and scripts.
-//
-// Descriptors may be ranged, which occurs when the public keys inside are
-// specified in the form of HD chains (xpubs).
-//
-// Descriptors always represent public information - public keys and scripts -
-// but in cases where private keys need to be conveyed along with a descriptor,
-// they can be included inside by changing public keys to private keys (WIF
-// format), and changing xpubs by xprvs.
-//
-// Reference documentation about the descriptor language can be found in
-// doc/descriptors.md.
-
-/** Interface for parsed descriptor objects. */
+
+/** \brief Interface for parsed descriptor objects.
+ *
+ * Descriptors are strings that describe a set of scriptPubKeys, together with
+ * all information necessary to solve them. By combining all information into
+ * one, they avoid the need to separately import keys and scripts.
+ *
+ * Descriptors may be ranged, which occurs when the public keys inside are
+ * specified in the form of HD chains (xpubs).
+ *
+ * Descriptors always represent public information - public keys and scripts -
+ * but in cases where private keys need to be conveyed along with a descriptor,
+ * they can be included inside by changing public keys to private keys (WIF
+ * format), and changing xpubs by xprvs.
+ *
+ * Reference documentation about the descriptor language can be found in
+ * doc/descriptors.md.
+ */
struct Descriptor {
virtual ~Descriptor() = default;
@@ -45,51 +47,51 @@ struct Descriptor {
/** Expand a descriptor at a specified position.
*
- * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
- * provider: the provider to query for private keys in case of hardened derivation.
- * output_scripts: the expanded scriptPubKeys will be put here.
- * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
- * cache: vector which will be overwritten with cache data necessary to evaluate the descriptor at this point without access to private keys.
+ * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored.
+ * @param[in] provider: The provider to query for private keys in case of hardened derivation.
+ * @param[out] output_scripts: The expanded scriptPubKeys.
+ * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).
+ * @param[out] cache: Cache data necessary to evaluate the descriptor at this point without access to private keys.
*/
virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const = 0;
/** Expand a descriptor at a specified position using cached expansion data.
*
- * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
- * cache: vector from which cached expansion data will be read.
- * output_scripts: the expanded scriptPubKeys will be put here.
- * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
+ * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored.
+ * @param[in] cache: Cached expansion data.
+ * @param[out] output_scripts: The expanded scriptPubKeys.
+ * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).
*/
virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
/** Expand the private key for a descriptor at a specified position, if possible.
*
- * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
- * provider: the provider to query for the private keys.
- * out: any private keys available for the specified pos will be placed here.
+ * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored.
+ * @param[in] provider: The provider to query for the private keys.
+ * @param[out] out: Any private keys available for the specified `pos`.
*/
virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0;
};
-/** Parse a descriptor string. Included private keys are put in out.
+/** Parse a `descriptor` string. Included private keys are put in `out`.
*
- * If the descriptor has a checksum, it must be valid. If require_checksum
+ * If the descriptor has a checksum, it must be valid. If `require_checksum`
* is set, the checksum is mandatory - otherwise it is optional.
*
* If a parse error occurs, or the checksum is missing/invalid, or anything
- * else is wrong, nullptr is returned.
+ * else is wrong, `nullptr` is returned.
*/
std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false);
-/** Get the checksum for a descriptor.
+/** Get the checksum for a `descriptor`.
*
- * If it already has one, and it is correct, return the checksum in the input.
- * If it already has one that is wrong, return "".
- * If it does not already have one, return the checksum that would need to be added.
+ * - If it already has one, and it is correct, return the checksum in the input.
+ * - If it already has one that is wrong, return "".
+ * - If it does not already have one, return the checksum that would need to be added.
*/
std::string GetDescriptorChecksum(const std::string& descriptor);
-/** Find a descriptor for the specified script, using information from provider where possible.
+/** Find a descriptor for the specified `script`, using information from `provider` where possible.
*
* A non-ranged descriptor which only generates the specified script will be returned in all
* circumstances.
@@ -98,9 +100,9 @@ std::string GetDescriptorChecksum(const std::string& descriptor);
* descriptor.
*
* - If all information for solving `script` is present in `provider`, a descriptor will be returned
- * which is `IsSolvable()` and encapsulates said information.
+ * which is IsSolvable() and encapsulates said information.
* - Failing that, if `script` corresponds to a known address type, an "addr()" descriptor will be
- * returned (which is not `IsSolvable()`).
+ * returned (which is not IsSolvable()).
* - Failing that, a "raw()" descriptor is returned.
*/
std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider);
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 276ff9a58a..d63d8b85b7 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -11,7 +11,6 @@
#include <vector>
#include <stdint.h>
-#include <string>
class CPubKey;
class CScript;
diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h
index 610f233500..467605ce46 100644
--- a/src/script/keyorigin.h
+++ b/src/script/keyorigin.h
@@ -6,7 +6,6 @@
#define BITCOIN_SCRIPT_KEYORIGIN_H
#include <serialize.h>
-#include <streams.h>
#include <vector>
struct KeyOriginInfo
diff --git a/src/script/sign.h b/src/script/sign.h
index 0e751afd3b..9d0a5b4d70 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -6,7 +6,6 @@
#ifndef BITCOIN_SCRIPT_SIGN_H
#define BITCOIN_SCRIPT_SIGN_H
-#include <boost/optional.hpp>
#include <hash.h>
#include <pubkey.h>
#include <script/interpreter.h>
diff --git a/src/script/standard.h b/src/script/standard.h
index e45e2d92cc..6db28dbc2d 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -11,7 +11,6 @@
#include <boost/variant.hpp>
-#include <stdint.h>
static const bool DEFAULT_ACCEPT_DATACARRIER = true;
diff --git a/src/serialize.h b/src/serialize.h
index a38d76fc18..ef270dbbe3 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -9,7 +9,6 @@
#include <compat/endian.h>
#include <algorithm>
-#include <assert.h>
#include <ios>
#include <limits>
#include <map>
diff --git a/src/streams.h b/src/streams.h
index 517eefc932..b598dc1aeb 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -13,8 +13,6 @@
#include <assert.h>
#include <ios>
#include <limits>
-#include <map>
-#include <set>
#include <stdint.h>
#include <stdio.h>
#include <string>
diff --git a/src/sync.cpp b/src/sync.cpp
index 20258d8e9a..653800ae4e 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -13,10 +13,8 @@
#include <util/strencodings.h>
#include <util/threadnames.h>
-#include <stdio.h>
#include <map>
-#include <memory>
#include <set>
#ifdef DEBUG_LOCKCONTENTION
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 662878750e..e46cf624cf 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -8,7 +8,6 @@
#include <key.h>
#include <key_io.h>
#include <streams.h>
-#include <util/system.h>
#include <util/strencodings.h>
#include <test/setup_common.h>
@@ -119,22 +118,6 @@ static void RunTest(const TestVector &test) {
}
key = keyNew;
pubkey = pubkeyNew;
-
- CDataStream ssPub(SER_DISK, CLIENT_VERSION);
- ssPub << pubkeyNew;
- BOOST_CHECK(ssPub.size() == 75);
-
- CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
- ssPriv << keyNew;
- BOOST_CHECK(ssPriv.size() == 75);
-
- CExtPubKey pubCheck;
- CExtKey privCheck;
- ssPub >> pubCheck;
- ssPriv >> privCheck;
-
- BOOST_CHECK(pubCheck == pubkeyNew);
- BOOST_CHECK(privCheck == keyNew);
}
}
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index cf87aa9303..ba293b7836 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -167,17 +167,23 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
LOCK(cs_main);
tip = ::ChainActive().Tip();
}
- CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
+ CKey coinbase_key_A, coinbase_key_B;
+ coinbase_key_A.MakeNewKey(true);
+ coinbase_key_B.MakeNewKey(true);
+ CScript coinbase_script_pub_key_A = GetScriptForDestination(PKHash(coinbase_key_A.GetPubKey()));
+ CScript coinbase_script_pub_key_B = GetScriptForDestination(PKHash(coinbase_key_B.GetPubKey()));
std::vector<std::shared_ptr<CBlock>> chainA, chainB;
- BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA));
- BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB));
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_A, 10, chainA));
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_B, 10, chainB));
// Check that new blocks on chain A get indexed.
uint256 chainA_last_header = last_header;
for (size_t i = 0; i < 2; i++) {
const auto& block = chainA[i];
BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
-
+ }
+ for (size_t i = 0; i < 2; i++) {
+ const auto& block = chainA[i];
const CBlockIndex* block_index;
{
LOCK(cs_main);
@@ -193,7 +199,9 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
for (size_t i = 0; i < 3; i++) {
const auto& block = chainB[i];
BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
-
+ }
+ for (size_t i = 0; i < 3; i++) {
+ const auto& block = chainB[i];
const CBlockIndex* block_index;
{
LOCK(cs_main);
@@ -221,7 +229,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
// Reorg back to chain A.
for (size_t i = 2; i < 4; i++) {
const auto& block = chainA[i];
- BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
}
// Check that chain A and B blocks can be retrieved.
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index 6cef8cd8a8..c6a08b293f 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -3,8 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compressor.h>
-#include <util/system.h>
#include <test/setup_common.h>
+#include <script/standard.h>
#include <stdint.h>
@@ -62,4 +62,76 @@ BOOST_AUTO_TEST_CASE(compress_amounts)
BOOST_CHECK(TestDecode(i));
}
+BOOST_AUTO_TEST_CASE(compress_script_to_ckey_id)
+{
+ // case CKeyID
+ CKey key;
+ key.MakeNewKey(true);
+ CPubKey pubkey = key.GetPubKey();
+
+ CScript script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK_EQUAL(script.size(), 25);
+
+ std::vector<unsigned char> out;
+ bool done = CompressScript(script, out);
+ BOOST_CHECK_EQUAL(done, true);
+
+ // Check compressed script
+ BOOST_CHECK_EQUAL(out.size(), 21);
+ BOOST_CHECK_EQUAL(out[0], 0x00);
+ BOOST_CHECK_EQUAL(memcmp(&out[1], &script[3], 20), 0); // compare the 20 relevant chars of the CKeyId in the script
+}
+
+BOOST_AUTO_TEST_CASE(compress_script_to_cscript_id)
+{
+ // case CScriptID
+ CScript script, redeemScript;
+ script << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK_EQUAL(script.size(), 23);
+
+ std::vector<unsigned char> out;
+ bool done = CompressScript(script, out);
+ BOOST_CHECK_EQUAL(done, true);
+
+ // Check compressed script
+ BOOST_CHECK_EQUAL(out.size(), 21);
+ BOOST_CHECK_EQUAL(out[0], 0x01);
+ BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 20), 0); // compare the 20 relevant chars of the CScriptId in the script
+}
+
+BOOST_AUTO_TEST_CASE(compress_script_to_compressed_pubkey_id)
+{
+ CKey key;
+ key.MakeNewKey(true); // case compressed PubKeyID
+
+ CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // COMPRESSED_PUBLIC_KEY_SIZE (33)
+ BOOST_CHECK_EQUAL(script.size(), 35);
+
+ std::vector<unsigned char> out;
+ bool done = CompressScript(script, out);
+ BOOST_CHECK_EQUAL(done, true);
+
+ // Check compressed script
+ BOOST_CHECK_EQUAL(out.size(), 33);
+ BOOST_CHECK_EQUAL(memcmp(&out[0], &script[1], 1), 0);
+ BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // compare the 32 chars of the compressed CPubKey
+}
+
+BOOST_AUTO_TEST_CASE(compress_script_to_uncompressed_pubkey_id)
+{
+ CKey key;
+ key.MakeNewKey(false); // case uncompressed PubKeyID
+ CScript script = CScript() << ToByteVector(key.GetPubKey()) << OP_CHECKSIG; // PUBLIC_KEY_SIZE (65)
+ BOOST_CHECK_EQUAL(script.size(), 67); // 1 char code + 65 char pubkey + OP_CHECKSIG
+
+ std::vector<unsigned char> out;
+ bool done = CompressScript(script, out);
+ BOOST_CHECK_EQUAL(done, true);
+
+ // Check compressed script
+ BOOST_CHECK_EQUAL(out.size(), 33);
+ BOOST_CHECK_EQUAL(memcmp(&out[1], &script[2], 32), 0); // first 32 chars of CPubKey are copied into out[1:]
+ BOOST_CHECK_EQUAL(out[0], 0x04 | (script[65] & 0x01)); // least significant bit (lsb) of last char of pubkey is mapped into out[0]
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index efcadd51fc..2ffe4dccdb 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -42,6 +42,86 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
}
}
+BOOST_AUTO_TEST_CASE(dbwrapper_basic_data)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (bool obfuscate : {false, true}) {
+ fs::path ph = GetDataDir() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false");
+ CDBWrapper dbw(ph, (1 << 20), false, true, obfuscate);
+
+ uint256 res;
+ uint32_t res_uint_32;
+ bool res_bool;
+
+ // Ensure that we're doing real obfuscation when obfuscate=true
+ BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
+
+ //Simulate block raw data - "b + block hash"
+ std::string key_block = "b" + InsecureRand256().ToString();
+
+ uint256 in_block = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key_block, in_block));
+ BOOST_CHECK(dbw.Read(key_block, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in_block.ToString());
+
+ //Simulate file raw data - "f + file_number"
+ std::string key_file = strprintf("f%04x", InsecureRand32());
+
+ uint256 in_file_info = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key_file, in_file_info));
+ BOOST_CHECK(dbw.Read(key_file, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in_file_info.ToString());
+
+ //Simulate transaction raw data - "t + transaction hash"
+ std::string key_transaction = "t" + InsecureRand256().ToString();
+
+ uint256 in_transaction = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key_transaction, in_transaction));
+ BOOST_CHECK(dbw.Read(key_transaction, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in_transaction.ToString());
+
+ //Simulate UTXO raw data - "c + transaction hash"
+ std::string key_utxo = "c" + InsecureRand256().ToString();
+
+ uint256 in_utxo = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key_utxo, in_utxo));
+ BOOST_CHECK(dbw.Read(key_utxo, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in_utxo.ToString());
+
+ //Simulate last block file number - "l"
+ char key_last_blockfile_number = 'l';
+ uint32_t lastblockfilenumber = InsecureRand32();
+ BOOST_CHECK(dbw.Write(key_last_blockfile_number, lastblockfilenumber));
+ BOOST_CHECK(dbw.Read(key_last_blockfile_number, res_uint_32));
+ BOOST_CHECK_EQUAL(lastblockfilenumber, res_uint_32);
+
+ //Simulate Is Reindexing - "R"
+ char key_IsReindexing = 'R';
+ bool isInReindexing = InsecureRandBool();
+ BOOST_CHECK(dbw.Write(key_IsReindexing, isInReindexing));
+ BOOST_CHECK(dbw.Read(key_IsReindexing, res_bool));
+ BOOST_CHECK_EQUAL(isInReindexing, res_bool);
+
+ //Simulate last block hash up to which UXTO covers - 'B'
+ char key_lastblockhash_uxto = 'B';
+ uint256 lastblock_hash = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key_lastblockhash_uxto, lastblock_hash));
+ BOOST_CHECK(dbw.Read(key_lastblockhash_uxto, res));
+ BOOST_CHECK_EQUAL(lastblock_hash, res);
+
+ //Simulate file raw data - "F + filename_number + filename"
+ std::string file_option_tag = "F";
+ uint8_t filename_length = InsecureRandBits(8);
+ std::string filename = "randomfilename";
+ std::string key_file_option = strprintf("%s%01x%s", file_option_tag,filename_length,filename);
+
+ bool in_file_bool = InsecureRandBool();
+ BOOST_CHECK(dbw.Write(key_file_option, in_file_bool));
+ BOOST_CHECK(dbw.Read(key_file_option, res_bool));
+ BOOST_CHECK_EQUAL(res_bool, in_file_bool);
+ }
+}
+
// Test batch operations
BOOST_AUTO_TEST_CASE(dbwrapper_batch)
{
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
index 6d5a6641f0..b504a3cbb1 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -15,7 +15,7 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
fs::path tmpfolder = GetDataDir();
// tmpfile1 should be the same as tmpfile2
fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃";
- fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃";
+ fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃";
{
fsbridge::ofstream file(tmpfile1);
file << "bitcoin";
diff --git a/src/test/fuzz/FuzzedDataProvider.h b/src/test/fuzz/FuzzedDataProvider.h
new file mode 100644
index 0000000000..1b5b4bb012
--- /dev/null
+++ b/src/test/fuzz/FuzzedDataProvider.h
@@ -0,0 +1,245 @@
+//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// A single header library providing an utility class to break up an array of
+// bytes. Whenever run on the same input, provides the same output, as long as
+// its methods are called in the same order, with the same arguments.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <cstring>
+#include <initializer_list>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+class FuzzedDataProvider {
+public:
+ // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+ // provide more granular access. |data| must outlive the FuzzedDataProvider.
+ FuzzedDataProvider(const uint8_t *data, size_t size)
+ : data_ptr_(data), remaining_bytes_(size) {}
+ ~FuzzedDataProvider() = default;
+
+ // Returns a std::vector containing |num_bytes| of input data. If fewer than
+ // |num_bytes| of data remain, returns a shorter std::vector containing all
+ // of the data that's left. Can be used with any byte sized type, such as
+ // char, unsigned char, uint8_t, etc.
+ template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes) {
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ return ConsumeBytes<T>(num_bytes, num_bytes);
+ }
+
+ // Similar to |ConsumeBytes|, but also appends the terminator value at the end
+ // of the resulting vector. Useful, when a mutable null-terminated C-string is
+ // needed, for example. But that is a rare case. Better avoid it, if possible,
+ // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
+ template <typename T>
+ std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes,
+ T terminator = 0) {
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+ result.back() = terminator;
+ return result;
+ }
+
+ // Returns a std::string containing |num_bytes| of input data. Using this and
+ // |.c_str()| on the resulting string is the best way to get an immutable
+ // null-terminated C string. If fewer than |num_bytes| of data remain, returns
+ // a shorter std::string containing all of the data that's left.
+ std::string ConsumeBytesAsString(size_t num_bytes) {
+ static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
+ "ConsumeBytesAsString cannot convert the data to a string.");
+
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ std::string result(
+ reinterpret_cast<const std::string::value_type *>(data_ptr_),
+ num_bytes);
+ Advance(num_bytes);
+ return result;
+ }
+
+ // Returns a number in the range [min, max] by consuming bytes from the
+ // input data. The value might not be uniformly distributed in the given
+ // range. If there's no input data left, always returns |min|. |min| must
+ // be less than or equal to |max|.
+ template <typename T> T ConsumeIntegralInRange(T min, T max) {
+ static_assert(std::is_integral<T>::value, "An integral type is required.");
+ static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+ if (min > max)
+ abort();
+
+ // Use the biggest type possible to hold the range and the result.
+ uint64_t range = static_cast<uint64_t>(max) - min;
+ uint64_t result = 0;
+ size_t offset = 0;
+
+ while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
+ remaining_bytes_ != 0) {
+ // Pull bytes off the end of the seed data. Experimentally, this seems to
+ // allow the fuzzer to more easily explore the input space. This makes
+ // sense, since it works by modifying inputs that caused new code to run,
+ // and this data is often used to encode length of data read by
+ // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+ // contents of the data that is actually read.
+ --remaining_bytes_;
+ result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+ offset += CHAR_BIT;
+ }
+
+ // Avoid division by 0, in case |range + 1| results in overflow.
+ if (range != std::numeric_limits<decltype(range)>::max())
+ result = result % (range + 1);
+
+ return static_cast<T>(min + result);
+ }
+
+ // Returns a std::string of length from 0 to |max_length|. When it runs out of
+ // input data, returns what remains of the input. Designed to be more stable
+ // with respect to a fuzzer inserting characters than just picking a random
+ // length and then consuming that many bytes with |ConsumeBytes|.
+ std::string ConsumeRandomLengthString(size_t max_length) {
+ // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+ // followed by anything else to the end of the string. As a result of this
+ // logic, a fuzzer can insert characters into the string, and the string
+ // will be lengthened to include those new characters, resulting in a more
+ // stable fuzzer than picking the length of a string independently from
+ // picking its contents.
+ std::string result;
+
+ // Reserve the anticipated capaticity to prevent several reallocations.
+ result.reserve(std::min(max_length, remaining_bytes_));
+ for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+ char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+ Advance(1);
+ if (next == '\\' && remaining_bytes_ != 0) {
+ next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+ Advance(1);
+ if (next != '\\')
+ break;
+ }
+ result += next;
+ }
+
+ result.shrink_to_fit();
+ return result;
+ }
+
+ // Returns a std::vector containing all remaining bytes of the input data.
+ template <typename T> std::vector<T> ConsumeRemainingBytes() {
+ return ConsumeBytes<T>(remaining_bytes_);
+ }
+
+ // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
+ // object.
+ // Returns a std::vector containing all remaining bytes of the input data.
+ std::string ConsumeRemainingBytesAsString() {
+ return ConsumeBytesAsString(remaining_bytes_);
+ }
+
+ // Returns a number in the range [Type's min, Type's max]. The value might
+ // not be uniformly distributed in the given range. If there's no input data
+ // left, always returns |min|.
+ template <typename T> T ConsumeIntegral() {
+ return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max());
+ }
+
+ // Reads one byte and returns a bool, or false when no data remains.
+ bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); }
+
+ // Returns a copy of a value selected from a fixed-size |array|.
+ template <typename T, size_t size>
+ T PickValueInArray(const T (&array)[size]) {
+ static_assert(size > 0, "The array must be non empty.");
+ return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+ }
+
+ template <typename T>
+ T PickValueInArray(std::initializer_list<const T> list) {
+ // static_assert(list.size() > 0, "The array must be non empty.");
+ return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+ }
+
+ // Return an enum value. The enum must start at 0 and be contiguous. It must
+ // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
+ // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
+ template <typename T> T ConsumeEnum() {
+ static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+ return static_cast<T>(ConsumeIntegralInRange<uint32_t>(
+ 0, static_cast<uint32_t>(T::kMaxValue)));
+ }
+
+ // Reports the remaining bytes available for fuzzed input.
+ size_t remaining_bytes() { return remaining_bytes_; }
+
+private:
+ FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+ FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
+
+ void Advance(size_t num_bytes) {
+ if (num_bytes > remaining_bytes_)
+ abort();
+
+ data_ptr_ += num_bytes;
+ remaining_bytes_ -= num_bytes;
+ }
+
+ template <typename T>
+ std::vector<T> ConsumeBytes(size_t size, size_t num_bytes_to_consume) {
+ static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+ // The point of using the size-based constructor below is to increase the
+ // odds of having a vector object with capacity being equal to the length.
+ // That part is always implementation specific, but at least both libc++ and
+ // libstdc++ allocate the requested number of bytes in that constructor,
+ // which seems to be a natural choice for other implementations as well.
+ // To increase the odds even more, we also call |shrink_to_fit| below.
+ std::vector<T> result(size);
+ std::memcpy(result.data(), data_ptr_, num_bytes_to_consume);
+ Advance(num_bytes_to_consume);
+
+ // Even though |shrink_to_fit| is also implementation specific, we expect it
+ // to provide an additional assurance in case vector's constructor allocated
+ // a buffer which is larger than the actual amount of data we put inside it.
+ result.shrink_to_fit();
+ return result;
+ }
+
+ template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value) {
+ static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+ static_assert(!std::numeric_limits<TU>::is_signed,
+ "Source type must be unsigned.");
+
+ // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+ if (std::numeric_limits<TS>::is_modulo)
+ return static_cast<TS>(value);
+
+ // Avoid using implementation-defined unsigned to signer conversions.
+ // To learn more, see https://stackoverflow.com/questions/13150449.
+ if (value <= std::numeric_limits<TS>::max())
+ return static_cast<TS>(value);
+ else {
+ constexpr auto TS_min = std::numeric_limits<TS>::min();
+ return TS_min + static_cast<char>(value - TS_min);
+ }
+ }
+
+ const uint8_t *data_ptr_;
+ size_t remaining_bytes_;
+};
+
+#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
new file mode 100644
index 0000000000..c4c25854fd
--- /dev/null
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <script/descriptor.h>
+#include <test/fuzz/fuzz.h>
+
+void initialize()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const std::string descriptor(buffer.begin(), buffer.end());
+ FlatSigningProvider signing_provider;
+ std::string error;
+ for (const bool require_checksum : {true, false}) {
+ Parse(descriptor, signing_provider, error, require_checksum);
+ }
+}
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 3a6876ad39..bcd8691359 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -12,6 +12,7 @@
#include <net.h>
#include <primitives/block.h>
#include <protocol.h>
+#include <pubkey.h>
#include <streams.h>
#include <undo.h>
#include <version.h>
@@ -23,6 +24,12 @@
#include <test/fuzz/fuzz.h>
+void initialize()
+{
+ // Fuzzers using pubkey must hold an ECCVerifyHandle.
+ static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+}
+
void test_one_input(const std::vector<uint8_t>& buffer)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp
new file mode 100644
index 0000000000..9444cd489e
--- /dev/null
+++ b/src/test/fuzz/eval_script.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <script/interpreter.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+
+#include <limits>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
+ const std::vector<uint8_t> script_bytes = [&] {
+ if (fuzzed_data_provider.remaining_bytes() != 0) {
+ return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>();
+ } else {
+ // Avoid UBSan warning:
+ // test/fuzz/FuzzedDataProvider.h:212:17: runtime error: null pointer passed as argument 1, which is declared to never be null
+ // /usr/include/string.h:43:28: note: nonnull attribute specified here
+ return std::vector<uint8_t>();
+ }
+ }();
+ const CScript script(script_bytes.begin(), script_bytes.end());
+ for (const auto sig_version : {SigVersion::BASE, SigVersion::WITNESS_V0}) {
+ std::vector<std::vector<unsigned char>> stack;
+ (void)EvalScript(stack, script, flags, BaseSignatureChecker(), sig_version, nullptr);
+ }
+}
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index cfa160dde2..da4e623e98 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -4,11 +4,9 @@
#include <test/fuzz/fuzz.h>
+#include <cstdint>
#include <unistd.h>
-
-#include <pubkey.h>
-#include <util/memory.h>
-
+#include <vector>
static bool read_stdin(std::vector<uint8_t>& data)
{
@@ -22,9 +20,9 @@ static bool read_stdin(std::vector<uint8_t>& data)
return length == 0;
}
-static void initialize()
+// Default initialization: Override using a non-weak initialize().
+__attribute__((weak)) void initialize()
{
- const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
}
// This function is used by libFuzzer
@@ -42,13 +40,9 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
return 0;
}
-// Disabled under WIN32 due to clash with Cygwin's WinMain.
-#ifndef WIN32
// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
-__attribute__((weak))
-#endif
-int main(int argc, char **argv)
+__attribute__((weak)) int main(int argc, char** argv)
{
initialize();
#ifdef __AFL_INIT
diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h
index 573bd572db..3be202b16e 100644
--- a/src/test/fuzz/fuzz.h
+++ b/src/test/fuzz/fuzz.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#include <vector>
-
+void initialize();
void test_one_input(const std::vector<uint8_t>& buffer);
#endif // BITCOIN_TEST_FUZZ_FUZZ_H
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
new file mode 100644
index 0000000000..0469e87de6
--- /dev/null
+++ b/src/test/fuzz/script.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <compressor.h>
+#include <core_io.h>
+#include <core_memusage.h>
+#include <policy/policy.h>
+#include <pubkey.h>
+#include <script/descriptor.h>
+#include <script/script.h>
+#include <script/sign.h>
+#include <script/signingprovider.h>
+#include <script/standard.h>
+#include <streams.h>
+#include <test/fuzz/fuzz.h>
+#include <util/memory.h>
+
+void initialize()
+{
+ // Fuzzers using pubkey must hold an ECCVerifyHandle.
+ static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ const CScript script(buffer.begin(), buffer.end());
+
+ std::vector<unsigned char> compressed;
+ (void)CompressScript(script, compressed);
+
+ CTxDestination address;
+ (void)ExtractDestination(script, address);
+
+ txnouttype type_ret;
+ std::vector<CTxDestination> addresses;
+ int required_ret;
+ (void)ExtractDestinations(script, type_ret, addresses, required_ret);
+
+ (void)GetScriptForWitness(script);
+
+ const FlatSigningProvider signing_provider;
+ (void)InferDescriptor(script, signing_provider);
+
+ (void)IsSegWitOutput(signing_provider, script);
+
+ (void)IsSolvable(signing_provider, script);
+
+ txnouttype which_type;
+ (void)IsStandard(script, which_type);
+
+ (void)RecursiveDynamicUsage(script);
+
+ std::vector<std::vector<unsigned char>> solutions;
+ (void)Solver(script, solutions);
+
+ (void)script.HasValidOps();
+ (void)script.IsPayToScriptHash();
+ (void)script.IsPayToWitnessScriptHash();
+ (void)script.IsPushOnly();
+ (void)script.IsUnspendable();
+ (void)script.GetSigOpCount(/* fAccurate= */ false);
+}
diff --git a/src/test/fuzz/spanparsing.cpp b/src/test/fuzz/spanparsing.cpp
new file mode 100644
index 0000000000..8e5e7dad11
--- /dev/null
+++ b/src/test/fuzz/spanparsing.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <util/spanparsing.h>
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const size_t query_size = fuzzed_data_provider.ConsumeIntegral<size_t>();
+ const std::string query = fuzzed_data_provider.ConsumeBytesAsString(std::min<size_t>(query_size, 1024 * 1024));
+ const std::string span_str = fuzzed_data_provider.ConsumeRemainingBytesAsString();
+ const Span<const char> const_span = MakeSpan(span_str);
+
+ Span<const char> mut_span = const_span;
+ (void)spanparsing::Const(query, mut_span);
+
+ mut_span = const_span;
+ (void)spanparsing::Func(query, mut_span);
+
+ mut_span = const_span;
+ (void)spanparsing::Expr(mut_span);
+
+ if (!query.empty()) {
+ mut_span = const_span;
+ (void)spanparsing::Split(mut_span, query.front());
+ }
+}
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 96d7947b07..383d879040 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -43,12 +43,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
CValidationState state_with_dupe_check;
- const bool valid_with_dupe_check = CheckTransaction(tx, state_with_dupe_check, /* fCheckDuplicateInputs= */ true);
- CValidationState state_without_dupe_check;
- const bool valid_without_dupe_check = CheckTransaction(tx, state_without_dupe_check, /* fCheckDuplicateInputs= */ false);
- if (valid_with_dupe_check) {
- assert(valid_without_dupe_check);
- }
+ (void)CheckTransaction(tx, state_with_dupe_check);
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
std::string reason;
diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp
index abcfc4547b..95587130fc 100644
--- a/src/test/key_properties.cpp
+++ b/src/test/key_properties.cpp
@@ -4,7 +4,6 @@
#include <key.h>
#include <uint256.h>
-#include <util/system.h>
#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/lib/transaction_utils.cpp b/src/test/lib/transaction_utils.cpp
new file mode 100644
index 0000000000..2619fb9006
--- /dev/null
+++ b/src/test/lib/transaction_utils.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/lib/transaction_utils.h>
+
+CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue)
+{
+ CMutableTransaction txCredit;
+ txCredit.nVersion = 1;
+ txCredit.nLockTime = 0;
+ txCredit.vin.resize(1);
+ txCredit.vout.resize(1);
+ txCredit.vin[0].prevout.SetNull();
+ txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
+ txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txCredit.vout[0].scriptPubKey = scriptPubKey;
+ txCredit.vout[0].nValue = nValue;
+
+ return txCredit;
+}
+
+CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit)
+{
+ CMutableTransaction txSpend;
+ txSpend.nVersion = 1;
+ txSpend.nLockTime = 0;
+ txSpend.vin.resize(1);
+ txSpend.vout.resize(1);
+ txSpend.vin[0].scriptWitness = scriptWitness;
+ txSpend.vin[0].prevout.hash = txCredit.GetHash();
+ txSpend.vin[0].prevout.n = 0;
+ txSpend.vin[0].scriptSig = scriptSig;
+ txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txSpend.vout[0].scriptPubKey = CScript();
+ txSpend.vout[0].nValue = txCredit.vout[0].nValue;
+
+ return txSpend;
+}
diff --git a/src/test/lib/transaction_utils.h b/src/test/lib/transaction_utils.h
new file mode 100644
index 0000000000..6f297ac34f
--- /dev/null
+++ b/src/test/lib/transaction_utils.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
+#define BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
+
+#include <primitives/transaction.h>
+
+// create crediting transaction
+// [1 coinbase input => 1 output with given scriptPubkey and value]
+CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0);
+
+// create spending transaction
+// [1 input with referenced transaction outpoint, scriptSig, scriptWitness =>
+// 1 output with empty scriptPubKey, full value of referenced transaction]
+CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit);
+
+#endif // BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 016a4f471b..5368f82ffe 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -6,7 +6,6 @@
#include <policy/fees.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util/system.h>
#include <util/time.h>
#include <test/setup_common.h>
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index deac349867..6c99021d97 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -5,7 +5,6 @@
#include <chain.h>
#include <chainparams.h>
#include <pow.h>
-#include <util/system.h>
#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 84a70fe78b..caa99805c3 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -12,6 +12,7 @@
#include <script/signingprovider.h>
#include <util/system.h>
#include <util/strencodings.h>
+#include <test/lib/transaction_utils.h>
#include <test/setup_common.h>
#include <rpc/util.h>
#include <streams.h>
@@ -121,40 +122,6 @@ static ScriptError_t ParseScriptError(const std::string &name)
BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
-CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0)
-{
- CMutableTransaction txCredit;
- txCredit.nVersion = 1;
- txCredit.nLockTime = 0;
- txCredit.vin.resize(1);
- txCredit.vout.resize(1);
- txCredit.vin[0].prevout.SetNull();
- txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
- txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txCredit.vout[0].scriptPubKey = scriptPubKey;
- txCredit.vout[0].nValue = nValue;
-
- return txCredit;
-}
-
-CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit)
-{
- CMutableTransaction txSpend;
- txSpend.nVersion = 1;
- txSpend.nLockTime = 0;
- txSpend.vin.resize(1);
- txSpend.vout.resize(1);
- txSpend.vin[0].scriptWitness = scriptWitness;
- txSpend.vin[0].prevout.hash = txCredit.GetHash();
- txSpend.vin[0].prevout.n = 0;
- txSpend.vin[0].scriptSig = scriptSig;
- txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txSpend.vout[0].scriptPubKey = CScript();
- txSpend.vout[0].nValue = txCredit.vout[0].nValue;
-
- return txSpend;
-}
-
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0)
{
bool expect = (scriptError == SCRIPT_ERR_OK);
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 3d39dfdb75..1cba3a1297 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
-#include <util/system.h>
#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 638819d564..6075fbfeca 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.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 <random.h>
#include <streams.h>
#include <test/setup_common.h>
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index d794d09d30..0ac4b7ebc9 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -6,7 +6,6 @@
#include <index/txindex.h>
#include <script/standard.h>
#include <test/setup_common.h>
-#include <util/system.h>
#include <util/time.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 31a66b6fa9..02303d0f65 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -13,6 +13,7 @@
#include <util/string.h>
#include <util/time.h>
#include <util/spanparsing.h>
+#include <util/vector.h>
#include <stdint.h>
#include <thread>
@@ -26,6 +27,11 @@
#include <boost/test/unit_test.hpp>
+/* defined in logging.cpp */
+namespace BCLog {
+ std::string LogEscapeMessage(const std::string& str);
+}
+
BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(util_criticalsection)
@@ -1696,4 +1702,122 @@ BOOST_AUTO_TEST_CASE(test_spanparsing)
BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
}
+BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
+{
+ // ASCII and UTF-8 must pass through unaltered.
+ BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
+ // Newlines must pass through unaltered.
+ BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
+ // Other control characters are escaped in C syntax.
+ BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
+ // Embedded NULL characters are escaped too.
+ const std::string NUL("O\x00O", 3);
+ BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
+}
+
+namespace {
+
+struct Tracker
+{
+ //! Points to the original object (possibly itself) we moved/copied from
+ const Tracker* origin;
+ //! How many copies where involved between the original object and this one (moves are not counted)
+ int copies;
+
+ Tracker() noexcept : origin(this), copies(0) {}
+ Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
+ Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
+ Tracker& operator=(const Tracker& t) noexcept
+ {
+ origin = t.origin;
+ copies = t.copies + 1;
+ return *this;
+ }
+ Tracker& operator=(Tracker&& t) noexcept
+ {
+ origin = t.origin;
+ copies = t.copies;
+ return *this;
+ }
+};
+
+}
+
+BOOST_AUTO_TEST_CASE(test_tracked_vector)
+{
+ Tracker t1;
+ Tracker t2;
+ Tracker t3;
+
+ BOOST_CHECK(t1.origin == &t1);
+ BOOST_CHECK(t2.origin == &t2);
+ BOOST_CHECK(t3.origin == &t3);
+
+ auto v1 = Vector(t1);
+ BOOST_CHECK_EQUAL(v1.size(), 1);
+ BOOST_CHECK(v1[0].origin == &t1);
+ BOOST_CHECK_EQUAL(v1[0].copies, 1);
+
+ auto v2 = Vector(std::move(t2));
+ BOOST_CHECK_EQUAL(v2.size(), 1);
+ BOOST_CHECK(v2[0].origin == &t2);
+ BOOST_CHECK_EQUAL(v2[0].copies, 0);
+
+ auto v3 = Vector(t1, std::move(t2));
+ BOOST_CHECK_EQUAL(v3.size(), 2);
+ BOOST_CHECK(v3[0].origin == &t1);
+ BOOST_CHECK(v3[1].origin == &t2);
+ BOOST_CHECK_EQUAL(v3[0].copies, 1);
+ BOOST_CHECK_EQUAL(v3[1].copies, 0);
+
+ auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
+ BOOST_CHECK_EQUAL(v4.size(), 3);
+ BOOST_CHECK(v4[0].origin == &t1);
+ BOOST_CHECK(v4[1].origin == &t2);
+ BOOST_CHECK(v4[2].origin == &t3);
+ BOOST_CHECK_EQUAL(v4[0].copies, 1);
+ BOOST_CHECK_EQUAL(v4[1].copies, 1);
+ BOOST_CHECK_EQUAL(v4[2].copies, 0);
+
+ auto v5 = Cat(v1, v4);
+ BOOST_CHECK_EQUAL(v5.size(), 4);
+ BOOST_CHECK(v5[0].origin == &t1);
+ BOOST_CHECK(v5[1].origin == &t1);
+ BOOST_CHECK(v5[2].origin == &t2);
+ BOOST_CHECK(v5[3].origin == &t3);
+ BOOST_CHECK_EQUAL(v5[0].copies, 2);
+ BOOST_CHECK_EQUAL(v5[1].copies, 2);
+ BOOST_CHECK_EQUAL(v5[2].copies, 2);
+ BOOST_CHECK_EQUAL(v5[3].copies, 1);
+
+ auto v6 = Cat(std::move(v1), v3);
+ BOOST_CHECK_EQUAL(v6.size(), 3);
+ BOOST_CHECK(v6[0].origin == &t1);
+ BOOST_CHECK(v6[1].origin == &t1);
+ BOOST_CHECK(v6[2].origin == &t2);
+ BOOST_CHECK_EQUAL(v6[0].copies, 1);
+ BOOST_CHECK_EQUAL(v6[1].copies, 2);
+ BOOST_CHECK_EQUAL(v6[2].copies, 1);
+
+ auto v7 = Cat(v2, std::move(v4));
+ BOOST_CHECK_EQUAL(v7.size(), 4);
+ BOOST_CHECK(v7[0].origin == &t2);
+ BOOST_CHECK(v7[1].origin == &t1);
+ BOOST_CHECK(v7[2].origin == &t2);
+ BOOST_CHECK(v7[3].origin == &t3);
+ BOOST_CHECK_EQUAL(v7[0].copies, 1);
+ BOOST_CHECK_EQUAL(v7[1].copies, 1);
+ BOOST_CHECK_EQUAL(v7[2].copies, 1);
+ BOOST_CHECK_EQUAL(v7[3].copies, 0);
+
+ auto v8 = Cat(std::move(v2), std::move(v3));
+ BOOST_CHECK_EQUAL(v8.size(), 3);
+ BOOST_CHECK(v8[0].origin == &t2);
+ BOOST_CHECK(v8[1].origin == &t1);
+ BOOST_CHECK(v8[2].origin == &t2);
+ BOOST_CHECK_EQUAL(v8[0].copies, 0);
+ BOOST_CHECK_EQUAL(v8[1].copies, 1);
+ BOOST_CHECK_EQUAL(v8[2].copies, 0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h
index 2743571379..0654c2ab1f 100644
--- a/src/threadinterrupt.h
+++ b/src/threadinterrupt.h
@@ -10,7 +10,6 @@
#include <atomic>
#include <chrono>
#include <condition_variable>
-#include <mutex>
/*
A helper class for interruptible sleeps. Calling operator() will interrupt
diff --git a/src/torcontrol.h b/src/torcontrol.h
index 079146b540..e1a1a7937a 100644
--- a/src/torcontrol.h
+++ b/src/torcontrol.h
@@ -8,7 +8,6 @@
#ifndef BITCOIN_TORCONTROL_H
#define BITCOIN_TORCONTROL_H
-#include <scheduler.h>
extern const std::string DEFAULT_TOR_CONTROL;
static const bool DEFAULT_LISTEN_ONION = true;
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 536bfee901..a7eb5f9f67 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -12,6 +12,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/translation.h>
+#include <util/vector.h>
#include <stdint.h>
@@ -102,7 +103,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
// A vector is used for future extensibility, as we may want to support
// interrupting after partial writes from multiple independent reorgs.
batch.Erase(DB_BEST_BLOCK);
- batch.Write(DB_HEAD_BLOCKS, std::vector<uint256>{hashBlock, old_tip});
+ batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
diff --git a/src/txdb.h b/src/txdb.h
index 140ce2c7ff..05bf4e4453 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -11,7 +11,6 @@
#include <chain.h>
#include <primitives/block.h>
-#include <map>
#include <memory>
#include <string>
#include <utility>
diff --git a/src/txmempool.h b/src/txmempool.h
index 229a923a28..b51e800001 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -8,7 +8,6 @@
#include <atomic>
#include <map>
-#include <memory>
#include <set>
#include <string>
#include <utility>
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 5e0380dc45..9efc2db391 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -8,7 +8,6 @@
#include <functional>
#include <memory>
-#include <stdint.h>
#include <string>
class CBlockIndex;
diff --git a/src/uint256.cpp b/src/uint256.cpp
index ea7164c1f0..ee597e1877 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -7,7 +7,6 @@
#include <util/strencodings.h>
-#include <stdio.h>
#include <string.h>
template <unsigned int BITS>
diff --git a/src/uint256.h b/src/uint256.h
index 97e0cfa015..60c5e0554c 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -8,7 +8,6 @@
#include <assert.h>
#include <cstring>
-#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
diff --git a/src/util/check.h b/src/util/check.h
new file mode 100644
index 0000000000..d18887ae95
--- /dev/null
+++ b/src/util/check.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_CHECK_H
+#define BITCOIN_UTIL_CHECK_H
+
+#include <tinyformat.h>
+
+#include <stdexcept>
+
+class NonFatalCheckError : public std::runtime_error
+{
+ using std::runtime_error::runtime_error;
+};
+
+/**
+ * Throw a NonFatalCheckError when the condition evaluates to false
+ *
+ * This should only be used
+ * - where the condition is assumed to be true, not for error handling or validating user input
+ * - where a failure to fulfill the condition is recoverable and does not abort the program
+ *
+ * For example in RPC code, where it is undersirable to crash the whole program, this can be generally used to replace
+ * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
+ * caller, which can then report the issue to the developers.
+ */
+#define CHECK_NONFATAL(condition) \
+ do { \
+ if (!(condition)) { \
+ throw NonFatalCheckError( \
+ strprintf("%s:%d (%s)\n" \
+ "Internal bug detected: '%s'\n" \
+ "You may report this issue here: %s\n", \
+ __FILE__, __LINE__, __func__, \
+ (#condition), \
+ PACKAGE_BUGREPORT)); \
+ } \
+ } while (false)
+
+#endif // BITCOIN_UTIL_CHECK_H
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index f4e41eea4f..ba5a12e58c 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -5,7 +5,6 @@
#include <util/moneystr.h>
-#include <primitives/transaction.h>
#include <tinyformat.h>
#include <util/strencodings.h>
diff --git a/src/util/moneystr.h b/src/util/moneystr.h
index b8e2812a96..4d0218911a 100644
--- a/src/util/moneystr.h
+++ b/src/util/moneystr.h
@@ -12,7 +12,6 @@
#include <amount.h>
#include <attributes.h>
-#include <cstdint>
#include <string>
/* Do not use these functions to represent or parse monetary amounts to or from
diff --git a/src/util/string.h b/src/util/string.h
index dec0c19b08..76a83a4949 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -5,7 +5,6 @@
#ifndef BITCOIN_UTIL_STRING_H
#define BITCOIN_UTIL_STRING_H
-#include <functional>
#include <string>
#include <vector>
diff --git a/src/util/system.cpp b/src/util/system.cpp
index f22256615f..526bf559c3 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -9,7 +9,6 @@
#include <util/strencodings.h>
#include <util/translation.h>
-#include <stdarg.h>
#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
#include <pthread.h>
@@ -380,6 +379,15 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
for (int i = 1; i < argc; i++) {
std::string key(argv[i]);
+
+#ifdef MAC_OSX
+ // At the first time when a user gets the "App downloaded from the
+ // internet" warning, and clicks the Open button, macOS passes
+ // a unique process serial number (PSN) as -psn_... command-line
+ // argument, which we filter out.
+ if (key.substr(0, 5) == "-psn_") continue;
+#endif
+
if (key == "-") break; //bitcoin-tx using stdin
std::string val;
size_t is_index = key.find('=');
diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp
index 168f9325d0..20df403a66 100644
--- a/src/util/threadnames.cpp
+++ b/src/util/threadnames.cpp
@@ -6,7 +6,6 @@
#include <config/bitcoin-config.h>
#endif
-#include <atomic>
#include <thread>
#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
diff --git a/src/util/translation.h b/src/util/translation.h
index f100dab20d..0e6eb5a094 100644
--- a/src/util/translation.h
+++ b/src/util/translation.h
@@ -7,7 +7,6 @@
#include <tinyformat.h>
-#include <utility>
/**
* Bilingual messages:
diff --git a/src/util/validation.cpp b/src/util/validation.cpp
index fe1f5a277e..9a0d889447 100644
--- a/src/util/validation.cpp
+++ b/src/util/validation.cpp
@@ -11,10 +11,9 @@
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state)
{
- return strprintf("%s%s (code %i)",
+ return strprintf("%s%s",
state.GetRejectReason(),
- state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(),
- state.GetRejectCode());
+ state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage());
}
const std::string strMessageMagic = "Bitcoin Signed Message:\n";
diff --git a/src/util/vector.h b/src/util/vector.h
new file mode 100644
index 0000000000..dab65ded2a
--- /dev/null
+++ b/src/util/vector.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_VECTOR_H
+#define BITCOIN_UTIL_VECTOR_H
+
+#include <initializer_list>
+#include <type_traits>
+#include <vector>
+
+/** Construct a vector with the specified elements.
+ *
+ * This is preferable over the list initializing constructor of std::vector:
+ * - It automatically infers the element type from its arguments.
+ * - If any arguments are rvalue references, they will be moved into the vector
+ * (list initialization always copies).
+ */
+template<typename... Args>
+inline std::vector<typename std::common_type<Args...>::type> Vector(Args&&... args)
+{
+ std::vector<typename std::common_type<Args...>::type> ret;
+ ret.reserve(sizeof...(args));
+ // The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html
+ (void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...};
+ return ret;
+}
+
+/** Concatenate two vectors, moving elements. */
+template<typename V>
+inline V Cat(V v1, V&& v2)
+{
+ v1.reserve(v1.size() + v2.size());
+ for (auto& arg : v2) {
+ v1.push_back(std::move(arg));
+ }
+ return v1;
+}
+
+/** Concatenate two vectors. */
+template<typename V>
+inline V Cat(V v1, const V& v2)
+{
+ v1.reserve(v1.size() + v2.size());
+ for (const auto& arg : v2) {
+ v1.push_back(arg);
+ }
+ return v1;
+}
+
+#endif // BITCOIN_UTIL_VECTOR_H
diff --git a/src/validation.cpp b/src/validation.cpp
index 726f251c5a..9301066c6a 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -28,7 +28,6 @@
#include <reverse_iterator.h>
#include <script/script.h>
#include <script/sigcache.h>
-#include <script/standard.h>
#include <shutdown.h>
#include <timedata.h>
#include <tinyformat.h>
@@ -46,8 +45,6 @@
#include <validationinterface.h>
#include <warnings.h>
-#include <future>
-#include <sstream>
#include <string>
#include <boost/algorithm/string/replace.hpp>
@@ -395,7 +392,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions& disconnectpool,
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
// were somehow broken and returning the wrong scriptPubKeys
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool,
- unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+ unsigned int flags, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
AssertLockHeld(cs_main);
// pool.cs should be locked already, but go ahead and re-take the lock here
@@ -425,7 +422,8 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
}
}
- return CheckInputs(tx, state, view, flags, cacheSigStore, true, txdata);
+ // Call CheckInputs() to cache signature and script validity against current tip consensus rules.
+ return CheckInputs(tx, state, view, flags, /* cacheSigStore = */ true, /* cacheFullSciptStore = */ true, txdata);
}
namespace {
@@ -508,11 +506,11 @@ private:
{
CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size);
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
}
if (package_fee < ::minRelayTxFee.GetFee(package_size)) {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size)));
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size)));
}
return true;
}
@@ -565,29 +563,29 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Coinbase is only valid in a block, not as a loose transaction
if (tx.IsCoinBase())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "coinbase");
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
std::string reason;
if (fRequireStandard && !IsStandardTx(tx, reason))
- return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, reason);
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, reason);
// Do not work on transactions that are too small.
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
// Transactions smaller than this are not relayed to mitigate CVE-2017-12842 by not relaying
// 64-byte transactions.
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE)
- return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "tx-size-small");
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "tx-size-small");
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
- return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-final");
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "non-final");
// is it already in the memory pool?
if (m_pool.exists(hash)) {
- return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-in-mempool");
+ return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, "txn-already-in-mempool");
}
// Check for conflicts with in-memory transactions
@@ -619,7 +617,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
}
}
if (fReplacementOptOut) {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_DUPLICATE, "txn-mempool-conflict");
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "txn-mempool-conflict");
}
setConflicts.insert(ptxConflicting->GetHash());
@@ -645,7 +643,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
for (size_t out = 0; out < tx.vout.size(); out++) {
// Optimistically just do efficient check of cache for outputs
if (coins_cache.HaveCoinInCache(COutPoint(hash, out))) {
- return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-known");
+ return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, "txn-already-known");
}
}
// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet
@@ -670,7 +668,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
// CoinsViewCache instead of create its own
if (!CheckSequenceLocks(m_pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
- return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-BIP68-final");
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "non-BIP68-final");
CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), nFees)) {
@@ -679,11 +677,11 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Check for non-standard pay-to-script-hash in inputs
if (fRequireStandard && !AreInputsStandard(tx, m_view))
- return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "bad-txns-nonstandard-inputs");
// Check for non-standard witness in P2WSH
if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view))
- return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, REJECT_NONSTANDARD, "bad-witness-nonstandard");
+ return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, "bad-witness-nonstandard");
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -707,7 +705,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
unsigned int nSize = entry->GetTxSize();
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
- return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops",
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, "bad-txns-too-many-sigops",
strprintf("%d", nSigOpsCost));
// No transactions are allowed below minRelayTxFee except from disconnected
@@ -716,8 +714,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
if (nAbsurdFee && nFees > nAbsurdFee)
return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false,
- REJECT_HIGHFEE, "absurdly-high-fee",
- strprintf("%d > %d", nFees, nAbsurdFee));
+ "absurdly-high-fee", strprintf("%d > %d", nFees, nAbsurdFee));
const CTxMemPool::setEntries setIterConflicting = m_pool.GetIterSet(setConflicts);
// Calculate in-mempool ancestors, up to a limit.
@@ -774,7 +771,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
if (nSize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
!m_pool.CalculateMemPoolAncestors(*entry, setAncestors, 2, m_limit_ancestor_size, m_limit_descendants + 1, m_limit_descendant_size + EXTRA_DESCENDANT_TX_SIZE_LIMIT, dummy_err_string)) {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too-long-mempool-chain", errString);
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "too-long-mempool-chain", errString);
}
}
@@ -787,7 +784,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
const uint256 &hashAncestor = ancestorIt->GetTx().GetHash();
if (setConflicts.count(hashAncestor))
{
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-spends-conflicting-tx",
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-spends-conflicting-tx",
strprintf("%s spends conflicting transaction %s",
hash.ToString(),
hashAncestor.ToString()));
@@ -827,7 +824,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee",
strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
hash.ToString(),
newFeeRate.ToString(),
@@ -855,7 +852,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
nConflictingSize += it->GetTxSize();
}
} else {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too many potential replacements",
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "too many potential replacements",
strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
hash.ToString(),
nConflictingCount,
@@ -879,7 +876,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
if (m_pool.exists(tx.vin[j].prevout.hash)) {
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "replacement-adds-unconfirmed",
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "replacement-adds-unconfirmed",
strprintf("replacement %s adds unconfirmed input, idx %d",
hash.ToString(), j));
}
@@ -891,7 +888,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// transactions would not be paid for.
if (nModifiedFees < nConflictingFees)
{
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee",
strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)));
}
@@ -901,7 +898,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
CAmount nDeltaFees = nModifiedFees - nConflictingFees;
if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize))
{
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "insufficient fee",
strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
hash.ToString(),
FormatMoney(nDeltaFees),
@@ -930,7 +927,7 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, Precompute
!CheckInputs(tx, stateDummy, m_view, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, false, txdata)) {
// Only the witness is missing, so the transaction itself may be fine.
state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false,
- state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
+ state.GetRejectReason(), state.GetDebugMessage());
}
assert(IsTransactionReason(state.GetReason()));
return false; // state filled in by CheckInputs
@@ -963,7 +960,7 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, Precomp
// invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack.
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
- if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, true, txdata)) {
+ if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata)) {
return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed against latest-block but not STANDARD flags %s, %s",
__func__, hash.ToString(), FormatStateMessage(state));
}
@@ -1013,7 +1010,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)
if (!bypass_limits) {
LimitMempoolSize(m_pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
if (!m_pool.exists(hash))
- return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full");
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, "mempool full");
}
return true;
}
@@ -1548,7 +1545,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
CScriptCheck check2(coin.out, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
if (check2())
- return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
}
// MANDATORY flag failures correspond to
// ValidationInvalidReason::CONSENSUS. Because CONSENSUS
@@ -1559,7 +1556,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// support, to avoid splitting the network (but this
// depends on the details of how net_processing handles
// such errors).
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
}
}
@@ -2062,7 +2059,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
for (size_t o = 0; o < tx->vout.size(); o++) {
if (view.HaveCoin(COutPoint(tx->GetHash(), o))) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): tried to overwrite transaction"),
- REJECT_INVALID, "bad-txns-BIP30");
+ "bad-txns-BIP30");
}
}
}
@@ -2107,14 +2104,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// defined for a block, so we reset the reason flag to
// CONSENSUS here.
state.Invalid(ValidationInvalidReason::CONSENSUS, false,
- state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
+ state.GetRejectReason(), state.GetDebugMessage());
}
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
}
nFees += txfee;
if (!MoneyRange(nFees)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: accumulated fee in the block out of range.", __func__),
- REJECT_INVALID, "bad-txns-accumulated-fee-outofrange");
+ "bad-txns-accumulated-fee-outofrange");
}
// Check that transaction is BIP68 final
@@ -2127,7 +2124,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: contains a non-BIP68-final transaction", __func__),
- REJECT_INVALID, "bad-txns-nonfinal");
+ "bad-txns-nonfinal");
}
}
@@ -2138,7 +2135,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
nSigOpsCost += GetTransactionSigOpCost(tx, view, flags);
if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST)
return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): too many sigops"),
- REJECT_INVALID, "bad-blk-sigops");
+ "bad-blk-sigops");
txdata.emplace_back(tx);
if (!tx.IsCoinBase())
@@ -2154,7 +2151,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// consider whether rewriting to CONSENSUS or
// RECENT_CONSENSUS_CHANGE would be more appropriate.
state.Invalid(ValidationInvalidReason::CONSENSUS, false,
- state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
+ state.GetRejectReason(), state.GetDebugMessage());
}
return error("ConnectBlock(): CheckInputs on %s failed with %s",
tx.GetHash().ToString(), FormatStateMessage(state));
@@ -2176,10 +2173,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
return state.Invalid(ValidationInvalidReason::CONSENSUS,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0]->GetValueOut(), blockReward),
- REJECT_INVALID, "bad-cb-amount");
+ "bad-cb-amount");
if (!control.Wait())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: CheckQueue failed", __func__), "block-validation-failed");
int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2;
LogPrint(BCLog::BENCH, " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n", nInputs - 1, MILLI * (nTime4 - nTime2), nInputs <= 1 ? 0 : MILLI * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * MICRO, nTimeVerify * MILLI / nBlocksTotal);
@@ -3256,7 +3253,7 @@ static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state,
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "high-hash", "proof of work failed");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "high-hash", "proof of work failed");
return true;
}
@@ -3278,13 +3275,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
bool mutated;
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
if (block.hashMerkleRoot != hashMerkleRoot2)
- return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txnmrklroot", "hashMerkleRoot mismatch");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-txnmrklroot", "hashMerkleRoot mismatch");
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
// of transactions in a block without affecting the merkle root of a block,
// while still invalidating it.
if (mutated)
- return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txns-duplicate", "duplicate transaction");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-txns-duplicate", "duplicate transaction");
}
// All potential-corruption validation must be done before we do any
@@ -3295,20 +3292,19 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
// Size limits
if (block.vtx.empty() || block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT || ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-length", "size limits failed");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-length", "size limits failed");
// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0]->IsCoinBase())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-missing", "first tx is not coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-missing", "first tx is not coinbase");
for (unsigned int i = 1; i < block.vtx.size(); i++)
if (block.vtx[i]->IsCoinBase())
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-multiple", "more than one coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-multiple", "more than one coinbase");
// Check transactions
- // Must check for duplicate inputs (see CVE-2018-17144)
for (const auto& tx : block.vtx)
- if (!CheckTransaction(*tx, state, true))
- return state.Invalid(state.GetReason(), false, state.GetRejectCode(), state.GetRejectReason(),
+ if (!CheckTransaction(*tx, state))
+ return state.Invalid(state.GetReason(), false, state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
unsigned int nSigOps = 0;
@@ -3317,7 +3313,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
nSigOps += GetLegacySigOpCount(*tx);
}
if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST)
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-sigops", "out-of-bounds SigOpCount");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-sigops", "out-of-bounds SigOpCount");
if (fCheckPOW && fCheckMerkleRoot)
block.fChecked = true;
@@ -3418,7 +3414,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
// Check proof of work
const Consensus::Params& consensusParams = params.GetConsensus();
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "bad-diffbits", "incorrect proof of work");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "bad-diffbits", "incorrect proof of work");
// Check against checkpoints
if (fCheckpointsEnabled) {
@@ -3427,23 +3423,23 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
// g_blockman.m_block_index.
CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
- return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
+ return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), "bad-fork-prior-to-checkpoint");
}
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, "time-too-old", "block's timestamp is too early");
// Check timestamp
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
- return state.Invalid(ValidationInvalidReason::BLOCK_TIME_FUTURE, false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");
+ return state.Invalid(ValidationInvalidReason::BLOCK_TIME_FUTURE, false, "time-too-new", "block timestamp too far in the future");
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
// check for version 2, 3 and 4 upgrades
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
(block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
(block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));
return true;
@@ -3473,7 +3469,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// Check that all transactions are finalized
for (const auto& tx : block.vtx) {
if (!IsFinalTx(*tx, nHeight, nLockTimeCutoff)) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-nonfinal", "non-final transaction");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-nonfinal", "non-final transaction");
}
}
@@ -3483,7 +3479,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
CScript expect = CScript() << nHeight;
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), block.vtx[0]->vin[0].scriptSig.begin())) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-height", "block height mismatch in coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-height", "block height mismatch in coinbase");
}
}
@@ -3505,11 +3501,11 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
- return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
- return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
}
fHaveWitness = true;
}
@@ -3519,7 +3515,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
if (!fHaveWitness) {
for (const auto& tx : block.vtx) {
if (tx->HasWitness()) {
- return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
}
}
}
@@ -3531,7 +3527,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// the block hash, so we couldn't mark the block as permanently
// failed).
if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) {
- return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-weight", strprintf("%s : weight limit failed", __func__));
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-blk-weight", strprintf("%s : weight limit failed", __func__));
}
return true;
@@ -3551,7 +3547,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
if (ppindex)
*ppindex = pindex;
if (pindex->nStatus & BLOCK_FAILED_MASK)
- return state.Invalid(ValidationInvalidReason::CACHED_INVALID, error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate");
+ return state.Invalid(ValidationInvalidReason::CACHED_INVALID, error("%s: block %s is marked invalid", __func__, hash.ToString()), "duplicate");
return true;
}
@@ -3562,10 +3558,10 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
CBlockIndex* pindexPrev = nullptr;
BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock);
if (mi == m_block_index.end())
- return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), "prev-blk-not-found");
pindexPrev = (*mi).second;
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), "bad-prevblk");
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
@@ -3602,7 +3598,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
setDirtyBlockIndex.insert(invalid_walk);
invalid_walk = invalid_walk->pprev;
}
- return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), "bad-prevblk");
}
}
}
diff --git a/src/validation.h b/src/validation.h
index fbbe3757e0..d17a320a47 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -24,12 +24,10 @@
#include <algorithm>
#include <atomic>
-#include <exception>
#include <map>
#include <memory>
#include <set>
#include <stdint.h>
-#include <string>
#include <utility>
#include <vector>
@@ -779,14 +777,6 @@ extern VersionBitsCache versionbitscache;
*/
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params);
-/** Reject codes greater or equal to this can be returned by AcceptToMemPool
- * for transactions, to signal internal conditions. They cannot and should not
- * be sent over the P2P network.
- */
-static const unsigned int REJECT_INTERNAL = 0x100;
-/** Too high fee. Can not be triggered by P2P transactions */
-static const unsigned int REJECT_HIGHFEE = 0x100;
-
/** Get block file info entry for one block file */
CBlockFileInfo* GetBlockFileInfo(size_t n);
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 59a620ab95..cf4a529a6d 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -9,8 +9,6 @@
#include <scheduler.h>
#include <txmempool.h>
-#include <list>
-#include <atomic>
#include <future>
#include <utility>
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index 0b76c1a0eb..f6179aa298 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -6,11 +6,8 @@
#include <crypto/aes.h>
#include <crypto/sha512.h>
-#include <script/script.h>
-#include <script/standard.h>
#include <util/system.h>
-#include <string>
#include <vector>
int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index 17a4e9820c..4367a5047f 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -9,7 +9,6 @@
#include <support/allocators/secure.h>
#include <script/signingprovider.h>
-#include <atomic>
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 26aeb754ad..e48eee6c2c 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -412,7 +412,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er
return true;
}
-bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
+bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
{
std::string walletFile;
std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile);
@@ -424,11 +424,11 @@ bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& w
BerkeleyEnvironment::VerifyResult r = env->Verify(walletFile, recoverFunc, backup_filename);
if (r == BerkeleyEnvironment::VerifyResult::RECOVER_OK)
{
- warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!"
+ warnings.push_back(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
" Original %s saved as %s in %s; if"
" your balance or transactions are incorrect you should"
" restore from a backup.").translated,
- walletFile, backup_filename, walletDir);
+ walletFile, backup_filename, walletDir));
}
if (r == BerkeleyEnvironment::VerifyResult::RECOVER_FAIL)
{
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 94f41eaf16..abec3ae4e2 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -10,9 +10,7 @@
#include <fs.h>
#include <serialize.h>
#include <streams.h>
-#include <sync.h>
#include <util/system.h>
-#include <version.h>
#include <atomic>
#include <map>
@@ -246,7 +244,7 @@ public:
/* verifies the database environment */
static bool VerifyEnvironment(const fs::path& file_path, std::string& errorStr);
/* verifies the database file */
- static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
+ static bool VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
template <typename K, typename T>
bool Read(const K& key, T& value)
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index b87231293f..0a4bb3f396 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.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 <consensus/validation.h>
#include <interfaces/chain.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
@@ -17,15 +16,15 @@
//! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
-static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
+static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
- if (wallet->HasWalletSpend(wtx.GetHash())) {
+ if (wallet.HasWalletSpend(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the wallet");
return feebumper::Result::INVALID_PARAMETER;
}
{
- if (wallet->chain().hasDescendantsInMempool(wtx.GetHash())) {
+ if (wallet.chain().hasDescendantsInMempool(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the mempool");
return feebumper::Result::INVALID_PARAMETER;
}
@@ -48,7 +47,7 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai
// check that original tx consists entirely of our inputs
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
- if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) {
+ if (!wallet.IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) {
errors.push_back("Transaction contains inputs that don't belong to this wallet");
return feebumper::Result::WALLET_ERROR;
}
@@ -58,13 +57,13 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai
}
//! Check if the user provided a valid feeRate
-static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) {
+static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) {
// check that fee rate is higher than mempool's minimum fee
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
// This may occur if the user set FeeRate, TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
// moment earlier. In this case, we report an error to the user, who may adjust the fee.
- CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
+ CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee();
if (newFeerate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
errors.push_back(strprintf(
@@ -76,7 +75,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt
CAmount new_total_fee = newFeerate.GetFee(maxTxSize);
- CFeeRate incrementalRelayFee = std::max(wallet->chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE));
+ CFeeRate incrementalRelayFee = std::max(wallet.chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE));
// Given old total fee and transaction size, calculate the old feeRate
CAmount old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
@@ -91,7 +90,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt
return feebumper::Result::INVALID_PARAMETER;
}
- CAmount requiredFee = GetRequiredFee(*wallet, maxTxSize);
+ CAmount requiredFee = GetRequiredFee(wallet, maxTxSize);
if (new_total_fee < requiredFee) {
errors.push_back(strprintf("Insufficient total fee (cannot be less than required fee %s)",
FormatMoney(requiredFee)));
@@ -99,7 +98,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt
}
// Check that in all cases the new fee doesn't violate maxTxFee
- const CAmount max_tx_fee = wallet->m_default_max_tx_fee;
+ const CAmount max_tx_fee = wallet.m_default_max_tx_fee;
if (new_total_fee > max_tx_fee) {
errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
FormatMoney(new_total_fee), FormatMoney(max_tx_fee)));
@@ -109,7 +108,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt
return feebumper::Result::OK;
}
-static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee)
+static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee)
{
// Get the fee rate of the original transaction. This is calculated from
// the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
@@ -123,15 +122,15 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont
// the minimum of that and the wallet's conservative
// WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
// network wide policy for incremental relay fee that our node may not be
- // aware of. This ensures we're over the over the required relay fee rate
+ // aware of. This ensures we're over the required relay fee rate
// (BIP 125 rule 4). The replacement tx will be at least as large as the
// original tx, so the total fee will be greater (BIP 125 rule 3)
- CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee();
+ CFeeRate node_incremental_relay_fee = wallet.chain().relayIncrementalFee();
CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
// Fee rate must also be at least the wallet's GetMinimumFeeRate
- CFeeRate min_feerate(GetMinimumFeeRate(*wallet, coin_control, /* feeCalc */ nullptr));
+ CFeeRate min_feerate(GetMinimumFeeRate(wallet, coin_control, /* feeCalc */ nullptr));
// Set the required fee rate for the replacement transaction in coin control.
return std::max(feerate, min_feerate);
@@ -139,11 +138,11 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont
namespace feebumper {
-bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
+bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
{
- auto locked_chain = wallet->chain().lock();
- LOCK(wallet->cs_wallet);
- const CWalletTx* wtx = wallet->GetWalletTx(txid);
+ auto locked_chain = wallet.chain().lock();
+ LOCK(wallet.cs_wallet);
+ const CWalletTx* wtx = wallet.GetWalletTx(txid);
if (wtx == nullptr) return false;
std::vector<std::string> errors_dummy;
@@ -166,7 +165,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co
}
const CWalletTx& wtx = it->second;
- Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors);
+ Result result = PreconditionChecks(*locked_chain, *wallet, wtx, errors);
if (result != Result::OK) {
return result;
}
@@ -276,17 +275,17 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co
}
-Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors,
+Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors,
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
{
// We are going to modify coin control later, copy to re-use
CCoinControl new_coin_control(coin_control);
- auto locked_chain = wallet->chain().lock();
- LOCK(wallet->cs_wallet);
+ auto locked_chain = wallet.chain().lock();
+ LOCK(wallet.cs_wallet);
errors.clear();
- auto it = wallet->mapWallet.find(txid);
- if (it == wallet->mapWallet.end()) {
+ auto it = wallet.mapWallet.find(txid);
+ if (it == wallet.mapWallet.end()) {
errors.push_back("Invalid or non-wallet transaction id");
return Result::INVALID_ADDRESS_OR_KEY;
}
@@ -300,7 +299,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
// Fill in recipients(and preserve a single change key if there is one)
std::vector<CRecipient> recipients;
for (const auto& output : wtx.tx->vout) {
- if (!wallet->IsChange(output)) {
+ if (!wallet.IsChange(output)) {
CRecipient recipient = {output.scriptPubKey, output.nValue, false};
recipients.push_back(recipient);
} else {
@@ -313,8 +312,8 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
if (coin_control.m_feerate) {
// The user provided a feeRate argument.
// We calculate this here to avoid compiler warning on the cs_wallet lock
- const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet);
- Result res = CheckFeeRate(wallet, wtx, *(new_coin_control.m_feerate), maxTxSize, errors);
+ const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, &wallet);
+ Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, errors);
if (res != Result::OK) {
return res;
}
@@ -342,7 +341,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
CAmount fee_ret;
int change_pos_in_out = -1; // No requested location for change
std::string fail_reason;
- if (!wallet->CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
+ if (!wallet.CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
errors.push_back("Unable to create transaction: " + fail_reason);
return Result::WALLET_ERROR;
}
@@ -353,7 +352,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
// Write back transaction
mtx = CMutableTransaction(*tx_new);
// Mark new tx not replaceable, if requested.
- if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
+ if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf)) {
for (auto& input : mtx.vin) {
if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
}
@@ -362,21 +361,21 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo
return Result::OK;
}
-bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) {
- auto locked_chain = wallet->chain().lock();
- LOCK(wallet->cs_wallet);
- return wallet->SignTransaction(mtx);
+bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
+ auto locked_chain = wallet.chain().lock();
+ LOCK(wallet.cs_wallet);
+ return wallet.SignTransaction(mtx);
}
-Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
+Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
{
- auto locked_chain = wallet->chain().lock();
- LOCK(wallet->cs_wallet);
+ auto locked_chain = wallet.chain().lock();
+ LOCK(wallet.cs_wallet);
if (!errors.empty()) {
return Result::MISC_ERROR;
}
- auto it = txid.IsNull() ? wallet->mapWallet.end() : wallet->mapWallet.find(txid);
- if (it == wallet->mapWallet.end()) {
+ auto it = txid.IsNull() ? wallet.mapWallet.end() : wallet.mapWallet.find(txid);
+ if (it == wallet.mapWallet.end()) {
errors.push_back("Invalid or non-wallet transaction id");
return Result::MISC_ERROR;
}
@@ -393,22 +392,11 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
mapValue_t mapValue = oldWtx.mapValue;
mapValue["replaces_txid"] = oldWtx.GetHash().ToString();
- CValidationState state;
- if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, state)) {
- // NOTE: CommitTransaction never returns false, so this should never happen.
- errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state)));
- return Result::WALLET_ERROR;
- }
-
- bumped_txid = tx->GetHash();
- if (state.IsInvalid()) {
- // This can happen if the mempool rejected the transaction. Report
- // what happened in the "errors" response.
- errors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state)));
- }
+ wallet.CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm);
// mark the original tx as bumped
- if (!wallet->MarkReplaced(oldWtx.GetHash(), bumped_txid)) {
+ bumped_txid = tx->GetHash();
+ if (!wallet.MarkReplaced(oldWtx.GetHash(), bumped_txid)) {
// TODO: see if JSON-RPC has a standard way of returning a response
// along with an exception. It would be good to return information about
// wtxBumped to the caller even if marking the original transaction
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 0c4e1cb7dd..9357397606 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -26,7 +26,7 @@ enum class Result
};
//! Return whether transaction can be bumped.
-bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid);
+bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid);
//! Create bumpfee transaction based on total amount.
Result CreateTotalBumpTransaction(const CWallet* wallet,
@@ -39,7 +39,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet,
CMutableTransaction& mtx);
//! Create bumpfee transaction based on feerate estimates.
-Result CreateRateBumpTransaction(CWallet* wallet,
+Result CreateRateBumpTransaction(CWallet& wallet,
const uint256& txid,
const CCoinControl& coin_control,
std::vector<std::string>& errors,
@@ -50,13 +50,13 @@ Result CreateRateBumpTransaction(CWallet* wallet,
//! Sign the new transaction,
//! @return false if the tx couldn't be found or if it was
//! impossible to create the signature(s)
-bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx);
+bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx);
//! Commit the bumpfee transaction.
//! @return success in case of CWallet::CommitTransaction was successful,
//! but sets errors if the tx could not be added to the mempool (will try later)
//! or if the old transaction could not be marked as replaced.
-Result CommitTransaction(CWallet* wallet,
+Result CommitTransaction(CWallet& wallet,
const uint256& txid,
CMutableTransaction&& mtx,
std::vector<std::string>& errors,
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 2792058f2a..249bc833c6 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -5,7 +5,6 @@
#include <wallet/fees.h>
-#include <util/system.h>
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 43b6ead028..3657a157b6 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -11,7 +11,6 @@
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallet.h>
-#include <wallet/walletutil.h>
#include <walletinitinterface.h>
class WalletInit : public WalletInitInterface {
@@ -122,8 +121,6 @@ bool WalletInit::ParameterInteraction() const
if (gArgs.GetBoolArg("-sysperms", false))
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
- if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
- return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.").translated);
return true;
}
diff --git a/src/wallet/ismine.cpp b/src/wallet/ismine.cpp
index b7ef2d4490..029b922785 100644
--- a/src/wallet/ismine.cpp
+++ b/src/wallet/ismine.cpp
@@ -7,7 +7,6 @@
#include <key.h>
#include <script/script.h>
-#include <script/sign.h>
#include <script/signingprovider.h>
#include <wallet/wallet.h>
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index b5d3b8c305..071befaebf 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -7,6 +7,7 @@
#include <interfaces/chain.h>
#include <scheduler.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallet.h>
@@ -53,10 +54,10 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
}
std::string error_string;
- std::string warning_string;
- bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string);
+ std::vector<std::string> warnings;
+ bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warnings);
if (!error_string.empty()) chain.initError(error_string);
- if (!warning_string.empty()) chain.initWarning(warning_string);
+ if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
if (!verify_success) return false;
}
@@ -66,8 +67,12 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
for (const std::string& walletFile : wallet_files) {
- std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
+ std::string error;
+ std::vector<std::string> warnings;
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings);
+ if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
if (!pwallet) {
+ chain.initError(error);
return false;
}
AddWallet(pwallet);
diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h
index a24a0967d2..a7e52df6d9 100644
--- a/src/wallet/psbtwallet.h
+++ b/src/wallet/psbtwallet.h
@@ -5,9 +5,7 @@
#ifndef BITCOIN_WALLET_PSBTWALLET_H
#define BITCOIN_WALLET_PSBTWALLET_H
-#include <node/transaction.h>
#include <psbt.h>
-#include <primitives/transaction.h>
#include <wallet/wallet.h>
/**
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index f52e4318c8..1cd4cb93b4 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -7,7 +7,6 @@
#include <interfaces/chain.h>
#include <key_io.h>
#include <merkleblock.h>
-#include <rpc/server.h>
#include <rpc/util.h>
#include <script/descriptor.h>
#include <script/script.h>
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index dc437e5cd8..e571501221 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -4,12 +4,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <amount.h>
-#include <consensus/validation.h>
#include <core_io.h>
#include <init.h>
#include <interfaces/chain.h>
#include <key_io.h>
-#include <node/transaction.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
@@ -22,6 +20,7 @@
#include <util/bip32.h>
#include <util/fees.h>
#include <util/moneystr.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/url.h>
#include <util/validation.h>
@@ -37,7 +36,6 @@
#include <univalue.h>
-#include <functional>
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
@@ -342,11 +340,7 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
- CValidationState state;
- if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) {
- strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state));
- throw JSONRPCError(RPC_WALLET_ERROR, strError);
- }
+ pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
return tx;
}
@@ -927,12 +921,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
- CValidationState state;
- if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) {
- strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state));
- throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
- }
-
+ pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
return tx->GetHash().GetHex();
}
@@ -2583,13 +2572,14 @@ static UniValue loadwallet(const JSONRPCRequest& request)
}
}
- std::string error, warning;
+ std::string error;
+ std::vector<std::string> warning;
std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning);
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
- obj.pushKV("warning", warning);
+ obj.pushKV("warning", Join(warning, "\n"));
return obj;
}
@@ -2695,12 +2685,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
}
SecureString passphrase;
passphrase.reserve(100);
- std::string warning;
+ std::vector<std::string> warnings;
if (!request.params[3].isNull()) {
passphrase = request.params[3].get_str().c_str();
if (passphrase.empty()) {
// Empty string means unencrypted
- warning = "Empty string given as passphrase, wallet will not be encrypted.";
+ warnings.emplace_back("Empty string given as passphrase, wallet will not be encrypted.");
}
}
@@ -2709,9 +2699,8 @@ static UniValue createwallet(const JSONRPCRequest& request)
}
std::string error;
- std::string create_warning;
std::shared_ptr<CWallet> wallet;
- WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, create_warning, wallet);
+ WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
switch (status) {
case WalletCreationStatus::CREATION_FAILED:
throw JSONRPCError(RPC_WALLET_ERROR, error);
@@ -2722,15 +2711,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
// no default case, so the compiler can warn about missing cases
}
- if (warning.empty()) {
- warning = create_warning;
- } else if (!warning.empty() && !create_warning.empty()){
- warning += "; " + create_warning;
- }
-
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
- obj.pushKV("warning", warning);
+ obj.pushKV("warning", Join(warnings, "\n"));
return obj;
}
@@ -3417,7 +3400,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
} else {
// Targeting feerate bump.
- res = feebumper::CreateRateBumpTransaction(pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
+ res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
}
if (res != feebumper::Result::OK) {
switch(res) {
@@ -3440,12 +3423,12 @@ static UniValue bumpfee(const JSONRPCRequest& request)
}
// sign bumped transaction
- if (!feebumper::SignTransaction(pwallet, mtx)) {
+ if (!feebumper::SignTransaction(*pwallet, mtx)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
}
// commit the bumped transaction
uint256 txid;
- if (feebumper::CommitTransaction(pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
+ if (feebumper::CommitTransaction(*pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
throw JSONRPCError(RPC_WALLET_ERROR, errors[0]);
}
UniValue result(UniValue::VOBJ);
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 73523ca36d..a2b2a7b227 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <vector>
-#include <consensus/validation.h>
#include <interfaces/chain.h>
#include <policy/policy.h>
#include <rpc/server.h>
@@ -451,8 +450,7 @@ public:
auto locked_chain = m_chain->lock();
BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, fee, changePos, error, dummy));
}
- CValidationState state;
- BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, state));
+ wallet->CommitTransaction(tx, {}, {});
CMutableTransaction blocktx;
{
LOCK(wallet->cs_wallet);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 09f08220db..159d4f78c6 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -27,13 +27,11 @@
#include <util/rbf.h>
#include <util/translation.h>
#include <util/validation.h>
-#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
#include <algorithm>
#include <assert.h>
-#include <future>
#include <boost/algorithm/string/replace.hpp>
@@ -140,16 +138,16 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
}
}
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning)
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
{
- if (!CWallet::Verify(chain, location, false, error, warning)) {
+ if (!CWallet::Verify(chain, location, false, error, warnings)) {
error = "Wallet file verification failed: " + error;
return nullptr;
}
- std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location);
+ std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings);
if (!wallet) {
- error = "Wallet loading failed.";
+ error = "Wallet loading failed: " + error;
return nullptr;
}
AddWallet(wallet);
@@ -157,12 +155,12 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocati
return wallet;
}
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
{
- return LoadWallet(chain, WalletLocation(name), error, warning);
+ return LoadWallet(chain, WalletLocation(name), error, warnings);
}
-WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result)
+WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result)
{
// Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
@@ -180,9 +178,8 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
}
// Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
- std::string wallet_error;
- if (!CWallet::Verify(chain, location, false, wallet_error, warning)) {
- error = "Wallet file verification failed: " + wallet_error;
+ if (!CWallet::Verify(chain, location, false, error, warnings)) {
+ error = "Wallet file verification failed: " + error;
return WalletCreationStatus::CREATION_FAILED;
}
@@ -193,9 +190,9 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
}
// Make the wallet
- std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, wallet_creation_flags);
+ std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings, wallet_creation_flags);
if (!wallet) {
- error = "Wallet creation failed";
+ error = "Wallet creation failed: " + error;
return WalletCreationStatus::CREATION_FAILED;
}
@@ -2739,8 +2736,11 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
}
std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);
- size_t max_ancestors = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT));
- size_t max_descendants = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT));
+ unsigned int limit_ancestor_count;
+ unsigned int limit_descendant_count;
+ chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
+ size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
+ size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
bool res = nTargetValue <= nValueFromPresetInputs ||
@@ -3284,51 +3284,44 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
return true;
}
-/**
- * Call after CreateTransaction unless you want to abort
- */
-bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state)
+void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
{
- {
- auto locked_chain = chain().lock();
- LOCK(cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
- CWalletTx wtxNew(this, std::move(tx));
- wtxNew.mapValue = std::move(mapValue);
- wtxNew.vOrderForm = std::move(orderForm);
- wtxNew.fTimeReceivedIsTxTime = true;
- wtxNew.fFromMe = true;
+ CWalletTx wtxNew(this, std::move(tx));
+ wtxNew.mapValue = std::move(mapValue);
+ wtxNew.vOrderForm = std::move(orderForm);
+ wtxNew.fTimeReceivedIsTxTime = true;
+ wtxNew.fFromMe = true;
- WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
- {
+ WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
- // Add tx to wallet, because if it has change it's also ours,
- // otherwise just for transaction history.
- AddToWallet(wtxNew);
+ // Add tx to wallet, because if it has change it's also ours,
+ // otherwise just for transaction history.
+ AddToWallet(wtxNew);
- // Notify that old coins are spent
- for (const CTxIn& txin : wtxNew.tx->vin)
- {
- CWalletTx &coin = mapWallet.at(txin.prevout.hash);
- coin.BindWallet(this);
- NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
- }
- }
+ // Notify that old coins are spent
+ for (const CTxIn& txin : wtxNew.tx->vin) {
+ CWalletTx &coin = mapWallet.at(txin.prevout.hash);
+ coin.BindWallet(this);
+ NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
+ }
- // Get the inserted-CWalletTx from mapWallet so that the
- // fInMempool flag is cached properly
- CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
+ // Get the inserted-CWalletTx from mapWallet so that the
+ // fInMempool flag is cached properly
+ CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
- if (fBroadcastTransactions)
- {
- std::string err_string;
- if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) {
- WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
- // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
- }
- }
+ if (!fBroadcastTransactions) {
+ // Don't submit tx to the mempool
+ return;
+ }
+
+ std::string err_string;
+ if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) {
+ WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
+ // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
}
- return true;
}
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
@@ -3467,21 +3460,6 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
return WalletBatch(*database).EraseName(EncodeDestination(address));
}
-const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const
-{
- CTxDestination address;
- if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) {
- auto mi = mapAddressBook.find(address);
- if (mi != mapAddressBook.end()) {
- return mi->second.name;
- }
- }
- // A scriptPubKey that doesn't have an entry in the address book is
- // associated with the default label ("").
- const static std::string DEFAULT_LABEL_NAME;
- return DEFAULT_LABEL_NAME;
-}
-
/**
* Mark old keypool keys as used,
* and generate all new keys
@@ -4196,7 +4174,7 @@ void CWallet::MarkPreSplitKeys()
}
}
-bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string)
+bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings)
{
// Do some checking on wallet path. It should be either a:
//
@@ -4250,10 +4228,10 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b
}
}
- return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
+ return WalletBatch::VerifyDatabaseFile(wallet_path, warnings, error_string);
}
-std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags)
+std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags)
{
const std::string walletFile = WalletDataFilePath(location.GetPath()).string();
@@ -4266,7 +4244,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath()));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DBErrors::LOAD_OK) {
- chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile));
+ error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile);
return nullptr;
}
}
@@ -4279,29 +4257,28 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// should be possible to use std::allocate_shared.
std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
- if (nLoadWalletRet != DBErrors::LOAD_OK)
- {
+ if (nLoadWalletRet != DBErrors::LOAD_OK) {
if (nLoadWalletRet == DBErrors::CORRUPT) {
- chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile));
+ error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile);
return nullptr;
}
else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
{
- chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
+ warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect.").translated,
walletFile));
}
else if (nLoadWalletRet == DBErrors::TOO_NEW) {
- chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME));
+ error = strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME);
return nullptr;
}
else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
- chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME));
+ error = strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME);
return nullptr;
}
else {
- chain.initError(strprintf(_("Error loading %s").translated, walletFile));
+ error = strprintf(_("Error loading %s").translated, walletFile);
return nullptr;
}
}
@@ -4320,7 +4297,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
- chain.initError(_("Cannot downgrade wallet").translated);
+ error = _("Cannot downgrade wallet").translated;
return nullptr;
}
walletInstance->SetMaxVersion(nMaxVersion);
@@ -4333,7 +4310,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
int max_version = walletInstance->GetVersion();
if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
- chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated);
+ error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated;
return nullptr;
}
@@ -4361,7 +4338,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Regenerate the keypool if upgraded to HD
if (hd_upgrade) {
if (!walletInstance->TopUpKeyPool()) {
- chain.initError(_("Unable to generate keys").translated);
+ error = _("Unable to generate keys").translated;
return nullptr;
}
}
@@ -4381,7 +4358,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Top up the keypool
if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) {
- chain.initError(_("Unable to generate initial keys").translated);
+ error = _("Unable to generate initial keys").translated;
return nullptr;
}
@@ -4389,33 +4366,33 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
- chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile));
+ error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile);
return NULL;
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
LOCK(walletInstance->cs_KeyStore);
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
- chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile));
+ warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile));
}
}
if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
- chain.initError(strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", "")));
+ error = strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", ""));
return nullptr;
}
if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) {
- chain.initError(strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", "")));
+ error = strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", ""));
return nullptr;
}
if (gArgs.IsArgSet("-mintxfee")) {
CAmount n = 0;
if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
- chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated);
+ error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated;
return nullptr;
}
if (n > HIGH_TX_FEE_PER_KB) {
- chain.initWarning(AmountHighWarn("-mintxfee").translated + " " +
+ warnings.push_back(AmountHighWarn("-mintxfee").translated + " " +
_("This is the minimum transaction fee you pay on every transaction.").translated);
}
walletInstance->m_min_fee = CFeeRate(n);
@@ -4424,11 +4401,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-fallbackfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
- chain.initError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", "")));
+ error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", ""));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- chain.initWarning(AmountHighWarn("-fallbackfee").translated + " " +
+ warnings.push_back(AmountHighWarn("-fallbackfee").translated + " " +
_("This is the transaction fee you may pay when fee estimates are not available.").translated);
}
walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
@@ -4439,11 +4416,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-discardfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
- chain.initError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", "")));
+ error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", ""));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- chain.initWarning(AmountHighWarn("-discardfee").translated + " " +
+ warnings.push_back(AmountHighWarn("-discardfee").translated + " " +
_("This is the transaction fee you may discard if change is smaller than dust at this level").translated);
}
walletInstance->m_discard_rate = CFeeRate(nFeePerK);
@@ -4451,41 +4428,40 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-paytxfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
- chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated);
+ error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated;
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- chain.initWarning(AmountHighWarn("-paytxfee").translated + " " +
+ warnings.push_back(AmountHighWarn("-paytxfee").translated + " " +
_("This is the transaction fee you will pay if you send a transaction.").translated);
}
walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) {
- chain.initError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated,
- gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()));
+ error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated,
+ gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString());
return nullptr;
}
}
- if (gArgs.IsArgSet("-maxtxfee"))
- {
+ if (gArgs.IsArgSet("-maxtxfee")) {
CAmount nMaxFee = 0;
if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
- chain.initError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated);
+ error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated;
return nullptr;
}
if (nMaxFee > HIGH_MAX_TX_FEE) {
- chain.initWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated);
+ warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated);
}
if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) {
- chain.initError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated,
- gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()));
+ error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated,
+ gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString());
return nullptr;
}
walletInstance->m_default_max_tx_fee = nMaxFee;
}
if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
- chain.initWarning(AmountHighWarn("-minrelaytxfee").translated + " " +
+ warnings.push_back(AmountHighWarn("-minrelaytxfee").translated + " " +
_("The wallet will avoid paying less than the minimum relay fee.").translated);
}
@@ -4535,7 +4511,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
if (rescan_height != block_height) {
- chain.initError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated);
+ error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated;
return nullptr;
}
}
@@ -4554,7 +4530,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
{
WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
- chain.initError(_("Failed to rescan the wallet during initialization").translated);
+ error = _("Failed to rescan the wallet during initialization").translated;
return nullptr;
}
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 006775e83b..85c277ff50 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -11,7 +11,6 @@
#include <interfaces/handler.h>
#include <outputtype.h>
#include <policy/feerate.h>
-#include <script/sign.h>
#include <tinyformat.h>
#include <ui_interface.h>
#include <util/strencodings.h>
@@ -48,7 +47,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name);
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning);
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings);
enum class WalletCreationStatus {
SUCCESS,
@@ -56,7 +55,7 @@ enum class WalletCreationStatus {
ENCRYPTION_FAILED
};
-WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result);
+WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result);
//! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
@@ -1147,7 +1146,16 @@ public:
*/
bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
- bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state);
+ /**
+ * Submit the transaction to the node's mempool and then relay to peers.
+ * Should be called after CreateTransaction unless you want to abort
+ * broadcasting the transaction.
+ *
+ * @param tx[in] The transaction to be broadcast.
+ * @param mapValue[in] key-values to be set on the transaction.
+ * @param orderForm[in] BIP 70 / BIP 21 order form details to be set on the transaction.
+ */
+ void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm);
bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
{
@@ -1246,8 +1254,6 @@ public:
bool DelAddressBook(const CTxDestination& address);
- const std::string& GetLabelName(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
-
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
{
AssertLockHeld(cs_wallet);
@@ -1321,10 +1327,10 @@ public:
bool MarkReplaced(const uint256& originalHash, const uint256& newHash);
//! Verify wallet naming and perform salvage on the wallet if required
- static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string);
+ static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
- static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0);
+ static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags = 0);
/**
* Wallet post-init setup
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 635997afc9..a9e6763c6d 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -5,8 +5,6 @@
#include <wallet/walletdb.h>
-#include <consensus/tx_check.h>
-#include <consensus/validation.h>
#include <fs.h>
#include <key_io.h>
#include <protocol.h>
@@ -218,8 +216,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> hash;
CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
ssValue >> wtx;
- CValidationState state;
- if (!(CheckTransaction(*wtx.tx, state) && (wtx.GetHash() == hash) && state.IsValid()))
+ if (wtx.GetHash() != hash)
return false;
// Undo serialize changes in 31600
@@ -729,9 +726,9 @@ bool WalletBatch::VerifyEnvironment(const fs::path& wallet_path, std::string& er
return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr);
}
-bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr)
+bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr)
{
- return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, WalletBatch::Recover);
+ return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warnings, errorStr, WalletBatch::Recover);
}
bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 0fee35934d..b1781d5ccf 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -7,15 +7,12 @@
#define BITCOIN_WALLET_WALLETDB_H
#include <amount.h>
-#include <primitives/transaction.h>
#include <script/sign.h>
#include <wallet/db.h>
#include <key.h>
-#include <list>
#include <stdint.h>
#include <string>
-#include <utility>
#include <vector>
/**
@@ -263,7 +260,7 @@ public:
/* verifies the database environment */
static bool VerifyEnvironment(const fs::path& wallet_path, std::string& errorStr);
/* verifies the database file */
- static bool VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr);
+ static bool VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr);
//! write the hdchain model (external chain child index counter)
bool WriteHDChain(const CHDChain& chain);
diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h
index 7ee2505631..bd08da42d6 100644
--- a/src/wallet/wallettool.h
+++ b/src/wallet/wallettool.h
@@ -5,7 +5,6 @@
#ifndef BITCOIN_WALLET_WALLETTOOL_H
#define BITCOIN_WALLET_WALLETTOOL_H
-#include <wallet/ismine.h>
#include <wallet/wallet.h>
namespace WalletTool {
diff --git a/src/warnings.h b/src/warnings.h
index 16c8f7b52e..e6701ebd9e 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -6,7 +6,6 @@
#ifndef BITCOIN_WARNINGS_H
#define BITCOIN_WARNINGS_H
-#include <stdlib.h>
#include <string>
void SetMiscWarning(const std::string& strWarning);
diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h
index 5219ffad40..e3fdbf7402 100644
--- a/src/zmq/zmqconfig.h
+++ b/src/zmq/zmqconfig.h
@@ -10,13 +10,11 @@
#endif
#include <stdarg.h>
-#include <string>
#if ENABLE_ZMQ
#include <zmq.h>
#endif
-#include <primitives/block.h>
#include <primitives/transaction.h>
void zmqError(const char *str);
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index de59b71b8f..ebbaf8683d 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -5,7 +5,6 @@
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqpublishnotifier.h>
-#include <version.h>
#include <validation.h>
#include <util/system.h>
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index a0cc26a162..6be0554a65 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -6,8 +6,6 @@
#define BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H
#include <validationinterface.h>
-#include <string>
-#include <map>
#include <list>
class CBlockIndex;