aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am22
-rw-r--r--src/Makefile.qt.include24
-rw-r--r--src/Makefile.qttest.include14
-rw-r--r--src/addrdb.cpp2
-rw-r--r--src/addrman.h2
-rw-r--r--src/arith_uint256.cpp2
-rw-r--r--src/base58.cpp7
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/bench/bench_bitcoin.cpp4
-rw-r--r--src/bench/block_assemble.cpp2
-rw-r--r--src/bench/checkqueue.cpp2
-rw-r--r--src/bench/coin_selection.cpp4
-rw-r--r--src/bench/crypto_hash.cpp2
-rw-r--r--src/bench/examples.cpp2
-rw-r--r--src/bitcoin-cli.cpp4
-rw-r--r--src/bitcoin-tx.cpp8
-rw-r--r--src/bitcoind.cpp4
-rw-r--r--src/blockencodings.cpp2
-rw-r--r--src/chainparams.cpp4
-rw-r--r--src/chainparamsbase.cpp4
-rw-r--r--src/consensus/merkle.cpp2
-rw-r--r--src/consensus/tx_verify.cpp2
-rw-r--r--src/core_read.cpp4
-rw-r--r--src/core_write.cpp6
-rw-r--r--src/dbwrapper.h4
-rw-r--r--src/dummywallet.cpp2
-rw-r--r--src/fs.cpp3
-rw-r--r--src/httprpc.cpp4
-rw-r--r--src/httpserver.cpp26
-rw-r--r--src/index/base.cpp4
-rw-r--r--src/index/txindex.cpp2
-rw-r--r--src/init.cpp4
-rw-r--r--src/init.h2
-rw-r--r--src/interfaces/handler.cpp2
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/interfaces/wallet.cpp10
-rw-r--r--src/interfaces/wallet.h6
-rw-r--r--src/key_io.cpp2
-rw-r--r--src/keystore.cpp2
-rw-r--r--src/logging.cpp2
-rw-r--r--src/merkleblock.cpp2
-rw-r--r--src/miner.cpp4
-rw-r--r--src/net.cpp2
-rw-r--r--src/net_processing.cpp6
-rw-r--r--src/netaddress.cpp2
-rw-r--r--src/netbase.cpp4
-rw-r--r--src/noui.cpp2
-rw-r--r--src/policy/fees.cpp2
-rw-r--r--src/policy/policy.cpp4
-rw-r--r--src/primitives/block.cpp2
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/primitives/transaction.h2
-rw-r--r--src/protocol.cpp4
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp8
-rw-r--r--src/qt/bitcoingui.cpp2
-rw-r--r--src/qt/callback.h30
-rw-r--r--src/qt/clientmodel.cpp2
-rw-r--r--src/qt/coincontroldialog.cpp5
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/intro.cpp2
-rw-r--r--src/qt/paymentrequestplus.cpp2
-rw-r--r--src/qt/paymentserver.cpp301
-rw-r--r--src/qt/paymentserver.h44
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/sendcoinsentry.cpp10
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/qt/test/addressbooktests.cpp17
-rw-r--r--src/qt/test/compattests.cpp6
-rw-r--r--src/qt/test/paymentservertests.cpp4
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/test/test_main.cpp8
-rw-r--r--src/qt/test/util.cpp11
-rw-r--r--src/qt/test/wallettests.cpp20
-rw-r--r--src/qt/transactiondesc.cpp15
-rw-r--r--src/qt/transactiondesc.h2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/qt/transactionrecord.h2
-rw-r--r--src/qt/transactiontablemodel.cpp7
-rw-r--r--src/qt/utilitydialog.cpp4
-rw-r--r--src/qt/walletmodel.cpp15
-rw-r--r--src/qt/walletmodel.h16
-rw-r--r--src/qt/walletmodeltransaction.cpp6
-rw-r--r--src/qt/walletmodeltransaction.h1
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/random.cpp4
-rw-r--r--src/rest.cpp2
-rw-r--r--src/rpc/blockchain.cpp12
-rw-r--r--src/rpc/client.cpp4
-rw-r--r--src/rpc/mining.cpp6
-rw-r--r--src/rpc/misc.cpp6
-rw-r--r--src/rpc/net.cpp4
-rw-r--r--src/rpc/protocol.cpp6
-rw-r--r--src/rpc/rawtransaction.cpp2
-rw-r--r--src/rpc/server.cpp4
-rw-r--r--src/rpc/util.cpp2
-rw-r--r--src/script/descriptor.cpp126
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/sigcache.cpp2
-rw-r--r--src/script/sign.cpp6
-rw-r--r--src/script/sign.h34
-rw-r--r--src/script/standard.cpp4
-rw-r--r--src/sync.cpp2
-rw-r--r--src/test/allocator_tests.cpp2
-rw-r--r--src/test/amount_tests.cpp57
-rw-r--r--src/test/base32_tests.cpp2
-rw-r--r--src/test/base58_tests.cpp2
-rw-r--r--src/test/base64_tests.cpp2
-rw-r--r--src/test/bip32_tests.cpp4
-rw-r--r--src/test/blockfilter_tests.cpp2
-rw-r--r--src/test/bloom_tests.cpp4
-rw-r--r--src/test/checkqueue_tests.cpp4
-rw-r--r--src/test/coins_tests.cpp2
-rw-r--r--src/test/compress_tests.cpp2
-rw-r--r--src/test/crypto_tests.cpp2
-rw-r--r--src/test/denialofservice_tests.cpp2
-rw-r--r--src/test/descriptor_tests.cpp42
-rw-r--r--src/test/getarg_tests.cpp2
-rw-r--r--src/test/hash_tests.cpp2
-rw-r--r--src/test/key_io_tests.cpp2
-rw-r--r--src/test/key_properties.cpp4
-rw-r--r--src/test/key_tests.cpp4
-rw-r--r--src/test/mempool_tests.cpp2
-rw-r--r--src/test/miner_tests.cpp8
-rw-r--r--src/test/net_tests.cpp2
-rw-r--r--src/test/netbase_tests.cpp2
-rw-r--r--src/test/policyestimator_tests.cpp2
-rw-r--r--src/test/pow_tests.cpp2
-rw-r--r--src/test/script_tests.cpp4
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/skiplist_tests.cpp2
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/txindex_tests.cpp4
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/test/util_tests.cpp6
-rw-r--r--src/timedata.cpp4
-rw-r--r--src/torcontrol.cpp4
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txmempool.cpp8
-rw-r--r--src/ui_interface.cpp2
-rw-r--r--src/uint256.cpp4
-rw-r--r--src/util/memory.h (renamed from src/utilmemory.h)4
-rw-r--r--src/util/moneystr.cpp (renamed from src/utilmoneystr.cpp)10
-rw-r--r--src/util/moneystr.h (renamed from src/utilmoneystr.h)6
-rw-r--r--src/util/strencodings.cpp (renamed from src/utilstrencodings.cpp)7
-rw-r--r--src/util/strencodings.h (renamed from src/utilstrencodings.h)22
-rw-r--r--src/util/system.cpp (renamed from src/util.cpp)4
-rw-r--r--src/util/system.h (renamed from src/util.h)10
-rw-r--r--src/util/time.cpp (renamed from src/utiltime.cpp)2
-rw-r--r--src/util/time.h (renamed from src/utiltime.h)6
-rw-r--r--src/validation.cpp19
-rw-r--r--src/validation.h6
-rw-r--r--src/validationinterface.cpp2
-rw-r--r--src/wallet/coincontrol.cpp2
-rw-r--r--src/wallet/coinselection.cpp4
-rw-r--r--src/wallet/crypter.cpp2
-rw-r--r--src/wallet/db.cpp33
-rw-r--r--src/wallet/db.h9
-rw-r--r--src/wallet/feebumper.cpp4
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/init.cpp12
-rw-r--r--src/wallet/rpcdump.cpp273
-rw-r--r--src/wallet/rpcwallet.cpp191
-rw-r--r--src/wallet/test/coinselector_tests.cpp2
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp4
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp3
-rw-r--r--src/wallet/test/wallet_tests.cpp16
-rw-r--r--src/wallet/wallet.cpp39
-rw-r--r--src/wallet/wallet.h83
-rw-r--r--src/wallet/walletdb.cpp4
-rw-r--r--src/wallet/walletutil.cpp24
-rw-r--r--src/wallet/walletutil.h20
-rw-r--r--src/warnings.cpp2
-rw-r--r--src/zmq/zmqabstractnotifier.cpp2
-rw-r--r--src/zmq/zmqnotificationinterface.cpp2
-rw-r--r--src/zmq/zmqpublishnotifier.cpp2
178 files changed, 1135 insertions, 945 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7a2e9fa5e8..703304cebd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -183,10 +183,10 @@ BITCOIN_CORE_H = \
txmempool.h \
ui_interface.h \
undo.h \
- util.h \
- utilmemory.h \
- utilmoneystr.h \
- utiltime.h \
+ util/system.h \
+ util/memory.h \
+ util/moneystr.h \
+ util/time.h \
validation.h \
validationinterface.h \
versionbits.h \
@@ -377,8 +377,8 @@ libbitcoin_consensus_a_SOURCES = \
tinyformat.h \
uint256.cpp \
uint256.h \
- utilstrencodings.cpp \
- utilstrencodings.h \
+ util/strencodings.cpp \
+ util/strencodings.h \
version.h
# common: shared between bitcoind, and bitcoin-qt and non-server tools
@@ -427,10 +427,10 @@ libbitcoin_util_a_SOURCES = \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
- util.cpp \
- utilmoneystr.cpp \
- utilstrencodings.cpp \
- utiltime.cpp \
+ util/system.cpp \
+ util/moneystr.cpp \
+ util/strencodings.cpp \
+ util/time.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
@@ -587,9 +587,11 @@ if HARDEN
$(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(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
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index c7a1963135..3ca2a7451d 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -122,7 +122,6 @@ QT_MOC_CPP = \
qt/moc_bitcoinamountfield.cpp \
qt/moc_bitcoingui.cpp \
qt/moc_bitcoinunits.cpp \
- qt/moc_callback.cpp \
qt/moc_clientmodel.cpp \
qt/moc_coincontroldialog.cpp \
qt/moc_coincontroltreewidget.cpp \
@@ -168,7 +167,6 @@ BITCOIN_MM = \
QT_MOC = \
qt/bitcoin.moc \
qt/bitcoinamountfield.moc \
- qt/callback.moc \
qt/intro.moc \
qt/overviewpage.moc \
qt/rpcconsole.moc
@@ -178,9 +176,15 @@ 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 \
@@ -191,7 +195,6 @@ BITCOIN_QT_H = \
qt/bitcoinamountfield.h \
qt/bitcoingui.h \
qt/bitcoinunits.h \
- qt/callback.h \
qt/clientmodel.h \
qt/coincontroldialog.h \
qt/coincontroltreewidget.h \
@@ -330,7 +333,6 @@ BITCOIN_QT_WALLET_CPP = \
qt/editaddressdialog.cpp \
qt/openuridialog.cpp \
qt/overviewpage.cpp \
- qt/paymentrequestplus.cpp \
qt/paymentserver.cpp \
qt/receivecoinsdialog.cpp \
qt/receiverequestdialog.cpp \
@@ -349,13 +351,19 @@ 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)
-endif
+if ENABLE_BIP70
+BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP)
+endif # ENABLE_BIP70
+endif # ENABLE_WALLET
RES_IMAGES =
@@ -409,8 +417,12 @@ 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) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
+if ENABLE_BIP70
+qt_bitcoin_qt_LDADD += $(SSL_LIBS)
+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
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 4b14212b2e..db7873e8b7 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -13,9 +13,12 @@ TEST_QT_MOC_CPP = \
if ENABLE_WALLET
TEST_QT_MOC_CPP += \
qt/test/moc_addressbooktests.cpp \
- qt/test/moc_paymentservertests.cpp \
qt/test/moc_wallettests.cpp
-endif
+if ENABLE_BIP70
+TEST_QT_MOC_CPP += \
+ qt/test/moc_paymentservertests.cpp
+endif # ENABLE_BIP70
+endif # ENABLE_WALLET
TEST_QT_H = \
qt/test/addressbooktests.h \
@@ -48,10 +51,13 @@ qt_test_test_bitcoin_qt_SOURCES = \
if ENABLE_WALLET
qt_test_test_bitcoin_qt_SOURCES += \
qt/test/addressbooktests.cpp \
- qt/test/paymentservertests.cpp \
qt/test/wallettests.cpp \
wallet/test/wallet_test_fixture.cpp
-endif
+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)
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 3eae2b5127..1590bce074 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -12,7 +12,7 @@
#include <random.h>
#include <streams.h>
#include <tinyformat.h>
-#include <util.h>
+#include <util/system.h>
namespace {
diff --git a/src/addrman.h b/src/addrman.h
index 6d5780afa8..b97feb6f08 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -11,7 +11,7 @@
#include <random.h>
#include <sync.h>
#include <timedata.h>
-#include <util.h>
+#include <util/system.h>
#include <map>
#include <set>
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index 791dad7a60..aa66d13102 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -6,7 +6,7 @@
#include <arith_uint256.h>
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <crypto/common.h>
#include <stdio.h>
diff --git a/src/base58.cpp b/src/base58.cpp
index 7020c24055..e3d2853399 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -6,6 +6,7 @@
#include <hash.h>
#include <uint256.h>
+#include <util/strencodings.h>
#include <assert.h>
#include <string.h>
@@ -34,7 +35,7 @@ static const int8_t mapBase58[256] = {
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
{
// Skip leading spaces.
- while (*psz && isspace(*psz))
+ while (*psz && IsSpace(*psz))
psz++;
// Skip and count leading '1's.
int zeroes = 0;
@@ -48,7 +49,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
std::vector<unsigned char> b256(size);
// Process the characters.
static_assert(sizeof(mapBase58)/sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
- while (*psz && !isspace(*psz)) {
+ while (*psz && !IsSpace(*psz)) {
// Decode base58 character
int carry = mapBase58[(uint8_t)*psz];
if (carry == -1) // Invalid b58 character
@@ -64,7 +65,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
psz++;
}
// Skip trailing spaces.
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
if (*psz != 0)
return false;
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index 8b80e17391..3c4b453a23 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -6,7 +6,7 @@
#include <validation.h>
#include <bech32.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <vector>
#include <string>
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 4fa516cb81..32faba86b4 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -7,8 +7,8 @@
#include <crypto/sha256.h>
#include <key.h>
#include <random.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <validation.h>
#include <memory>
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index bc99b8cdcd..ac2299374c 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -13,7 +13,7 @@
#include <scheduler.h>
#include <txdb.h>
#include <txmempool.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <validation.h>
#include <validationinterface.h>
diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp
index 79689f6e0b..6ab542067a 100644
--- a/src/bench/checkqueue.cpp
+++ b/src/bench/checkqueue.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <checkqueue.h>
#include <prevector.h>
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 27c23d6834..decdadfb26 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -33,7 +33,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<Ou
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CoinSelection(benchmark::State& state)
{
- const CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ const CWallet wallet(WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet.cs_wallet);
// Add coins.
@@ -57,7 +57,7 @@ static void CoinSelection(benchmark::State& state)
}
typedef std::set<CInputCoin> CoinSet;
-static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static const CWallet testWallet(WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn;
// Copied from src/wallet/test/coinselector_tests.cpp
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 5b0cf27e04..d7499a3767 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -9,7 +9,7 @@
#include <hash.h>
#include <random.h>
#include <uint256.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp
index 6d95e05ef6..e7ddd5a938 100644
--- a/src/bench/examples.cpp
+++ b/src/bench/examples.cpp
@@ -4,7 +4,7 @@
#include <bench/bench.h>
#include <validation.h>
-#include <utiltime.h>
+#include <util/time.h>
// Sanity test: this should loop ten times, and
// min/max/average should be close to 100ms.
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index f466505114..dc1b46faf1 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -12,8 +12,8 @@
#include <fs.h>
#include <rpc/client.h>
#include <rpc/protocol.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <memory>
#include <stdio.h>
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index a3fcb87675..bdc064b9fb 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -18,9 +18,9 @@
#include <script/script.h>
#include <script/sign.h>
#include <univalue.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
#include <memory>
#include <stdio.h>
@@ -356,7 +356,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
if (vStrInputParts.size() < numkeys + 3)
throw std::runtime_error("incorrect number of multisig pubkeys");
- if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required)
+ if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)
throw std::runtime_error("multisig parameter mismatch. Required " \
+ std::to_string(required) + " of " + std::to_string(numkeys) + "signatures.");
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 18fcd9bc2a..c6e2a7c20a 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -15,10 +15,10 @@
#include <init.h>
#include <noui.h>
#include <shutdown.h>
-#include <util.h>
+#include <util/system.h>
#include <httpserver.h>
#include <httprpc.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <walletinitinterface.h>
#include <stdio.h>
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index 4c57965bec..a06bced11b 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -11,7 +11,7 @@
#include <streams.h>
#include <txmempool.h>
#include <validation.h>
-#include <util.h>
+#include <util/system.h>
#include <unordered_map>
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 0574e2395e..4ce1b53880 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -8,8 +8,8 @@
#include <chainparamsseeds.h>
#include <consensus/merkle.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <versionbitsinfo.h>
#include <assert.h>
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 870640e77d..f0559a319a 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -6,8 +6,8 @@
#include <chainparamsbase.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilmemory.h>
+#include <util/system.h>
+#include <util/memory.h>
#include <assert.h>
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 2a87a936b1..b47d9774ca 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -4,7 +4,7 @@
#include <consensus/merkle.h>
#include <hash.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
/* WARNING! If you're reading this because you're learning about crypto
and/or designing a new system that will use merkle trees, keep in mind
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index 0628ec1d47..b17a8bb31d 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -12,7 +12,7 @@
// TODO remove the following dependencies
#include <chain.h>
#include <coins.h>
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 301f99bc1c..3b82b2853c 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -11,8 +11,8 @@
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <boost/algorithm/string/classification.hpp>
diff --git a/src/core_write.cpp b/src/core_write.cpp
index b86490716f..765a170307 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -12,9 +12,9 @@
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
UniValue ValueFromAmount(const CAmount& amount)
{
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 52f9efe17c..416f5e8399 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -9,8 +9,8 @@
#include <fs.h>
#include <serialize.h>
#include <streams.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <leveldb/db.h>
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 3eb77354c1..2a9b297029 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdio.h>
-#include <util.h>
+#include <util/system.h>
#include <walletinitinterface.h>
class CWallet;
diff --git a/src/fs.cpp b/src/fs.cpp
index a146107c4c..3c8f4c0247 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -3,6 +3,7 @@
#ifndef WIN32
#include <fcntl.h>
#else
+#define NOMINMAX
#include <codecvt>
#include <windows.h>
#endif
@@ -89,7 +90,7 @@ bool FileLock::TryLock()
return false;
}
_OVERLAPPED overlapped = {0};
- if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, 0, 0, &overlapped)) {
+ if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
reason = GetErrorReason();
return false;
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 4064251c71..fcf760a4c6 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -11,8 +11,8 @@
#include <rpc/server.h>
#include <random.h>
#include <sync.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <ui_interface.h>
#include <walletinitinterface.h>
#include <crypto/hmac_sha256.h>
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index c29f7a4375..91ebc4680c 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -6,8 +6,8 @@
#include <chainparamsbase.h>
#include <compat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <netbase.h>
#include <rpc/protocol.h> // For HTTP status codes
#include <sync.h>
@@ -224,21 +224,25 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
}
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
- LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
- RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
-
// Early address-based allow check
if (!ClientAllowed(hreq->GetPeer())) {
+ LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n",
+ hreq->GetPeer().ToString());
hreq->WriteReply(HTTP_FORBIDDEN);
return;
}
// Early reject unknown HTTP methods
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
+ LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
+ hreq->GetPeer().ToString());
hreq->WriteReply(HTTP_BADMETHOD);
return;
}
+ LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
+ RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToString());
+
// Find registered handler for prefix
std::string strURI = hreq->GetURI();
std::string path;
@@ -292,26 +296,26 @@ static bool ThreadHTTP(struct event_base* base)
/** Bind HTTP server to specified addresses */
static bool HTTPBindAddresses(struct evhttp* http)
{
- int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
+ int http_port = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
std::vector<std::pair<std::string, uint16_t> > endpoints;
// Determine what addresses to bind to
if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs
- endpoints.push_back(std::make_pair("::1", defaultPort));
- endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
+ endpoints.push_back(std::make_pair("::1", http_port));
+ endpoints.push_back(std::make_pair("127.0.0.1", http_port));
if (gArgs.IsArgSet("-rpcbind")) {
LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
}
} else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
- int port = defaultPort;
+ int port = http_port;
std::string host;
SplitHostPort(strRPCBind, port, host);
endpoints.push_back(std::make_pair(host, port));
}
} else { // No specific bind address specified, bind to any
- endpoints.push_back(std::make_pair("::", defaultPort));
- endpoints.push_back(std::make_pair("0.0.0.0", defaultPort));
+ endpoints.push_back(std::make_pair("::", http_port));
+ endpoints.push_back(std::make_pair("0.0.0.0", http_port));
}
// Bind addresses
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 788f7adccd..4d4a7e1502 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -7,7 +7,7 @@
#include <shutdown.h>
#include <tinyformat.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <warnings.h>
@@ -65,7 +65,7 @@ bool BaseIndex::Init()
return true;
}
-static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev)
+static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index f606c8993c..ba1c44765f 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -5,7 +5,7 @@
#include <index/txindex.h>
#include <shutdown.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <boost/thread.hpp>
diff --git a/src/init.cpp b/src/init.cpp
index 06f9ace7ec..d54d4a8782 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -41,8 +41,8 @@
#include <txmempool.h>
#include <torcontrol.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <validationinterface.h>
#include <warnings.h>
#include <walletinitinterface.h>
diff --git a/src/init.h b/src/init.h
index c58ba5cfd3..b106353d08 100644
--- a/src/init.h
+++ b/src/init.h
@@ -8,7 +8,7 @@
#include <memory>
#include <string>
-#include <util.h>
+#include <util/system.h>
class CScheduler;
class CWallet;
diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp
index ddf9b342d8..92601fc4e9 100644
--- a/src/interfaces/handler.cpp
+++ b/src/interfaces/handler.cpp
@@ -4,7 +4,7 @@
#include <interfaces/handler.h>
-#include <utilmemory.h>
+#include <util/memory.h>
#include <boost/signals2/connection.hpp>
#include <utility>
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 2b19e11f08..490c456e6e 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -25,7 +25,7 @@
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <warnings.h>
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 566ae37509..14c6bd0330 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -103,7 +103,7 @@ static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_R
}
//! Construct wallet TxOut struct.
-static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet.cs_wallet)
{
WalletTxOut result;
result.txout = wtx.tx->vout[n];
@@ -290,8 +290,7 @@ public:
}
bool tryGetTxStatus(const uint256& txid,
interfaces::WalletTxStatus& tx_status,
- int& num_blocks,
- int64_t& adjusted_time) override
+ int& num_blocks) override
{
TRY_LOCK(::cs_main, locked_chain);
if (!locked_chain) {
@@ -306,7 +305,6 @@ public:
return false;
}
num_blocks = ::chainActive.Height();
- adjusted_time = GetAdjustedTime();
tx_status = MakeWalletTxStatus(mi->second);
return true;
}
@@ -314,14 +312,12 @@ public:
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
- int& num_blocks,
- int64_t& adjusted_time) override
+ int& num_blocks) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
num_blocks = ::chainActive.Height();
- adjusted_time = GetAdjustedTime();
in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm;
tx_status = MakeWalletTxStatus(mi->second);
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 7aa91f37e1..c79b9afce3 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -178,16 +178,14 @@ public:
//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
WalletTxStatus& tx_status,
- int& num_blocks,
- int64_t& adjusted_time) = 0;
+ int& num_blocks) = 0;
//! Get transaction details.
virtual WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
- int& num_blocks,
- int64_t& adjusted_time) = 0;
+ int& num_blocks) = 0;
//! Get balances.
virtual WalletBalances getBalances() = 0;
diff --git a/src/key_io.cpp b/src/key_io.cpp
index c6a541cdb1..282385f50d 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -7,7 +7,7 @@
#include <base58.h>
#include <bech32.h>
#include <script/script.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
diff --git a/src/keystore.cpp b/src/keystore.cpp
index b2012a04bb..148979cf35 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -5,7 +5,7 @@
#include <keystore.h>
-#include <util.h>
+#include <util/system.h>
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
{
diff --git a/src/logging.cpp b/src/logging.cpp
index 0ae4f8121e..77dc2d0939 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <logging.h>
-#include <utiltime.h>
+#include <util/time.h>
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 7bbc45d38a..0c37bab1f8 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -7,7 +7,7 @@
#include <hash.h>
#include <consensus/consensus.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
diff --git a/src/miner.cpp b/src/miner.cpp
index 6d35f9ac37..feb86cab66 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -21,8 +21,8 @@
#include <primitives/transaction.h>
#include <script/standard.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <validationinterface.h>
#include <algorithm>
diff --git a/src/net.cpp b/src/net.cpp
index c8d3efceed..65a308780a 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -18,7 +18,7 @@
#include <netbase.h>
#include <scheduler.h>
#include <ui_interface.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#ifdef WIN32
#include <string.h>
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index a1b6e021ae..f37312d155 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -25,9 +25,9 @@
#include <tinyformat.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
#include <memory>
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 778c2700f9..e1af4eff62 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -5,7 +5,7 @@
#include <netaddress.h>
#include <hash.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <tinyformat.h>
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 04d5eb12c8..6a750d5141 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -10,8 +10,8 @@
#include <uint256.h>
#include <random.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <atomic>
diff --git a/src/noui.cpp b/src/noui.cpp
index df4bfabb66..c7d8fee0ba 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -6,7 +6,7 @@
#include <noui.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <cstdio>
#include <stdint.h>
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index aee6fbee1a..3afe6fe1b7 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -10,7 +10,7 @@
#include <primitives/transaction.h>
#include <streams.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
static constexpr double INF_FEERATE = 1e99;
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index ac1b75edb4..d4cc538492 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -11,8 +11,8 @@
#include <validation.h>
#include <coins.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index fb95a66bde..a0c2e3f125 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -7,7 +7,7 @@
#include <hash.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <crypto/common.h>
uint256 CBlockHeader::GetHash() const
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index bdb470470e..28c145f71d 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -7,7 +7,7 @@
#include <hash.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
std::string COutPoint::ToString() const
{
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 6d8b530f69..0f834eb8c1 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -73,7 +73,7 @@ public:
/* Below flags apply in the context of BIP 68*/
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. */
- static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
+ static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1U << 31);
/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
diff --git a/src/protocol.cpp b/src/protocol.cpp
index b4fc9def1f..bdf236c2c7 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -5,8 +5,8 @@
#include <protocol.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#ifndef WIN32
# include <arpa/inet.h>
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 97348aad2b..dcfe3dcc57 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -10,7 +10,7 @@
#include <interfaces/node.h>
#include <sync.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <QDebug>
#include <QList>
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index a014ad4b28..7508f596e6 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -32,7 +32,7 @@
#include <rpc/server.h>
#include <ui_interface.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
#include <walletinitinterface.h>
@@ -439,8 +439,10 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
window->setCurrentWallet(walletModel->getWalletName());
}
+#ifdef ENABLE_BIP70
connect(walletModel, &WalletModel::coinsSent,
paymentServer, &PaymentServer::fetchPaymentACK);
+#endif
connect(walletModel, &WalletModel::unload, this, &BitcoinApplication::removeWallet);
m_wallet_models.push_back(walletModel);
@@ -467,7 +469,9 @@ void BitcoinApplication::initializeResult(bool success)
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
qWarning() << "Platform customization:" << platformStyle->getName();
#ifdef ENABLE_WALLET
+#ifdef ENABLE_BIP70
PaymentServer::LoadRootCAs();
+#endif
paymentServer->setOptionsModel(optionsModel);
#endif
@@ -536,7 +540,7 @@ WId BitcoinApplication::getMainWinId() const
static void SetupUIArgs()
{
-#ifdef ENABLE_WALLET
+#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), true, OptionsCategory::GUI);
#endif
gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 311841017f..072334ebb0 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -33,7 +33,7 @@
#include <interfaces/node.h>
#include <noui.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <iostream>
diff --git a/src/qt/callback.h b/src/qt/callback.h
deleted file mode 100644
index da6b0c4c2e..0000000000
--- a/src/qt/callback.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef BITCOIN_QT_CALLBACK_H
-#define BITCOIN_QT_CALLBACK_H
-
-#include <QObject>
-
-class Callback : public QObject
-{
- Q_OBJECT
-public Q_SLOTS:
- virtual void call() = 0;
-};
-
-template <typename F>
-class FunctionCallback : public Callback
-{
- F f;
-
-public:
- explicit FunctionCallback(F f_) : f(std::move(f_)) {}
- ~FunctionCallback() override {}
- void call() override { f(this); }
-};
-
-template <typename F>
-FunctionCallback<F>* makeCallback(F f)
-{
- return new FunctionCallback<F>(std::move(f));
-}
-
-#endif // BITCOIN_QT_CALLBACK_H
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 183444efab..75012b279c 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -20,7 +20,7 @@
#include <netbase.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
#include <stdint.h>
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 68330c51fa..ea970c0bc9 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -2,10 +2,15 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/coincontroldialog.h>
#include <qt/forms/ui_coincontroldialog.h>
#include <qt/addresstablemodel.h>
+#include <base58.h>
#include <qt/bitcoinunits.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 5f6af61a70..a68140ccf9 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -18,7 +18,7 @@
#include <protocol.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
+#include <util/system.h>
#ifdef WIN32
#ifdef _WIN32_WINNT
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index b19cc17a4d..0b61b05318 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -13,7 +13,7 @@
#include <qt/guiutil.h>
#include <interfaces/node.h>
-#include <util.h>
+#include <util/system.h>
#include <QFileDialog>
#include <QSettings>
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index a989988c45..b962ab1ef2 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -9,7 +9,7 @@
#include <qt/paymentrequestplus.h>
-#include <util.h>
+#include <util/system.h>
#include <stdexcept>
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index bcafc8f859..8148986b51 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/paymentserver.h>
#include <qt/bitcoinunits.h>
@@ -13,7 +17,7 @@
#include <policy/policy.h>
#include <key_io.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <wallet/wallet.h>
#include <cstdlib>
@@ -45,6 +49,7 @@
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";
@@ -52,21 +57,7 @@ const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment";
const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack";
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest";
-
-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;
-}
+#endif
//
// Create a name that is unique for:
@@ -93,94 +84,6 @@ static QString ipcServerName()
static QList<QString> savedPaymentRequests;
-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:
- QSslSocket::setDefaultCaCertificates(certList);
- } else
- certList = QSslSocket::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;
- }
- }
- qWarning() << "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
-}
-
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
@@ -221,6 +124,7 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
}
}
}
+#ifdef ENABLE_BIP70
else if (QFile::exists(arg)) // Filename
{
savedPaymentRequests.append(arg);
@@ -244,6 +148,7 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
// 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
}
}
@@ -290,12 +195,16 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
QObject(parent),
saveURIs(true),
uriServer(0),
- netManager(0),
optionsModel(0)
+#ifdef ENABLE_BIP70
+ ,netManager(0)
+#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
@@ -319,14 +228,18 @@ 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
}
//
@@ -349,33 +262,11 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
return QObject::eventFilter(object, event);
}
-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);
-}
-
void PaymentServer::uiReady()
{
+#ifdef ENABLE_BIP70
initNetManager();
+#endif
saveURIs = false;
for (const QString& s : savedPaymentRequests)
@@ -403,6 +294,10 @@ void PaymentServer::handleURIOrFile(const QString& s)
QUrlQuery uri((QUrl(s)));
if (uri.hasQueryItem("r")) // payment request URI
{
+#ifdef ENABLE_BIP70
+ 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);
@@ -420,7 +315,11 @@ void PaymentServer::handleURIOrFile(const QString& s)
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
CClientUIInterface::ICON_WARNING);
}
-
+#else
+ Q_EMIT message(tr("URI handling"),
+ tr("Cannot process payment request because BIP70 support was not compiled in."),
+ CClientUIInterface::ICON_WARNING);
+#endif
return;
}
else // normal URI
@@ -444,6 +343,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
}
+#ifdef ENABLE_BIP70
if (QFile::exists(s)) // payment request file
{
PaymentRequestPlus request;
@@ -459,6 +359,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
return;
}
+#endif
}
void PaymentServer::handleURIConnection()
@@ -481,6 +382,140 @@ void PaymentServer::handleURIConnection()
handleURIOrFile(msg);
}
+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:
+ QSslSocket::setDefaultCaCertificates(certList);
+ } else
+ certList = QSslSocket::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;
+ }
+ }
+ qWarning() << "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::"!
@@ -731,11 +766,6 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
}
-void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
-{
- this->optionsModel = _optionsModel;
-}
-
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
{
// currently we don't further process or store the paymentACK message
@@ -794,3 +824,4 @@ X509_STORE* PaymentServer::getCertStore()
{
return certStore.get();
}
+#endif
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index d335db9c85..30b5bc3b6d 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -32,7 +32,13 @@
// sends them to the server.
//
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h>
+#endif
#include <qt/walletmodel.h>
#include <QObject>
@@ -73,6 +79,10 @@ public:
explicit PaymentServer(QObject* parent, bool startLocalServer = true);
~PaymentServer();
+ // 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.
@@ -83,9 +93,6 @@ public:
// Return certificate store
static X509_STORE* getCertStore();
- // OptionsModel is used for getting proxy settings and display unit
- void setOptionsModel(OptionsModel *optionsModel);
-
// 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
@@ -94,33 +101,40 @@ public:
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);
- // Fired when a valid PaymentACK is received
- void receivedPaymentACK(const QString &paymentACKMsg);
-
// 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
void uiReady();
- // Submit Payment message to a merchant, get back PaymentACK:
- void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
-
// 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
@@ -128,19 +142,19 @@ protected:
bool eventFilter(QObject *object, QEvent *event);
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();
-
- bool saveURIs; // true during startup
- QLocalServer* uriServer;
-
QNetworkAccessManager* netManager; // Used to fetch payment requests
-
- OptionsModel *optionsModel;
+#endif
};
#endif // BITCOIN_QT_PAYMENTSERVER_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index c004c783f2..606f1d2910 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -18,7 +18,7 @@
#include <netbase.h>
#include <rpc/server.h>
#include <rpc/client.h>
-#include <util.h>
+#include <util/system.h>
#include <openssl/crypto.h>
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 6f66bc19e1..858128f9f9 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/sendcoinsdialog.h>
#include <qt/forms/ui_sendcoinsdialog.h>
@@ -290,7 +294,9 @@ void SendCoinsDialog::on_sendButton_clicked()
QString recipientElement;
recipientElement = "<br />";
+#ifdef ENABLE_BIP70
if (!rcp.paymentRequest.IsInitialized()) // normal payment
+#endif
{
if(rcp.label.length() > 0) // label with address
{
@@ -302,6 +308,7 @@ 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, GUIUtil::HtmlEscape(rcp.authenticatedMerchant)));
@@ -310,6 +317,7 @@ void SendCoinsDialog::on_sendButton_clicked()
{
recipientElement.append(tr("%1 to %2").arg(amount, address));
}
+#endif
formatted.append(recipientElement);
}
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index b394ff3150..76c942c8b9 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/sendcoinsentry.h>
#include <qt/forms/ui_sendcoinsentry.h>
@@ -133,9 +137,11 @@ 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()))
{
@@ -166,9 +172,11 @@ 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();
@@ -196,6 +204,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
recipient = value;
+#ifdef ENABLE_BIP70
if (recipient.paymentRequest.IsInitialized()) // payment request
{
if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated
@@ -216,6 +225,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
}
}
else // normal payment
+#endif
{
// message
ui->messageTextLabel->setText(recipient.message);
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 1eff4f6b65..b6235e91f7 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -15,7 +15,7 @@
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <version.h>
#include <QApplication>
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index c3d33c76d4..0cabb5f0be 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -6,17 +6,17 @@
#include <qt/addressbookpage.h>
#include <qt/addresstablemodel.h>
#include <qt/editaddressdialog.h>
-#include <qt/callback.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
#include <qt/walletmodel.h>
#include <key.h>
-#include <pubkey.h>
#include <key_io.h>
+#include <pubkey.h>
#include <wallet/wallet.h>
+#include <QApplication>
#include <QTimer>
#include <QMessageBox>
@@ -56,7 +56,7 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook()
{
TestChain100Setup test;
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
@@ -139,5 +139,16 @@ void TestAddAddressesToSendBook()
void AddressBookTests::addressBookTests()
{
+#ifdef Q_OS_MAC
+ if (QApplication::platformName() == "minimal") {
+ // Disable for mac on "minimal" platform to avoid crashes inside the Qt
+ // framework when it tries to look up unimplemented cocoa functions,
+ // and fails to handle returned nulls
+ // (https://bugreports.qt.io/browse/QTBUG-49686).
+ QWARN("Skipping AddressBookTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
+ "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
+ return;
+ }
+#endif
TestAddAddressesToSendBook();
}
diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp
index af5c69ea9a..6750c543da 100644
--- a/src/qt/test/compattests.cpp
+++ b/src/qt/test/compattests.cpp
@@ -2,7 +2,13 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#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>
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index 5384b9e8b0..94907595f5 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -13,8 +13,8 @@
#include <random.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index 2e321c1ba1..ed453336da 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -14,7 +14,7 @@
#include <qt/rpcconsole.h>
#include <test/test_bitcoin.h>
#include <univalue.h>
-#include <util.h>
+#include <util/system.h>
#include <QDir>
#include <QtGlobal>
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index df65a85fb5..b6523604fd 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -8,15 +8,17 @@
#include <chainparams.h>
#include <qt/test/rpcnestedtests.h>
-#include <util.h>
+#include <util/system.h>
#include <qt/test/uritests.h>
#include <qt/test/compattests.h>
#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
+#endif // ENABLE_WALLET
#include <QApplication>
#include <QObject>
@@ -74,7 +76,7 @@ int main(int argc, char *argv[])
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
-#ifdef ENABLE_WALLET
+#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
PaymentServerTests test2;
if (QTest::qExec(&test2) != 0) {
fInvalid = true;
diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp
index 0bd719326e..ae2fb93bf7 100644
--- a/src/qt/test/util.cpp
+++ b/src/qt/test/util.cpp
@@ -1,15 +1,13 @@
-#include <qt/callback.h>
-
#include <QApplication>
#include <QMessageBox>
-#include <QTimer>
-#include <QString>
#include <QPushButton>
+#include <QString>
+#include <QTimer>
#include <QWidget>
void ConfirmMessage(QString* text, int msec)
{
- QTimer::singleShot(msec, makeCallback([text](Callback* callback) {
+ QTimer::singleShot(msec, [text]() {
for (QWidget* widget : QApplication::topLevelWidgets()) {
if (widget->inherits("QMessageBox")) {
QMessageBox* messageBox = qobject_cast<QMessageBox*>(widget);
@@ -17,6 +15,5 @@ void ConfirmMessage(QString* text, int msec)
messageBox->defaultButton()->click();
}
}
- delete callback;
- }), &Callback::call);
+ });
}
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index a0cfe8ae87..12dbf922f1 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -2,8 +2,8 @@
#include <qt/test/util.h>
#include <interfaces/node.h>
+#include <base58.h>
#include <qt/bitcoinamountfield.h>
-#include <qt/callback.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
@@ -39,7 +39,7 @@ namespace
//! Press "Yes" or "Cancel" buttons in modal send confirmation dialog.
void ConfirmSend(QString* text = nullptr, bool cancel = false)
{
- QTimer::singleShot(0, makeCallback([text, cancel](Callback* callback) {
+ QTimer::singleShot(0, [text, cancel]() {
for (QWidget* widget : QApplication::topLevelWidgets()) {
if (widget->inherits("SendConfirmationDialog")) {
SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget);
@@ -49,8 +49,7 @@ void ConfirmSend(QString* text = nullptr, bool cancel = false)
button->click();
}
}
- delete callback;
- }), &Callback::call);
+ });
}
//! Send coins to address and return txid.
@@ -133,7 +132,7 @@ void TestGUI()
for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
{
@@ -243,5 +242,16 @@ void TestGUI()
void WalletTests::walletTests()
{
+#ifdef Q_OS_MAC
+ if (QApplication::platformName() == "minimal") {
+ // Disable for mac on "minimal" platform to avoid crashes inside the Qt
+ // framework when it tries to look up unimplemented cocoa functions,
+ // and fails to handle returned nulls
+ // (https://bugreports.qt.io/browse/QTBUG-49686).
+ QWARN("Skipping WalletTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
+ "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
+ return;
+ }
+#endif
TestGUI();
}
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 59332be754..0d070d9e87 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifdef HAVE_CONFIG_H
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/transactiondesc.h>
#include <qt/bitcoinunits.h>
@@ -15,7 +19,7 @@
#include <validation.h>
#include <script/script.h>
#include <timedata.h>
-#include <util.h>
+#include <util/system.h>
#include <wallet/db.h>
#include <wallet/wallet.h>
#include <policy/policy.h>
@@ -23,7 +27,7 @@
#include <stdint.h>
#include <string>
-QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime)
+QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks)
{
if (!status.is_final)
{
@@ -49,11 +53,10 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
{
int numBlocks;
- int64_t adjustedTime;
interfaces::WalletTxStatus status;
interfaces::WalletOrderForm orderForm;
bool inMempool;
- interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks, adjustedTime);
+ interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks);
QString strHTML;
@@ -65,7 +68,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
CAmount nDebit = wtx.debit;
CAmount nNet = nCredit - nDebit;
- strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime);
+ strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks);
strHTML += "<br>";
strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
@@ -257,6 +260,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
if (r.first == "Message")
strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
+#ifdef ENABLE_BIP70
//
// PaymentRequest info:
//
@@ -271,6 +275,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
}
}
+#endif
if (wtx.is_coinbase)
{
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index 80eca7b97c..cf955a433c 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -29,7 +29,7 @@ public:
private:
TransactionDesc() {}
- static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime);
+ static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks);
};
#endif // BITCOIN_QT_TRANSACTIONDESC_H
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index d1a7527ac7..d88cfe52ed 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -158,7 +158,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
return parts;
}
-void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime)
+void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks)
{
// Determine transaction status
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index e187309d3f..470f70e2ab 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -138,7 +138,7 @@ public:
/** Update status from core wallet tx.
*/
- void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime);
+ void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks);
/** Return whether a status update is needed.
*/
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index b4be068904..1983c3bc92 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -18,7 +18,7 @@
#include <interfaces/node.h>
#include <sync.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <QColor>
@@ -193,9 +193,8 @@ public:
// simply re-use the cached status.
interfaces::WalletTxStatus wtx;
int numBlocks;
- int64_t adjustedTime;
- if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, adjustedTime) && rec->statusUpdateNeeded(numBlocks)) {
- rec->updateStatus(wtx, numBlocks, adjustedTime);
+ if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks) && rec->statusUpdateNeeded(numBlocks)) {
+ rec->updateStatus(wtx, numBlocks);
}
return rec;
}
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 7d903b3b1c..ebf7bad795 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -14,13 +14,15 @@
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/intro.h>
+#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h>
+#endif
#include <qt/guiutil.h>
#include <clientversion.h>
#include <init.h>
#include <interfaces/node.h>
-#include <util.h>
+#include <util/system.h>
#include <stdio.h>
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index f7cc94ae32..353da0c9b4 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/walletmodel.h>
#include <qt/addresstablemodel.h>
@@ -16,7 +20,7 @@
#include <interfaces/node.h>
#include <key_io.h>
#include <ui_interface.h>
-#include <util.h> // for GetBoolArg
+#include <util/system.h> // for GetBoolArg
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
@@ -142,6 +146,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
if (rcp.fSubtractFeeFromAmount)
fSubtractFeeFromAmount = true;
+#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest...
CAmount subtotal = 0;
@@ -164,6 +169,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
total += subtotal;
}
else
+#endif
{ // User-entered bitcoin address / amount:
if(!validateAddress(rcp.address))
{
@@ -235,6 +241,7 @@ 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.
@@ -247,7 +254,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
rcp.paymentRequest.SerializeToString(&value);
vOrderForm.emplace_back("PaymentRequest", std::move(value));
}
- else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
+ else
+#endif
+ if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
vOrderForm.emplace_back("Message", rcp.message.toStdString());
}
@@ -266,7 +275,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
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 b22728c69b..ec4c5a2a6c 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -10,7 +10,13 @@
#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>
@@ -63,8 +69,14 @@ public:
// 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;
@@ -80,9 +92,11 @@ 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);
@@ -98,8 +112,10 @@ 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);
}
}
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index de50616499..eb3b0baf08 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifdef HAVE_CONFIG_H
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/walletmodeltransaction.h>
#include <interfaces/node.h>
@@ -46,6 +50,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
{
SendCoinsRecipient& rcp = (*it);
+#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized())
{
CAmount subtotal = 0;
@@ -62,6 +67,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
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 75ede2e2a1..289aee847b 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -8,6 +8,7 @@
#include <qt/walletmodel.h>
#include <memory>
+#include <amount.h>
#include <QObject>
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index d732326b33..08cae76add 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -6,7 +6,7 @@
#if defined(Q_OS_WIN)
#include <shutdown.h>
-#include <util.h>
+#include <util/system.h>
#include <windows.h>
diff --git a/src/random.cpp b/src/random.cpp
index 503d5b3636..a34c70e1d5 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -13,7 +13,7 @@
#endif
#include <logging.h> // for LogPrint()
#include <sync.h> // for WAIT_LOCK
-#include <utiltime.h> // for GetTime()
+#include <util/time.h> // for GetTime()
#include <stdlib.h>
#include <chrono>
@@ -35,7 +35,7 @@
#include <sys/random.h>
#endif
#ifdef HAVE_SYSCTL_ARND
-#include <utilstrencodings.h> // for ARRAYLEN
+#include <util/strencodings.h> // for ARRAYLEN
#include <sys/sysctl.h>
#endif
diff --git a/src/rest.cpp b/src/rest.cpp
index 1850c0b7a6..6c7e0384cb 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -16,7 +16,7 @@
#include <streams.h>
#include <sync.h>
#include <txmempool.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <version.h>
#include <boost/algorithm/string.hpp>
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index ff71b19250..92f6f0fe11 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -26,8 +26,8 @@
#include <sync.h>
#include <txdb.h>
#include <txmempool.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <hash.h>
#include <validationinterface.h>
#include <versionbitsinfo.h>
@@ -1798,6 +1798,10 @@ static UniValue getblockstats(const JSONRPCRequest& request)
const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "feerate_percentiles", "minfeerate", "maxfeerate");
const bool do_calculate_sw = do_all || SetHasKeys(stats, "swtxs", "swtotal_size", "swtotal_weight");
+ if (loop_inputs && !g_txindex) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled");
+ }
+
CAmount maxfee = 0;
CAmount maxfeerate = 0;
CAmount minfee = MAX_MONEY;
@@ -1861,10 +1865,6 @@ static UniValue getblockstats(const JSONRPCRequest& request)
}
if (loop_inputs) {
-
- if (!g_txindex) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled");
- }
CAmount tx_total_in = 0;
for (const CTxIn& in : tx->vin) {
CTransactionRef tx_in;
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 649e222c39..2b99808c07 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -5,7 +5,7 @@
#include <rpc/client.h>
#include <rpc/protocol.h>
-#include <util.h>
+#include <util/system.h>
#include <set>
#include <stdint.h>
@@ -45,7 +45,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listreceivedbyaddress", 0, "minconf" },
{ "listreceivedbyaddress", 1, "include_empty" },
{ "listreceivedbyaddress", 2, "include_watchonly" },
- { "listreceivedbyaddress", 3, "address_filter" },
{ "listreceivedbylabel", 0, "minconf" },
{ "listreceivedbylabel", 1, "include_empty" },
{ "listreceivedbylabel", 2, "include_watchonly" },
@@ -148,7 +147,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "logging", 0, "include" },
{ "logging", 1, "exclude" },
{ "disconnectnode", 1, "nodeid" },
- { "addwitnessaddress", 1, "p2sh" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index c565b9b4f9..58b54c66de 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -20,8 +20,8 @@
#include <rpc/server.h>
#include <shutdown.h>
#include <txmempool.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <validation.h>
#include <validationinterface.h>
#include <versionbitsinfo.h>
@@ -167,6 +167,8 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
"\nExamples:\n"
"\nGenerate 11 blocks to myaddress\n"
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
+ + "If you are running the bitcoin core wallet, you can get a new address to send the newly generated bitcoin to with:\n"
+ + HelpExampleCli("getnewaddress", "")
);
int nGenerate = request.params[0].get_int();
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 6a66998d37..cebf12bb34 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -17,8 +17,8 @@
#include <rpc/server.h>
#include <rpc/util.h>
#include <timedata.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <warnings.h>
#include <stdint.h>
@@ -446,7 +446,7 @@ static const CRPCCommand commands[] =
{ "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
{ "control", "logging", &logging, {"include", "exclude"}},
{ "util", "validateaddress", &validateaddress, {"address"} },
- { "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
+ { "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} },
{ "util", "verifymessage", &verifymessage, {"address","signature","message"} },
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 846d90cd0a..4d893bb838 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -16,8 +16,8 @@
#include <sync.h>
#include <timedata.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <warnings.h>
diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp
index ee178f34ce..23999b305a 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -7,9 +7,9 @@
#include <random.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <util/time.h>
#include <version.h>
/**
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index a2d990b51d..0f87646b08 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -26,7 +26,7 @@
#include <script/standard.h>
#include <txmempool.h>
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <future>
#include <stdint.h>
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 60bf3c28c0..78abd7b610 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -11,8 +11,8 @@
#include <shutdown.h>
#include <sync.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <boost/bind.hpp>
#include <boost/signals2/signal.hpp>
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index ba414bf3f5..8a66191a6a 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -7,7 +7,7 @@
#include <rpc/protocol.h>
#include <rpc/util.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
// Converts a hex string to a public key if possible
CPubKey HexToPubKey(const std::string& hex_in)
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 45b097dde6..90c4ddcc11 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -10,8 +10,8 @@
#include <script/standard.h>
#include <span.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <memory>
#include <string>
@@ -41,7 +41,7 @@ struct PubkeyProvider
virtual ~PubkeyProvider() = default;
/** Derive a public key. */
- virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const = 0;
+ virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info) const = 0;
/** Whether this represent multiple public keys at different positions. */
virtual bool IsRange() const = 0;
@@ -56,6 +56,37 @@ struct PubkeyProvider
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
};
+class OriginPubkeyProvider final : public PubkeyProvider
+{
+ KeyOriginInfo m_origin;
+ std::unique_ptr<PubkeyProvider> m_provider;
+
+ std::string OriginString() const
+ {
+ return HexStr(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint)) + FormatKeyPath(m_origin.path);
+ }
+
+public:
+ OriginPubkeyProvider(KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : m_origin(std::move(info)), m_provider(std::move(provider)) {}
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info) const override
+ {
+ if (!m_provider->GetPubKey(pos, arg, key, info)) return false;
+ std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
+ info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
+ return true;
+ }
+ bool IsRange() const override { return m_provider->IsRange(); }
+ size_t GetSize() const override { return m_provider->GetSize(); }
+ std::string ToString() const override { return "[" + OriginString() + "]" + m_provider->ToString(); }
+ bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
+ {
+ std::string sub;
+ if (!m_provider->ToPrivateString(arg, sub)) return false;
+ ret = "[" + OriginString() + "]" + std::move(sub);
+ return true;
+ }
+};
+
/** An object representing a parsed constant public key in a descriptor. */
class ConstPubkeyProvider final : public PubkeyProvider
{
@@ -63,9 +94,12 @@ class ConstPubkeyProvider final : public PubkeyProvider
public:
ConstPubkeyProvider(const CPubKey& pubkey) : m_pubkey(pubkey) {}
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info) const override
{
- out = m_pubkey;
+ key = m_pubkey;
+ info.path.clear();
+ CKeyID keyid = m_pubkey.GetID();
+ std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
return true;
}
bool IsRange() const override { return false; }
@@ -98,7 +132,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
CKey key;
if (!arg.GetKey(m_extkey.pubkey.GetID(), key)) return false;
ret.nDepth = m_extkey.nDepth;
- std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + 4, ret.vchFingerprint);
+ std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
ret.nChild = m_extkey.nChild;
ret.chaincode = m_extkey.chaincode;
ret.key = key;
@@ -118,27 +152,32 @@ public:
BIP32PubkeyProvider(const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
bool IsRange() const override { return m_derive != DeriveType::NO; }
size_t GetSize() const override { return 33; }
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info) const override
{
if (IsHardened()) {
- CExtKey key;
- if (!GetExtKey(arg, key)) return false;
+ CExtKey extkey;
+ if (!GetExtKey(arg, extkey)) return false;
for (auto entry : m_path) {
- key.Derive(key, entry);
+ extkey.Derive(extkey, entry);
}
- if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
- if (m_derive == DeriveType::HARDENED) key.Derive(key, pos | 0x80000000UL);
- out = key.Neuter().pubkey;
+ if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
+ if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
+ key = extkey.Neuter().pubkey;
} else {
// TODO: optimize by caching
- CExtPubKey key = m_extkey;
+ CExtPubKey extkey = m_extkey;
for (auto entry : m_path) {
- key.Derive(key, entry);
+ extkey.Derive(extkey, entry);
}
- if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
+ if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
assert(m_derive != DeriveType::HARDENED);
- out = key.pubkey;
+ key = extkey.pubkey;
}
+ CKeyID keyid = m_extkey.pubkey.GetID();
+ std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
+ info.path = m_path;
+ if (m_derive == DeriveType::UNHARDENED) info.path.push_back((uint32_t)pos);
+ if (m_derive == DeriveType::HARDENED) info.path.push_back(((uint32_t)pos) | 0x80000000L);
return true;
}
std::string ToString() const override
@@ -221,9 +260,11 @@ public:
bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
{
CPubKey key;
- if (!m_provider->GetPubKey(pos, arg, key)) return false;
+ KeyOriginInfo info;
+ if (!m_provider->GetPubKey(pos, arg, key, info)) return false;
output_scripts = std::vector<CScript>{m_script_fn(key)};
- out.pubkeys.emplace(key.GetID(), std::move(key));
+ out.origins.emplace(key.GetID(), std::move(info));
+ out.pubkeys.emplace(key.GetID(), key);
return true;
}
};
@@ -272,15 +313,19 @@ public:
bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
{
- std::vector<CPubKey> pubkeys;
- pubkeys.reserve(m_providers.size());
+ std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
+ entries.reserve(m_providers.size());
+ // Construct temporary data in `entries`, to avoid producing output in case of failure.
for (const auto& p : m_providers) {
- CPubKey key;
- if (!p->GetPubKey(pos, arg, key)) return false;
- pubkeys.push_back(key);
+ entries.emplace_back();
+ if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second)) return false;
}
- for (const CPubKey& key : pubkeys) {
- out.pubkeys.emplace(key.GetID(), std::move(key));
+ std::vector<CPubKey> pubkeys;
+ pubkeys.reserve(entries.size());
+ for (auto& entry : entries) {
+ pubkeys.push_back(entry.first);
+ out.origins.emplace(entry.first.GetID(), std::move(entry.second));
+ out.pubkeys.emplace(entry.first.GetID(), entry.first);
}
output_scripts = std::vector<CScript>{GetScriptForMultisig(m_threshold, pubkeys)};
return true;
@@ -343,13 +388,15 @@ public:
bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
{
CPubKey key;
- if (!m_provider->GetPubKey(pos, arg, key)) return false;
+ KeyOriginInfo info;
+ if (!m_provider->GetPubKey(pos, arg, key, info)) return false;
CKeyID keyid = key.GetID();
{
CScript p2pk = GetScriptForRawPubKey(key);
CScript p2pkh = GetScriptForDestination(keyid);
output_scripts = std::vector<CScript>{std::move(p2pk), std::move(p2pkh)};
out.pubkeys.emplace(keyid, key);
+ out.origins.emplace(keyid, std::move(info));
}
if (key.IsCompressed()) {
CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(keyid));
@@ -447,7 +494,8 @@ bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
return true;
}
-std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
+/** Parse a public key that excludes origin information. */
+std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
{
auto split = Split(sp, '/');
std::string str(split[0].begin(), split[0].end());
@@ -484,6 +532,28 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move(path), type);
}
+/** Parse a public key including origin information (if enabled). */
+std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
+{
+ auto origin_split = Split(sp, ']');
+ if (origin_split.size() > 2) return nullptr;
+ if (origin_split.size() == 1) return ParsePubkeyInner(origin_split[0], permit_uncompressed, out);
+ if (origin_split[0].size() < 1 || origin_split[0][0] != '[') return nullptr;
+ auto slash_split = Split(origin_split[0].subspan(1), '/');
+ if (slash_split[0].size() != 8) return nullptr;
+ std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
+ if (!IsHex(fpr_hex)) return nullptr;
+ auto fpr_bytes = ParseHex(fpr_hex);
+ KeyOriginInfo info;
+ static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
+ assert(fpr_bytes.size() == 4);
+ std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
+ if (!ParseKeyPath(slash_split, info.path)) return nullptr;
+ auto provider = ParsePubkeyInner(origin_split[1], permit_uncompressed, out);
+ if (!provider) return nullptr;
+ return MakeUnique<OriginPubkeyProvider>(std::move(info), std::move(provider));
+}
+
/** Parse a script in a particular context. */
std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out)
{
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 9bdf3ed808..982aa241e7 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -6,7 +6,7 @@
#include <script/script.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
const char* GetOpName(opcodetype opcode)
{
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 68f0542294..94005cf6f3 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -9,7 +9,7 @@
#include <pubkey.h>
#include <random.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <cuckoocache.h>
#include <boost/thread.hpp>
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 0042f35e2e..89cc7c808c 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -280,6 +280,11 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t
if (require_witness_sig && !sigdata.witness) return false;
input.FromSignatureData(sigdata);
+ if (sigdata.witness) {
+ assert(!utxo.IsNull());
+ input.witness_utxo = utxo;
+ }
+
// If both UTXO types are present, drop the unnecessary one.
if (input.non_witness_utxo && !input.witness_utxo.IsNull()) {
if (sigdata.witness) {
@@ -686,6 +691,7 @@ bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& inf
bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
+bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return LookupHelper(origins, keyid, info); }
bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
diff --git a/src/script/sign.h b/src/script/sign.h
index 2fc4575e59..d47aada17d 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -34,7 +34,7 @@ public:
virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; }
virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; }
virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; }
- virtual bool GetKeyOrigin(const CKeyID& id, KeyOriginInfo& info) const { return false; }
+ virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; }
};
extern const SigningProvider& DUMMY_SIGNING_PROVIDER;
@@ -58,10 +58,12 @@ struct FlatSigningProvider final : public SigningProvider
{
std::map<CScriptID, CScript> scripts;
std::map<CKeyID, CPubKey> pubkeys;
+ std::map<CKeyID, KeyOriginInfo> origins;
std::map<CKeyID, CKey> keys;
bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
+ bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
bool GetKey(const CKeyID& keyid, CKey& key) const override;
};
@@ -300,6 +302,7 @@ struct PSBTInput
template <typename Stream>
inline void Unserialize(Stream& s) {
// Read loop
+ bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
@@ -307,7 +310,10 @@ struct PSBTInput
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) return;
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
// First byte of key is the type
unsigned char type = key[0];
@@ -422,6 +428,10 @@ struct PSBTInput
break;
}
}
+
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of an input map");
+ }
}
template <typename Stream>
@@ -475,6 +485,7 @@ struct PSBTOutput
template <typename Stream>
inline void Unserialize(Stream& s) {
// Read loop
+ bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
@@ -482,7 +493,10 @@ struct PSBTOutput
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) return;
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
// First byte of key is the type
unsigned char type = key[0];
@@ -527,6 +541,10 @@ struct PSBTOutput
}
}
}
+
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of an output map");
+ }
}
template <typename Stream>
@@ -602,6 +620,7 @@ struct PartiallySignedTransaction
}
// Read global data
+ bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
@@ -609,7 +628,10 @@ struct PartiallySignedTransaction
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) break;
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
// First byte of key is the type
unsigned char type = key[0];
@@ -649,6 +671,10 @@ struct PartiallySignedTransaction
}
}
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of the global map");
+ }
+
// Make sure that we got an unsigned tx
if (!tx) {
throw std::ios_base::failure("No unsigned transcation was provided");
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 08ba1b1e0f..31bfd04b0f 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -8,8 +8,8 @@
#include <crypto/sha256.h>
#include <pubkey.h>
#include <script/script.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
typedef std::vector<unsigned char> valtype;
diff --git a/src/sync.cpp b/src/sync.cpp
index c9aa98dcd6..30811f5f89 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -5,7 +5,7 @@
#include <sync.h>
#include <logging.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <stdio.h>
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
index c72c062b81..5a108dcdad 100644
--- a/src/test/allocator_tests.cpp
+++ b/src/test/allocator_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <support/allocators/secure.h>
#include <test/test_bitcoin.h>
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index adffcfeef5..1ff040b077 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -13,8 +13,10 @@ BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(MoneyRangeTest)
{
BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false);
- BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(0)), true);
BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY), true);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
}
BOOST_AUTO_TEST_CASE(GetFeeTest)
@@ -23,43 +25,43 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
feeRate = CFeeRate(0);
// Must always return 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), CAmount(0));
feeRate = CFeeRate(1000);
// Must always just return the arg
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(121));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(999));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(1e3));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(9e3));
feeRate = CFeeRate(-1000);
// Must always just return -1 * arg
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(-1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(-121));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(-999));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(-1e3));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(-9e3));
feeRate = CFeeRate(123);
// Truncates the result, if not integer
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14);
- BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(1)); // Special case: returns 1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(14));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(122), CAmount(15));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(122));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(123));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(1107));
feeRate = CFeeRate(-123);
// Truncates the result, if not integer
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(-1)); // Special case: returns -1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(-1));
// check alternate constructor
feeRate = CFeeRate(1000);
@@ -67,6 +69,9 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100));
// Check full constructor
+ BOOST_CHECK(CFeeRate(CAmount(-1), 0) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(0), 0) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(1), 0) == CFeeRate(0));
// default value
BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0));
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 6b06d2e1b6..32af843bf6 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 5fc4abaf3d..f8f9b3c1a7 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -6,7 +6,7 @@
#include <base58.h>
#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <univalue.h>
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index daceea262c..0abbb682a7 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 2cdbaca7ba..c9951f4b7e 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -7,8 +7,8 @@
#include <key.h>
#include <key_io.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <string>
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
index 4941ebd483..2144202b8d 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -10,7 +10,7 @@
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 8a8e8bfdc3..c900bee199 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -13,8 +13,8 @@
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <vector>
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index f4b416c4ca..a757e06a9d 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <validation.h>
#include <test/test_bitcoin.h>
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 6f4b5ecd26..521312f1b7 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -6,7 +6,7 @@
#include <script/standard.h>
#include <uint256.h>
#include <undo.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <validation.h>
#include <consensus/validation.h>
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index a4e99d438f..e686c05165 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compressor.h>
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
#include <stdint.h>
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 713e3e2ded..f3fd83a0cc 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -11,7 +11,7 @@
#include <crypto/hmac_sha256.h>
#include <crypto/hmac_sha512.h>
#include <random.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <vector>
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 52bbe96b96..97cf5ed345 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -11,7 +11,7 @@
#include <pow.h>
#include <script/sign.h>
#include <serialize.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <test/test_bitcoin.h>
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index e739b84a48..57e4b067c0 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -9,7 +9,7 @@
#include <test/test_bitcoin.h>
#include <boost/test/unit_test.hpp>
#include <script/descriptor.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
namespace {
@@ -43,9 +43,12 @@ std::string MaybeUseHInsteadOfApostrophy(std::string ret)
return ret;
}
-void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts)
+const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
+
+void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
FlatSigningProvider keys_priv, keys_pub;
+ std::set<std::vector<uint32_t>> left_paths = paths;
// Check that parsing succeeds.
auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv);
@@ -84,7 +87,7 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
for (size_t i = 0; i < max; ++i) {
const auto& ref = scripts[(flags & RANGE) ? i : 0];
for (int t = 0; t < 2; ++t) {
- FlatSigningProvider key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
+ const FlatSigningProvider& key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
FlatSigningProvider script_provider;
std::vector<CScript> spks;
BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider));
@@ -100,9 +103,16 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv);
}
}
-
+ // Test whether the observed key path is present in the 'paths' variable (which contains expected, unobserved paths),
+ // and then remove it from that set.
+ for (const auto& origin : script_provider.origins) {
+ BOOST_CHECK_MESSAGE(paths.count(origin.second.path), "Unexpected key path: " + prv);
+ left_paths.erase(origin.second.path);
+ }
}
}
+ // Verify no expected paths remain that were not observed.
+ BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
}
}
@@ -114,7 +124,7 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Basic single-key compressed
Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}});
- Check("pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}});
+ Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, {{1,0x80000002UL,3,0x80000004UL}});
Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}});
Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
@@ -135,20 +145,26 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}});
// Versions with BIP32 derivations
- Check("combo(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
- Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}});
- Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}});
- Check("wpkh(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}});
- Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}});
- Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}});
+ Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, {{0}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, {{0xFFFFFFFFUL,0}});
+ Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, {{0}, {1}});
+ CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)"); // BIP 32 path element overflow
// Multisig constructions
Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
- Check("sh(multi(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}});
- Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Double key origin descriptor
+ CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Non hex fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // No public key with origin
+ CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too short fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too long fingerprint
// Check for invalid nesting of structures
CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2SH needs a script, not a key
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 7592330b10..0432ede3e0 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
#include <string>
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index 6ed0209895..fd3a6b0dec 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <hash.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <vector>
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index a0c10d8ddd..5db62f4bba 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -8,7 +8,7 @@
#include <key.h>
#include <key_io.h>
#include <script/script.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp
index 14e3c85359..c564b4eab8 100644
--- a/src/test/key_properties.cpp
+++ b/src/test/key_properties.cpp
@@ -6,8 +6,8 @@
#include <base58.h>
#include <script/script.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <string>
#include <vector>
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 61db70decb..91cafd05d9 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -7,8 +7,8 @@
#include <key_io.h>
#include <script/script.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <string>
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 0e15464fd9..db38c9623c 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -4,7 +4,7 @@
#include <policy/policy.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 3eb8aa14fd..a7074a5e43 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -15,8 +15,8 @@
#include <script/standard.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
@@ -92,8 +92,8 @@ static CBlockIndex CreateBlockIndex(int nHeight)
static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- LOCK(mempool.cs);
- return CheckSequenceLocks(tx, flags);
+ LOCK(::mempool.cs);
+ return CheckSequenceLocks(::mempool, tx, flags);
}
// Test suite for ancestor feerate transaction selection.
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 35a143957e..213afed730 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -11,7 +11,7 @@
#include <net.h>
#include <netbase.h>
#include <chainparams.h>
-#include <util.h>
+#include <util/system.h>
#include <memory>
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 8072eb922d..0d557cff13 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -4,7 +4,7 @@
#include <netbase.h>
#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <string>
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 2022ed6659..51668cbe64 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -6,7 +6,7 @@
#include <policy/fees.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 1ac9adc740..f788c34e05 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -6,7 +6,7 @@
#include <chainparams.h>
#include <pow.h>
#include <random.h>
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 7fbf37e7fb..1c70fdcce6 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -10,8 +10,8 @@
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <test/test_bitcoin.h>
#include <rpc/server.h>
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index e6905457bb..c329844341 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -11,8 +11,8 @@
#include <serialize.h>
#include <streams.h>
#include <test/test_bitcoin.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <iostream>
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index c0754618fb..552bd1ab03 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
-#include <util.h>
+#include <util/system.h>
#include <test/test_bitcoin.h>
#include <vector>
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index c527ad448c..9978c71661 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -19,7 +19,7 @@
#include <script/sign.h>
#include <script/script_error.h>
#include <script/standard.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <map>
#include <string>
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index 2a160b9988..43e025c58f 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -5,8 +5,8 @@
#include <index/txindex.h>
#include <script/standard.h>
#include <test/test_bitcoin.h>
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 2bf835a756..506a60d173 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -12,7 +12,7 @@
#include <script/standard.h>
#include <script/sign.h>
#include <test/test_bitcoin.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <core_io.h>
#include <keystore.h>
#include <policy/policy.h>
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index c74eb7531a..ff19b12a9c 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -2,13 +2,13 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <clientversion.h>
#include <primitives/transaction.h>
#include <sync.h>
-#include <utilstrencodings.h>
-#include <utilmoneystr.h>
+#include <util/strencodings.h>
+#include <util/moneystr.h>
#include <test/test_bitcoin.h>
#include <stdint.h>
diff --git a/src/timedata.cpp b/src/timedata.cpp
index 291111feb2..9c022c9ad1 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -11,8 +11,8 @@
#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <warnings.h>
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index c88f61f1ec..229cc7d553 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -4,10 +4,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <torcontrol.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <netbase.h>
#include <net.h>
-#include <util.h>
+#include <util/system.h>
#include <crypto/hmac_sha256.h>
#include <vector>
diff --git a/src/txdb.cpp b/src/txdb.cpp
index cbea550739..8447352c54 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -11,7 +11,7 @@
#include <pow.h>
#include <shutdown.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <ui_interface.h>
#include <stdint.h>
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 3ad93342c4..68f47d5cce 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -14,9 +14,9 @@
#include <reverse_iterator.h>
#include <streams.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/time.h>
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, unsigned int _entryHeight,
@@ -498,7 +498,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
const CTransaction& tx = it->GetTx();
LockPoints lp = it->GetLockPoints();
bool validLP = TestLockPointValidity(&lp);
- if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) {
+ if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(*this, tx, flags, &lp, validLP)) {
// Note if CheckSequenceLocks fails the LockPoints may still be invalid
// So it's critical that we remove the tx and not depend on the LockPoints.
txToRemove.insert(it);
diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp
index 22b4768059..947d7e2308 100644
--- a/src/ui_interface.cpp
+++ b/src/ui_interface.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <boost/signals2/last_value.hpp>
#include <boost/signals2/signal.hpp>
diff --git a/src/uint256.cpp b/src/uint256.cpp
index e513dc1de7..d9da668036 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -5,7 +5,7 @@
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <stdio.h>
#include <string.h>
@@ -29,7 +29,7 @@ void base_blob<BITS>::SetHex(const char* psz)
memset(data, 0, sizeof(data));
// skip leading spaces
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
// skip 0x
diff --git a/src/utilmemory.h b/src/util/memory.h
index e71fe92284..15ecf8f80d 100644
--- a/src/utilmemory.h
+++ b/src/util/memory.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_UTILMEMORY_H
-#define BITCOIN_UTILMEMORY_H
+#ifndef BITCOIN_UTIL_MEMORY_H
+#define BITCOIN_UTIL_MEMORY_H
#include <memory>
#include <utility>
diff --git a/src/utilmoneystr.cpp b/src/util/moneystr.cpp
index 326ef9b27a..4c4de7b729 100644
--- a/src/utilmoneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -3,11 +3,11 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
#include <primitives/transaction.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
std::string FormatMoney(const CAmount& n)
{
@@ -41,7 +41,7 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
std::string strWhole;
int64_t nUnits = 0;
const char* p = pszIn;
- while (isspace(*p))
+ while (IsSpace(*p))
p++;
for (; *p; p++)
{
@@ -56,14 +56,14 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
}
break;
}
- if (isspace(*p))
+ if (IsSpace(*p))
break;
if (!isdigit(*p))
return false;
strWhole.insert(strWhole.end(), *p);
}
for (; *p; p++)
- if (!isspace(*p))
+ if (!IsSpace(*p))
return false;
if (strWhole.size() > 10) // guard against 63 bit overflow
return false;
diff --git a/src/utilmoneystr.h b/src/util/moneystr.h
index 67579adb77..9133f46d5d 100644
--- a/src/utilmoneystr.h
+++ b/src/util/moneystr.h
@@ -6,8 +6,8 @@
/**
* Money parsing/formatting utilities.
*/
-#ifndef BITCOIN_UTILMONEYSTR_H
-#define BITCOIN_UTILMONEYSTR_H
+#ifndef BITCOIN_UTIL_MONEYSTR_H
+#define BITCOIN_UTIL_MONEYSTR_H
#include <stdint.h>
#include <string>
@@ -21,4 +21,4 @@ std::string FormatMoney(const CAmount& n);
bool ParseMoney(const std::string& str, CAmount& nRet);
bool ParseMoney(const char* pszIn, CAmount& nRet);
-#endif // BITCOIN_UTILMONEYSTR_H
+#endif // BITCOIN_UTIL_MONEYSTR_H
diff --git a/src/utilstrencodings.cpp b/src/util/strencodings.cpp
index 4940267bae..2a2df43337 100644
--- a/src/utilstrencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <tinyformat.h>
@@ -20,6 +20,7 @@ static const std::string SAFE_CHARS[] =
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
+ CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
};
std::string SanitizeString(const std::string& str, int rule)
@@ -85,7 +86,7 @@ std::vector<unsigned char> ParseHex(const char* psz)
std::vector<unsigned char> vch;
while (true)
{
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
signed char c = HexDigit(*psz++);
if (c == (signed char)-1)
@@ -266,7 +267,7 @@ static bool ParsePrechecks(const std::string& str)
{
if (str.empty()) // No empty string allowed
return false;
- if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
+ if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
return false;
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
return false;
diff --git a/src/utilstrencodings.h b/src/util/strencodings.h
index 846a3917a2..87ccf40a1b 100644
--- a/src/utilstrencodings.h
+++ b/src/util/strencodings.h
@@ -6,8 +6,8 @@
/**
* Utilities for converting data from/to strings.
*/
-#ifndef BITCOIN_UTILSTRENCODINGS_H
-#define BITCOIN_UTILSTRENCODINGS_H
+#ifndef BITCOIN_UTIL_STRENCODINGS_H
+#define BITCOIN_UTIL_STRENCODINGS_H
#include <stdint.h>
#include <string>
@@ -25,6 +25,7 @@ enum SafeChars
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
+ SAFE_CHARS_URI, //!< Chars allowed in URIs (RFC 3986)
};
/**
@@ -72,6 +73,21 @@ constexpr bool IsDigit(char c)
}
/**
+ * Tests if the given character is a whitespace character. The whitespace characters
+ * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
+ * tab ('\t'), and vertical tab ('\v').
+ *
+ * This function is locale independent. Under the C locale this function gives the
+ * same result as std::isspace.
+ *
+ * @param[in] c character to test
+ * @return true if the argument is a whitespace character; otherwise false
+ */
+constexpr inline bool IsSpace(char c) noexcept {
+ return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
+}
+
+/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
@@ -230,4 +246,4 @@ constexpr unsigned char ToUpper(unsigned char c)
*/
std::string Capitalize(std::string str);
-#endif // BITCOIN_UTILSTRENCODINGS_H
+#endif // BITCOIN_UTIL_STRENCODINGS_H
diff --git a/src/util.cpp b/src/util/system.cpp
index 6479b9b9ce..4f5dd2d6e9 100644
--- a/src/util.cpp
+++ b/src/util/system.cpp
@@ -3,12 +3,12 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <chainparamsbase.h>
#include <random.h>
#include <serialize.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <stdarg.h>
diff --git a/src/util.h b/src/util/system.h
index fa6d2cd489..5634b8dd61 100644
--- a/src/util.h
+++ b/src/util/system.h
@@ -7,8 +7,8 @@
* Server/client environment: argument handling, config file parsing,
* thread wrappers, startup time
*/
-#ifndef BITCOIN_UTIL_H
-#define BITCOIN_UTIL_H
+#ifndef BITCOIN_UTIL_SYSTEM_H
+#define BITCOIN_UTIL_SYSTEM_H
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
@@ -19,8 +19,8 @@
#include <logging.h>
#include <sync.h>
#include <tinyformat.h>
-#include <utilmemory.h>
-#include <utiltime.h>
+#include <util/memory.h>
+#include <util/time.h>
#include <atomic>
#include <exception>
@@ -379,4 +379,4 @@ private:
} // namespace util
-#endif // BITCOIN_UTIL_H
+#endif // BITCOIN_UTIL_SYSTEM_H
diff --git a/src/utiltime.cpp b/src/util/time.cpp
index 908791da48..83a7937d8f 100644
--- a/src/utiltime.cpp
+++ b/src/util/time.cpp
@@ -7,7 +7,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <utiltime.h>
+#include <util/time.h>
#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
diff --git a/src/utiltime.h b/src/util/time.h
index c3e3da3014..f2e2747434 100644
--- a/src/utiltime.h
+++ b/src/util/time.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_UTILTIME_H
-#define BITCOIN_UTILTIME_H
+#ifndef BITCOIN_UTIL_TIME_H
+#define BITCOIN_UTIL_TIME_H
#include <stdint.h>
#include <string>
@@ -35,4 +35,4 @@ std::string FormatISO8601DateTime(int64_t nTime);
std::string FormatISO8601Date(int64_t nTime);
std::string FormatISO8601Time(int64_t nTime);
-#endif // BITCOIN_UTILTIME_H
+#endif // BITCOIN_UTIL_TIME_H
diff --git a/src/validation.cpp b/src/validation.cpp
index 458458d85d..241957878e 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -35,9 +35,9 @@
#include <txmempool.h>
#include <ui_interface.h>
#include <undo.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -361,10 +361,10 @@ bool TestLockPointValidity(const LockPoints* lp)
return true;
}
-bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool useExistingLockPoints)
+bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp, bool useExistingLockPoints)
{
AssertLockHeld(cs_main);
- AssertLockHeld(mempool.cs);
+ AssertLockHeld(pool.cs);
CBlockIndex* tip = chainActive.Tip();
assert(tip != nullptr);
@@ -387,7 +387,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
}
else {
// pcoinsTip contains the UTXO set for chainActive.Tip()
- CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool);
+ CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool);
std::vector<int> prevheights;
prevheights.resize(tx.vin.size());
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
@@ -679,7 +679,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// be mined yet.
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
// CoinsViewCache instead of create its own
- if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
+ if (!CheckSequenceLocks(pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");
CAmount nFees = 0;
@@ -918,7 +918,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack.
- unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(chainActive.Tip(), Params().GetConsensus());
+ unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(chainActive.Tip(), chainparams.GetConsensus());
if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, currentBlockScriptVerifyFlags, true, txdata)) {
return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed against latest-block but not STANDARD flags %s, %s",
__func__, hash.ToString(), FormatStateMessage(state));
@@ -4766,6 +4766,9 @@ bool DumpMempool()
std::map<uint256, CAmount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
+ static Mutex dump_mutex;
+ LOCK(dump_mutex);
+
{
LOCK(mempool.cs);
for (const auto &i : mempool.mapDeltas) {
diff --git a/src/validation.h b/src/validation.h
index 1034ba4665..3e98ebc866 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -257,7 +257,7 @@ bool LoadGenesisBlock(const CChainParams& chainparams);
* initializing state if we're running with -reindex. */
bool LoadBlockIndex(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Update the chain tip based on database information. */
-bool LoadChainTip(const CChainParams& chainparams);
+bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Unload database information */
void UnloadBlockIndex();
/** Run an instance of the script checking thread */
@@ -347,7 +347,7 @@ bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_mai
*
* See consensus/consensus.h for flag definitions.
*/
-bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Closure representing one script verification
@@ -436,7 +436,7 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash)
}
/** Find the last common block between the parameter chain and a locator. */
-CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
+CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Mark a block as precious and reorganize.
*
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index e25eca2368..214a9ffba9 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -8,7 +8,7 @@
#include <primitives/block.h>
#include <scheduler.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <list>
diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp
index 645981faa4..87d2c4f06e 100644
--- a/src/wallet/coincontrol.cpp
+++ b/src/wallet/coincontrol.cpp
@@ -4,7 +4,7 @@
#include <wallet/coincontrol.h>
-#include <util.h>
+#include <util/system.h>
void CCoinControl::SetNull()
{
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index fdeb89553b..5e955b8495 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -4,8 +4,8 @@
#include <wallet/coinselection.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <boost/optional.hpp>
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index 729e4e39b0..de320b4e9e 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -8,7 +8,7 @@
#include <crypto/sha512.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
+#include <util/system.h>
#include <string>
#include <vector>
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index a7bf89c572..74787eb5d2 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -8,7 +8,7 @@
#include <addrman.h>
#include <hash.h>
#include <protocol.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <wallet/walletutil.h>
#include <stdint.h>
@@ -20,6 +20,7 @@
#include <boost/thread.hpp>
namespace {
+
//! Make sure database has a unique fileid within the environment. If it
//! doesn't, throw an error. BDB caches do not work properly when more than one
//! open database has the same fileid (values written to one database may show
@@ -29,25 +30,19 @@ namespace {
//! (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html),
//! so bitcoin should never create different databases with the same fileid, but
//! this error can be triggered if users manually copy database files.
-void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filename, Db& db)
+void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filename, Db& db, WalletDatabaseFileId& fileid)
{
if (env.IsMock()) return;
- u_int8_t fileid[DB_FILE_ID_LEN];
- int ret = db.get_mpf()->get_fileid(fileid);
+ int ret = db.get_mpf()->get_fileid(fileid.value);
if (ret != 0) {
throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (get_fileid failed with %d)", filename, ret));
}
- for (const auto& item : env.mapDb) {
- u_int8_t item_fileid[DB_FILE_ID_LEN];
- if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 &&
- memcmp(fileid, item_fileid, sizeof(fileid)) == 0) {
- const char* item_filename = nullptr;
- item.second->get_dbname(&item_filename, nullptr);
+ for (const auto& item : env.m_fileids) {
+ if (fileid == item.second && &fileid != &item.second) {
throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (duplicates fileid %s from %s)", filename,
- HexStr(std::begin(item_fileid), std::end(item_fileid)),
- item_filename ? item_filename : "(unknown database)"));
+ HexStr(std::begin(item.second.value), std::end(item.second.value)), item.first));
}
}
}
@@ -56,6 +51,11 @@ CCriticalSection cs_db;
std::map<std::string, BerkeleyEnvironment> g_dbenvs GUARDED_BY(cs_db); //!< Map from directory name to open db environment.
} // namespace
+bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
+{
+ return memcmp(value, &rhs.value, sizeof(value)) == 0;
+}
+
BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
{
fs::path env_directory;
@@ -504,7 +504,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
// versions of BDB have an set_lk_exclusive method for this
// purpose, but the older version we use does not.)
for (const auto& env : g_dbenvs) {
- CheckUniqueFileid(env.second, strFilename, *pdb_temp);
+ CheckUniqueFileid(env.second, strFilename, *pdb_temp, this->env->m_fileids[strFilename]);
}
pdb = pdb_temp.release();
@@ -826,6 +826,13 @@ void BerkeleyDatabase::Flush(bool shutdown)
LOCK(cs_db);
g_dbenvs.erase(env->Directory().string());
env = nullptr;
+ } else {
+ // TODO: To avoid g_dbenvs.erase erasing the environment prematurely after the
+ // first database shutdown when multiple databases are open in the same
+ // environment, should replace raw database `env` pointers with shared or weak
+ // pointers, or else separate the database and environment shutdowns so
+ // environments can be shut down after databases.
+ env->m_fileids.erase(strFile);
}
}
}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 467ed13b45..8f96483a18 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -11,13 +11,14 @@
#include <serialize.h>
#include <streams.h>
#include <sync.h>
-#include <util.h>
+#include <util/system.h>
#include <version.h>
#include <atomic>
#include <map>
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
#include <db_cxx.h>
@@ -25,6 +26,11 @@
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
static const bool DEFAULT_WALLET_PRIVDB = true;
+struct WalletDatabaseFileId {
+ u_int8_t value[DB_FILE_ID_LEN];
+ bool operator==(const WalletDatabaseFileId& rhs) const;
+};
+
class BerkeleyEnvironment
{
private:
@@ -38,6 +44,7 @@ public:
std::unique_ptr<DbEnv> dbenv;
std::map<std::string, int> mapFileUseCount;
std::map<std::string, Db*> mapDb;
+ std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
std::condition_variable_any m_db_in_use;
BerkeleyEnvironment(const fs::path& env_directory);
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 677bf74b5d..5eb70cd7a5 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -12,8 +12,8 @@
#include <policy/rbf.h>
#include <validation.h> //for mempool access
#include <txmempool.h>
-#include <utilmoneystr.h>
-#include <util.h>
+#include <util/moneystr.h>
+#include <util/system.h>
#include <net.h>
//! Check whether transaction has descendant in wallet or mempool, or has been
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index d620e25f2b..9e2984ff05 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -7,7 +7,7 @@
#include <policy/policy.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 46983642f0..220780c96c 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -8,8 +8,8 @@
#include <net.h>
#include <scheduler.h>
#include <outputtype.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <validation.h>
#include <walletinitinterface.h>
#include <wallet/rpcwallet.h>
@@ -211,15 +211,15 @@ bool WalletInit::Verify() const
std::set<fs::path> wallet_paths;
for (const auto& wallet_file : wallet_files) {
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
+ WalletLocation location(wallet_file);
- if (!wallet_paths.insert(wallet_path).second) {
+ if (!wallet_paths.insert(location.GetPath()).second) {
return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
}
std::string error_string;
std::string warning_string;
- bool verify_success = CWallet::Verify(wallet_file, salvage_wallet, error_string, warning_string);
+ bool verify_success = CWallet::Verify(location, salvage_wallet, error_string, warning_string);
if (!error_string.empty()) InitError(error_string);
if (!warning_string.empty()) InitWarning(warning_string);
if (!verify_success) return false;
@@ -236,7 +236,7 @@ bool WalletInit::Open() const
}
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
- std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(WalletLocation(walletFile));
if (!pwallet) {
return false;
}
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 92457c4644..2a4cf0147e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -9,8 +9,8 @@
#include <script/script.h>
#include <script/standard.h>
#include <sync.h>
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <wallet/wallet.h>
#include <merkleblock.h>
#include <core_io.h>
@@ -808,29 +808,24 @@ UniValue dumpwallet(const JSONRPCRequest& request)
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
try {
- bool success = false;
-
- // Required fields.
+ // First ensure scriptPubKey has either a script or JSON with "address" string
const UniValue& scriptPubKey = data["scriptPubKey"];
-
- // Should have script or JSON with "address".
- if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey");
+ bool isScript = scriptPubKey.getType() == UniValue::VSTR;
+ if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string");
}
+ const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
// Optional fields.
const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
+ const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : "";
const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
- const std::string& label = data.exists("label") && !internal ? data["label"].get_str() : "";
-
- bool isScript = scriptPubKey.getType() == UniValue::VSTR;
- bool isP2SH = strRedeemScript.length() > 0;
- const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
+ const std::string& label = data.exists("label") ? data["label"].get_str() : "";
- // Parse the output.
+ // Generate the script and destination for the scriptPubKey provided
CScript script;
CTxDestination dest;
@@ -854,35 +849,38 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
// Watchonly and private keys
if (watchOnly && keys.size()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Watch-only addresses should not include private keys");
}
- // Internal + Label
+ // Internal addresses should not have a label
if (internal && data.exists("label")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
}
- // Keys / PubKeys size check.
- if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey
- throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address");
+ // Force users to provide the witness script in its field rather than redeemscript
+ if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WSH addresses have an empty redeemscript. Please provide the witnessscript instead.");
}
- // Invalid P2SH redeemScript
- if (isP2SH && !IsHex(strRedeemScript)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script");
- }
-
- // Process. //
+ CScript scriptpubkey_script = script;
+ CTxDestination scriptpubkey_dest = dest;
+ bool allow_p2wpkh = true;
// P2SH
- if (isP2SH) {
+ if (!strRedeemScript.empty() && script.IsPayToScriptHash()) {
+ // Check the redeemScript is valid
+ if (!IsHex(strRedeemScript)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script: must be hex string");
+ }
+
// Import redeem script.
std::vector<unsigned char> vData(ParseHex(strRedeemScript));
CScript redeemScript = CScript(vData.begin(), vData.end());
+ CScriptID redeem_id(redeemScript);
- // Invalid P2SH address
- if (!script.IsPayToScriptHash()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
+ // Check that the redeemScript and scriptPubKey match
+ if (GetScriptForDestination(redeem_id) != script) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The redeemScript does not match the scriptPubKey");
}
pwallet->MarkDirty();
@@ -891,103 +889,83 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- CScriptID redeem_id(redeemScript);
if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- CScript redeemDestination = GetScriptForDestination(redeem_id);
+ // Now set script to the redeemScript so we parse the inner script as P2WSH or P2WPKH below
+ script = redeemScript;
+ ExtractDestination(script, dest);
+ }
- if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
+ // (P2SH-)P2WSH
+ if (!witness_script_hex.empty() && script.IsPayToWitnessScriptHash()) {
+ if (!IsHex(witness_script_hex)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script: must be hex string");
}
- pwallet->MarkDirty();
+ // Generate the scripts
+ std::vector<unsigned char> witness_script_parsed(ParseHex(witness_script_hex));
+ CScript witness_script = CScript(witness_script_parsed.begin(), witness_script_parsed.end());
+ CScriptID witness_id(witness_script);
- if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ // Check that the witnessScript and scriptPubKey match
+ if (GetScriptForDestination(WitnessV0ScriptHash(witness_script)) != script) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The witnessScript does not match the scriptPubKey or redeemScript");
}
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
+ // Add the witness script as watch only only if it is not for P2SH-P2WSH
+ if (!scriptpubkey_script.IsPayToScriptHash() && !pwallet->AddWatchOnly(witness_script, timestamp)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- // Import private keys.
- if (keys.size()) {
- for (size_t i = 0; i < keys.size(); i++) {
- const std::string& privkey = keys[i].get_str();
-
- CKey key = DecodeSecret(privkey);
-
- if (!key.IsValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
- }
-
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
-
- CKeyID vchAddress = pubkey.GetID();
- pwallet->MarkDirty();
- pwallet->SetAddressBook(vchAddress, label, "receive");
-
- if (pwallet->HaveKey(vchAddress)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
- }
-
- pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ if (!pwallet->HaveCScript(witness_id) && !pwallet->AddCScript(witness_script)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2wsh witnessScript to wallet");
+ }
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
- }
+ // Now set script to the witnessScript so we parse the inner script as P2PK or P2PKH below
+ script = witness_script;
+ ExtractDestination(script, dest);
+ allow_p2wpkh = false; // P2WPKH cannot be embedded in P2WSH
+ }
- pwallet->UpdateTimeFirstKey(timestamp);
- }
+ // (P2SH-)P2PK/P2PKH/P2WPKH
+ if (dest.type() == typeid(CKeyID) || dest.type() == typeid(WitnessV0KeyHash)) {
+ if (!allow_p2wpkh && dest.type() == typeid(WitnessV0KeyHash)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WPKH cannot be embedded in P2WSH");
}
-
- success = true;
- } else {
- // Import public keys.
- if (pubKeys.size() && keys.size() == 0) {
+ if (keys.size() > 1 || pubKeys.size() > 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "More than one key given for one single-key address");
+ }
+ CPubKey pubkey;
+ if (keys.size()) {
+ pubkey = DecodeSecret(keys[0].get_str()).GetPubKey();
+ }
+ if (pubKeys.size()) {
const std::string& strPubKey = pubKeys[0].get_str();
-
if (!IsHex(strPubKey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
}
-
- std::vector<unsigned char> vData(ParseHex(strPubKey));
- CPubKey pubKey(vData.begin(), vData.end());
-
- if (!pubKey.IsFullyValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
- }
-
- CTxDestination pubkey_dest = pubKey.GetID();
-
- // Consistency check.
- if (!(pubkey_dest == dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
-
- CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
-
- if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
+ std::vector<unsigned char> vData(ParseHex(pubKeys[0].get_str()));
+ CPubKey pubkey_temp(vData.begin(), vData.end());
+ if (pubkey.size() && pubkey_temp != pubkey) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key does not match public key for address");
}
-
- pwallet->MarkDirty();
-
- if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ pubkey = pubkey_temp;
+ }
+ if (pubkey.size() > 0) {
+ if (!pubkey.IsFullyValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
}
- // add to address book or update label
- if (IsValidDestination(pubkey_dest)) {
- pwallet->SetAddressBook(pubkey_dest, label, "receive");
+ // Check the key corresponds to the destination given
+ std::vector<CTxDestination> destinations = GetAllDestinationsForKey(pubkey);
+ if (std::find(destinations.begin(), destinations.end(), dest) == destinations.end()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Key does not match address destination");
}
- // TODO Is this necessary?
- CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey);
+ // This is necessary to force the wallet to import the pubKey
+ CScript scriptRawPubKey = GetScriptForRawPubKey(pubkey);
if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -998,73 +976,61 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
-
- success = true;
}
+ }
- // Import private keys.
- if (keys.size()) {
- const std::string& strPrivkey = keys[0].get_str();
-
- // Checks.
- CKey key = DecodeSecret(strPrivkey);
-
- if (!key.IsValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
- }
-
- CPubKey pubKey = key.GetPubKey();
- assert(key.VerifyPubKey(pubKey));
-
- CTxDestination pubkey_dest = pubKey.GetID();
+ // Import the address
+ if (::IsMine(*pwallet, scriptpubkey_script) == ISMINE_SPENDABLE) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
+ }
- // Consistency check.
- if (!(pubkey_dest == dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
+ pwallet->MarkDirty();
- CKeyID vchAddress = pubKey.GetID();
- pwallet->MarkDirty();
- pwallet->SetAddressBook(vchAddress, label, "receive");
+ if (!pwallet->AddWatchOnly(scriptpubkey_script, timestamp)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ }
- if (pwallet->HaveKey(vchAddress)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
+ if (!watchOnly && !pwallet->HaveCScript(CScriptID(scriptpubkey_script)) && !pwallet->AddCScript(scriptpubkey_script)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding scriptPubKey script to wallet");
+ }
- pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ // add to address book or update label
+ if (IsValidDestination(scriptpubkey_dest)) {
+ pwallet->SetAddressBook(scriptpubkey_dest, label, "receive");
+ }
- if (!pwallet->AddKeyPubKey(key, pubKey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
- }
+ // Import private keys.
+ for (size_t i = 0; i < keys.size(); i++) {
+ const std::string& strPrivkey = keys[i].get_str();
- pwallet->UpdateTimeFirstKey(timestamp);
+ // Checks.
+ CKey key = DecodeSecret(strPrivkey);
- success = true;
+ if (!key.IsValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
}
- // Import scriptPubKey only.
- if (pubKeys.size() == 0 && keys.size() == 0) {
- if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
+ CPubKey pubKey = key.GetPubKey();
+ assert(key.VerifyPubKey(pubKey));
- pwallet->MarkDirty();
+ CKeyID vchAddress = pubKey.GetID();
+ pwallet->MarkDirty();
- if (!pwallet->AddWatchOnly(script, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
+ if (pwallet->HaveKey(vchAddress)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
+ }
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
- }
+ pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
- success = true;
+ if (!pwallet->AddKeyPubKey(key, pubKey)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
+
+ pwallet->UpdateTimeFirstKey(timestamp);
}
UniValue result = UniValue(UniValue::VOBJ);
- result.pushKV("success", UniValue(success));
+ result.pushKV("success", UniValue(true));
return result;
} catch (const UniValue& e) {
UniValue result = UniValue(UniValue::VOBJ);
@@ -1117,7 +1083,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
" 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
" creation time of all keys being imported by the importmulti call will be scanned.\n"
- " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH address or a P2SH scriptPubKey\n"
+ " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey\n"
+ " \"witnessscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey\n"
" \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n"
" \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n"
" \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n"
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index a3f5f8b211..45d4b5bceb 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -23,8 +23,8 @@
#include <script/sign.h>
#include <shutdown.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
#include <wallet/rpcwallet.h>
@@ -982,131 +982,6 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
return result;
}
-class Witnessifier : public boost::static_visitor<bool>
-{
-public:
- CWallet * const pwallet;
- CTxDestination result;
- bool already_witness;
-
- explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {}
-
- bool operator()(const CKeyID &keyID) {
- if (pwallet) {
- CScript basescript = GetScriptForDestination(keyID);
- CScript witscript = GetScriptForWitness(basescript);
- if (!IsSolvable(*pwallet, witscript)) {
- return false;
- }
- return ExtractDestination(witscript, result);
- }
- return false;
- }
-
- bool operator()(const CScriptID &scriptID) {
- CScript subscript;
- if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
- int witnessversion;
- std::vector<unsigned char> witprog;
- if (subscript.IsWitnessProgram(witnessversion, witprog)) {
- ExtractDestination(subscript, result);
- already_witness = true;
- return true;
- }
- CScript witscript = GetScriptForWitness(subscript);
- if (!IsSolvable(*pwallet, witscript)) {
- return false;
- }
- return ExtractDestination(witscript, result);
- }
- return false;
- }
-
- bool operator()(const WitnessV0KeyHash& id)
- {
- already_witness = true;
- result = id;
- return true;
- }
-
- bool operator()(const WitnessV0ScriptHash& id)
- {
- already_witness = true;
- result = id;
- return true;
- }
-
- template<typename T>
- bool operator()(const T& dest) { return false; }
-};
-
-static UniValue addwitnessaddress(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- {
- std::string msg = "addwitnessaddress \"address\" ( p2sh )\n"
- "\nDEPRECATED: set the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n"
- "Add a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n"
- "It returns the witness script.\n"
-
- "\nArguments:\n"
- "1. \"address\" (string, required) An address known to the wallet\n"
- "2. p2sh (bool, optional, default=true) Embed inside P2SH\n"
-
- "\nResult:\n"
- "\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n"
- "}\n"
- ;
- throw std::runtime_error(msg);
- }
-
- if (!IsDeprecatedRPCEnabled("addwitnessaddress")) {
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "addwitnessaddress is deprecated and will be fully removed in v0.17. "
- "To use addwitnessaddress in v0.16, restart bitcoind with -deprecatedrpc=addwitnessaddress.\n"
- "Projects should transition to using the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n");
- }
-
- CTxDestination dest = DecodeDestination(request.params[0].get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- }
-
- bool p2sh = true;
- if (!request.params[1].isNull()) {
- p2sh = request.params[1].get_bool();
- }
-
- Witnessifier w(pwallet);
- bool ret = boost::apply_visitor(w, dest);
- if (!ret) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
- }
-
- CScript witprogram = GetScriptForDestination(w.result);
-
- if (p2sh) {
- w.result = CScriptID(witprogram);
- }
-
- if (w.already_witness) {
- if (!(dest == w.result)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types");
- }
- } else {
- pwallet->AddCScript(witprogram); // Implicit for single-key now, but necessary for multisig and for compatibility with older software
- pwallet->SetAddressBook(w.result, "", "receive");
- }
-
- return EncodeDestination(w.result);
-}
-
struct tallyitem
{
CAmount nAmount;
@@ -1121,7 +996,7 @@ struct tallyitem
}
};
-static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1928,13 +1803,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
}
-static void LockWallet(CWallet* pWallet)
-{
- LOCK(pWallet->cs_wallet);
- pWallet->nRelockTime = 0;
- pWallet->Lock();
-}
-
static UniValue walletpassphrase(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -2004,7 +1872,18 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime;
- RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), std::bind(LockWallet, pwallet), nSleepTime);
+
+ // Keep a weak pointer to the wallet so that it is possible to unload the
+ // wallet before the following callback is called. If a valid shared pointer
+ // is acquired in the callback then the wallet is still loaded.
+ std::weak_ptr<CWallet> weak_wallet = wallet;
+ RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
+ if (auto shared_wallet = weak_wallet.lock()) {
+ LOCK(shared_wallet->cs_wallet);
+ shared_wallet->Lock();
+ shared_wallet->nRelockTime = 0;
+ }
+ }, nSleepTime);
return NullUniValue;
}
@@ -2526,26 +2405,26 @@ static UniValue loadwallet(const JSONRPCRequest& request)
+ HelpExampleCli("loadwallet", "\"test.dat\"")
+ HelpExampleRpc("loadwallet", "\"test.dat\"")
);
- std::string wallet_file = request.params[0].get_str();
+
+ WalletLocation location(request.params[0].get_str());
std::string error;
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
- if (fs::symlink_status(wallet_path).type() == fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + wallet_file + " not found.");
- } else if (fs::is_directory(wallet_path)) {
+ if (!location.Exists()) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + location.GetName() + " not found.");
+ } else if (fs::is_directory(location.GetPath())) {
// The given filename is a directory. Check that there's a wallet.dat file.
- fs::path wallet_dat_file = wallet_path / "wallet.dat";
+ fs::path wallet_dat_file = location.GetPath() / "wallet.dat";
if (fs::symlink_status(wallet_dat_file).type() == fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + wallet_file + " does not contain a wallet.dat file.");
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + location.GetName() + " does not contain a wallet.dat file.");
}
}
std::string warning;
- if (!CWallet::Verify(wallet_file, false, error, warning)) {
+ if (!CWallet::Verify(location, false, error, warning)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
}
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir()));
+ std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(location);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
}
@@ -2579,7 +2458,6 @@ static UniValue createwallet(const JSONRPCRequest& request)
+ HelpExampleRpc("createwallet", "\"testwallet\"")
);
}
- std::string wallet_name = request.params[0].get_str();
std::string error;
std::string warning;
@@ -2588,17 +2466,17 @@ static UniValue createwallet(const JSONRPCRequest& request)
disable_privatekeys = request.params[1].get_bool();
}
- fs::path wallet_path = fs::absolute(wallet_name, GetWalletDir());
- if (fs::symlink_status(wallet_path).type() != fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + wallet_name + " already exists.");
+ WalletLocation location(request.params[0].get_str());
+ if (location.Exists()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + location.GetName() + " already exists.");
}
// Wallet::Verify will check if we're trying to create a wallet with a duplication name.
- if (!CWallet::Verify(wallet_name, false, error, warning)) {
+ if (!CWallet::Verify(location, false, error, warning)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
}
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_name, fs::absolute(wallet_name, GetWalletDir()), (disable_privatekeys ? (uint64_t)WALLET_FLAG_DISABLE_PRIVATE_KEYS : 0));
+ std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(location, (disable_privatekeys ? (uint64_t)WALLET_FLAG_DISABLE_PRIVATE_KEYS : 0));
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
}
@@ -3321,6 +3199,12 @@ UniValue generate(const JSONRPCRequest& request)
);
}
+ if (!IsDeprecatedRPCEnabled("generate")) {
+ throw JSONRPCError(RPC_METHOD_DEPRECATED, "The wallet generate rpc method is deprecated and will be fully removed in v0.19. "
+ "To use generate in v0.18, restart bitcoind with -deprecatedrpc=generate.\n"
+ "Clients should transition to using the node rpc method generatetoaddress\n");
+ }
+
int num_generate = request.params[0].get_int();
uint64_t max_tries = 1000000;
if (!request.params[1].isNull()) {
@@ -3570,8 +3454,10 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" \"address\" : \"address\", (string) The bitcoin address validated\n"
" \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
+ " \"solvable\" : true|false, (boolean) If the address is solvable by the wallet\n"
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
" \"isscript\" : true|false, (boolean) If the key is a script\n"
+ " \"ischange\" : true|false, (boolean) If the address was used for change output\n"
" \"iswitness\" : true|false, (boolean) If the address is a witness address\n"
" \"witness_version\" : version (numeric, optional) The version number of the witness program\n"
" \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n"
@@ -3624,11 +3510,13 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
isminetype mine = IsMine(*pwallet, dest);
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
+ ret.pushKV("solvable", IsSolvable(*pwallet, scriptPubKey));
UniValue detail = DescribeWalletAddress(pwallet, dest);
ret.pushKVs(detail);
if (pwallet->mapAddressBook.count(dest)) {
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
}
+ ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
const CKeyMetadata* meta = nullptr;
CKeyID key_id = GetKeyForDestination(*pwallet, dest);
if (!key_id.IsNull()) {
@@ -4091,7 +3979,6 @@ static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
- { "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 21857df081..a9464870ea 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -28,7 +28,7 @@ std::vector<std::unique_ptr<CWalletTx>> wtxn;
typedef std::set<CInputCoin> CoinSet;
static std::vector<COutput> vCoins;
-static CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static CWallet testWallet(WalletLocation(), WalletDatabase::CreateDummy());
static CAmount balance = 0;
CoinEligibilityFilter filter_standard(1, 6, 0);
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 526f2d983f..cb1ad25461 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -4,7 +4,7 @@
#include <key_io.h>
#include <script/sign.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <univalue.h>
@@ -17,6 +17,8 @@ BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup)
BOOST_AUTO_TEST_CASE(psbt_updater_test)
{
+ LOCK(m_wallet.cs_wallet);
+
// Create prevtxs and add to wallet
CDataStream s_prev_tx1(ParseHex("0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000"), SER_NETWORK, PROTOCOL_VERSION);
CTransactionRef prev_tx1;
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index f193d5c41d..ae7092fa89 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <wallet/crypter.h>
#include <vector>
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index de59b60349..d42209ab15 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -6,9 +6,10 @@
#include <rpc/server.h>
#include <wallet/db.h>
+#include <wallet/rpcwallet.h>
WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
- TestingSetup(chainName), m_wallet("mock", WalletDatabase::CreateMock())
+ TestingSetup(chainName), m_wallet(WalletLocation(), WalletDatabase::CreateMock())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 3a8e6f751a..269a916829 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -46,7 +46,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
@@ -61,7 +61,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
@@ -73,7 +73,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is
// after.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateDummy());
AddWallet(wallet);
UniValue keys;
keys.setArray();
@@ -134,7 +134,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Import key into wallet and call dumpwallet to create backup file.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet->cs_wallet);
wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
@@ -150,7 +150,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateDummy());
JSONRPCRequest request;
request.params.setArray();
@@ -180,7 +180,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(WalletLocation(), WalletDatabase::CreateDummy());
CWalletTx wtx(&wallet, m_coinbase_txns.back());
LOCK2(cs_main, wallet.cs_wallet);
wtx.hashBlock = chainActive.Tip()->GetBlockHash();
@@ -273,7 +273,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>("mock", WalletDatabase::CreateMock());
+ wallet = MakeUnique<CWallet>(WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
AddKey(*wallet, coinbaseKey);
@@ -377,7 +377,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(WalletLocation(), WalletDatabase::CreateDummy());
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000));
CPubKey pubkey;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index afe47d986e..2ea9f45462 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -25,9 +25,8 @@
#include <shutdown.h>
#include <timedata.h>
#include <txmempool.h>
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
#include <wallet/fees.h>
-#include <wallet/walletutil.h>
#include <algorithm>
#include <assert.h>
@@ -1262,6 +1261,11 @@ CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) cons
bool CWallet::IsChange(const CTxOut& txout) const
{
+ return IsChange(txout.scriptPubKey);
+}
+
+bool CWallet::IsChange(const CScript& script) const
+{
// TODO: fix handling of 'change' outputs. The assumption is that any
// payment to a script that is ours, but is not in the address book
// is change. That assumption is likely to break when we implement multisignature
@@ -1269,10 +1273,10 @@ bool CWallet::IsChange(const CTxOut& txout) const
// a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
- if (::IsMine(*this, txout.scriptPubKey))
+ if (::IsMine(*this, script))
{
CTxDestination address;
- if (!ExtractDestination(txout.scriptPubKey, address))
+ if (!ExtractDestination(script, address))
return true;
LOCK(cs_wallet);
@@ -3821,7 +3825,7 @@ void CWallet::MarkPreSplitKeys()
}
}
-bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string)
+bool CWallet::Verify(const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string)
{
// Do some checking on wallet path. It should be either a:
//
@@ -3830,23 +3834,23 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
// 3. Path to a symlink to a directory.
// 4. For backwards compatibility, the name of a data file in -walletdir.
LOCK(cs_wallets);
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
+ const fs::path& wallet_path = location.GetPath();
fs::file_type path_type = fs::symlink_status(wallet_path).type();
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
- (path_type == fs::regular_file && fs::path(wallet_file).filename() == wallet_file))) {
+ (path_type == fs::regular_file && fs::path(location.GetName()).filename() == location.GetName()))) {
error_string = strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, "
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
- wallet_file, GetWalletDir());
+ location.GetName(), GetWalletDir());
return false;
}
// Make sure that the wallet path doesn't clash with an existing wallet path
for (auto wallet : GetWallets()) {
- if (fs::absolute(wallet->GetName(), GetWalletDir()) == wallet_path) {
- error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", wallet_file);
+ if (wallet->GetLocation().GetPath() == wallet_path) {
+ error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", location.GetName());
return false;
}
}
@@ -3856,13 +3860,13 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return false;
}
} catch (const fs::filesystem_error& e) {
- error_string = strprintf("Error loading wallet %s. %s", wallet_file, fsbridge::get_filesystem_error_message(e));
+ error_string = strprintf("Error loading wallet %s. %s", location.GetName(), fsbridge::get_filesystem_error_message(e));
return false;
}
if (salvage_wallet) {
// Recover readable keypairs:
- CWallet dummyWallet("dummy", WalletDatabase::CreateDummy());
+ CWallet dummyWallet(WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename;
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false;
@@ -3872,9 +3876,9 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
}
-std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path, uint64_t wallet_creation_flags)
+std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const WalletLocation& location, uint64_t wallet_creation_flags)
{
- const std::string& walletFile = name;
+ const std::string& walletFile = location.GetName();
// needed to restore wallet transaction meta data after -zapwallettxes
std::vector<CWalletTx> vWtx;
@@ -3882,7 +3886,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (gArgs.GetBoolArg("-zapwallettxes", false)) {
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
- std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path));
+ std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(location, WalletDatabase::Create(location.GetPath()));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DBErrors::LOAD_OK) {
InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
@@ -3896,7 +3900,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
bool fFirstRun = true;
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
- std::shared_ptr<CWallet> walletInstance(new CWallet(name, WalletDatabase::Create(path)), ReleaseWallet);
+ std::shared_ptr<CWallet> walletInstance(new CWallet(location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
@@ -4093,7 +4097,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
- LOCK(cs_main);
+ LOCK2(cs_main, walletInstance->cs_wallet);
CBlockIndex *pindexRescan = chainActive.Genesis();
if (!gArgs.GetBoolArg("-rescan", false))
@@ -4178,7 +4182,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
- LOCK(walletInstance->cs_wallet);
walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index da326517c0..74eaa09506 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -12,15 +12,15 @@
#include <streams.h>
#include <tinyformat.h>
#include <ui_interface.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <validationinterface.h>
#include <script/ismine.h>
#include <script/sign.h>
-#include <util.h>
+#include <util/system.h>
#include <wallet/crypter.h>
#include <wallet/coinselection.h>
#include <wallet/walletdb.h>
-#include <wallet/rpcwallet.h>
+#include <wallet/walletutil.h>
#include <algorithm>
#include <atomic>
@@ -460,7 +460,11 @@ public:
CAmount GetDebit(const isminefilter& filter) const;
CAmount GetCredit(const isminefilter& filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CAmount GetImmatureCredit(bool fUseCache=true) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
+ // annotation "EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)". The
+ // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
+ // having to resolve the issue of member access into incomplete type CWallet.
+ CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CAmount GetChange() const;
@@ -492,7 +496,13 @@ public:
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- std::set<uint256> GetConflicts() const;
+ // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
+ // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
+ // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
+ // resolve the issue of member access into incomplete type CWallet. Note
+ // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
+ // in place.
+ std::set<uint256> GetConflicts() const NO_THREAD_SAFETY_ANALYSIS;
};
class COutput
@@ -591,13 +601,13 @@ private:
std::mutex mutexScanning;
friend class WalletRescanReserver;
- WalletBatch *encrypted_batch = nullptr;
+ WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
//! the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion = FEATURE_BASE;
//! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
- int nWalletMaxVersion = FEATURE_BASE;
+ int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
int64_t nNextResend = 0;
int64_t nLastResend = 0;
@@ -609,9 +619,9 @@ private:
* mutated transactions where the mutant gets mined).
*/
typedef std::multimap<COutPoint, uint256> TxSpends;
- TxSpends mapTxSpends;
- void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
- void AddToSpends(const uint256& wtxid);
+ TxSpends mapTxSpends GUARDED_BY(cs_wallet);
+ void AddToSpends(const COutPoint& outpoint, const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void AddToSpends(const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Add a transaction to the wallet, or update it. pIndex and posInBlock should
@@ -632,9 +642,9 @@ private:
void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);
/* Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed */
- void MarkInputsDirty(const CTransactionRef& tx);
+ void MarkInputsDirty(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
+ void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
@@ -647,13 +657,13 @@ private:
void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::set<int64_t> setInternalKeyPool;
- std::set<int64_t> setExternalKeyPool;
+ std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_wallet);
std::set<int64_t> set_pre_split_keypool;
- int64_t m_max_keypool_index = 0;
+ int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
std::map<CKeyID, int64_t> m_pool_key_to_index;
std::atomic<uint64_t> m_wallet_flags{0};
- int64_t nTimeFirstKey = 0;
+ int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
/**
* Private version of AddWatchOnly method which does not accept a
@@ -666,12 +676,8 @@ private:
*/
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- /**
- * Wallet filename from wallet=<path> command line or config option.
- * Used in debug logs and to send RPCs to the right wallet instance when
- * more than one wallet is loaded.
- */
- std::string m_name;
+ /** Wallet location which includes wallet name (see WalletLocation). */
+ WalletLocation m_location;
/** Internal database handle. */
std::unique_ptr<WalletDatabase> database;
@@ -709,27 +715,29 @@ public:
* if they are not ours
*/
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet,
- const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
+ const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ const WalletLocation& GetLocation() const { return m_location; }
/** Get a name for this wallet for logging/debugging purposes.
*/
- const std::string& GetName() const { return m_name; }
+ const std::string& GetName() const { return m_location.GetName(); }
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void MarkPreSplitKeys();
+ void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Map from Key ID to key metadata.
- std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
+ std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_wallet);
// Map from Script ID to key metadata (for watch-only keys).
- std::map<CScriptID, CKeyMetadata> m_script_metadata;
+ std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_wallet);
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID = 0;
/** Construct wallet with specified name and database implementation. */
- CWallet(std::string name, std::unique_ptr<WalletDatabase> database) : m_name(std::move(name)), database(std::move(database))
+ CWallet(const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_location(location), database(std::move(database))
{
}
@@ -739,17 +747,17 @@ public:
encrypted_batch = nullptr;
}
- std::map<uint256, CWalletTx> mapWallet;
+ std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
- int64_t nOrderPosNext = 0;
+ int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0;
uint64_t nAccountingEntryNumber = 0;
std::map<CTxDestination, CAddressBookData> mapAddressBook;
- std::set<COutPoint> setLockedCoins;
+ std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
const CWalletTx* GetWalletTx(const uint256& hash) const;
@@ -769,7 +777,7 @@ public:
/**
* Find non-change parent output.
*/
- const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const;
+ const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Shuffle and select coins until nTargetValue is reached while avoiding
@@ -780,7 +788,7 @@ public:
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups,
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
- bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_main, cs_wallet);
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -856,7 +864,7 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
- void LoadToWallet(const CWalletTx& wtxIn);
+ void LoadToWallet(const CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void TransactionAddedToMempool(const CTransactionRef& tx) override;
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
@@ -961,6 +969,7 @@ public:
isminetype IsMine(const CTxOut& txout) const;
CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
bool IsChange(const CTxOut& txout) const;
+ bool IsChange(const CScript& script) const;
CAmount GetChange(const CTxOut& txout) const;
bool IsMine(const CTransaction& tx) const;
/** should probably be renamed to IsRelevantToMe */
@@ -1000,7 +1009,7 @@ public:
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
//! Get wallet transactions that conflict with given transaction (spend same outputs)
- std::set<uint256> GetConflicts(const uint256& txid) const;
+ std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1048,10 +1057,10 @@ public:
bool MarkReplaced(const uint256& originalHash, const uint256& newHash);
//! Verify wallet naming and perform salvage on the wallet if required
- static bool Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string);
+ static bool Verify(const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
- static std::shared_ptr<CWallet> CreateWalletFromFile(const std::string& name, const fs::path& path, uint64_t wallet_creation_flags = 0);
+ static std::shared_ptr<CWallet> CreateWalletFromFile(const WalletLocation& location, uint64_t wallet_creation_flags = 0);
/**
* Wallet post-init setup
@@ -1198,6 +1207,6 @@ public:
// Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
// be IsAllFromMe).
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false);
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
#endif // BITCOIN_WALLET_WALLET_H
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 5e85151358..09a33f252c 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -12,8 +12,8 @@
#include <protocol.h>
#include <serialize.h>
#include <sync.h>
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <wallet/wallet.h>
#include <atomic>
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index c0c9afe13e..6db4c63acb 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -4,7 +4,7 @@
#include <wallet/walletutil.h>
-#include <util.h>
+#include <util/system.h>
fs::path GetWalletDir()
{
@@ -52,12 +52,17 @@ static bool IsBerkeleyBtree(const fs::path& path)
std::vector<fs::path> ListWalletDir()
{
const fs::path wallet_dir = GetWalletDir();
+ const size_t offset = wallet_dir.string().size() + 1;
std::vector<fs::path> paths;
- for (auto it = fs::recursive_directory_iterator(wallet_dir); it != end(it); ++it) {
+ for (auto it = fs::recursive_directory_iterator(wallet_dir); it != fs::recursive_directory_iterator(); ++it) {
+ // Get wallet path relative to walletdir by removing walletdir from the wallet path.
+ // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
+ const fs::path path = it->path().string().substr(offset);
+
if (it->status().type() == fs::directory_file && IsBerkeleyBtree(it->path() / "wallet.dat")) {
// Found a directory which contains wallet.dat btree file, add it as a wallet.
- paths.emplace_back(fs::relative(it->path(), wallet_dir));
+ paths.emplace_back(path);
} else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBerkeleyBtree(it->path())) {
if (it->path().filename() == "wallet.dat") {
// Found top-level wallet.dat btree file, add top level directory ""
@@ -68,10 +73,21 @@ std::vector<fs::path> ListWalletDir()
// software will never create these files but will allow them to be
// opened in a shared database environment for backwards compatibility.
// Add it to the list of available wallets.
- paths.emplace_back(fs::relative(it->path(), wallet_dir));
+ paths.emplace_back(path);
}
}
}
return paths;
}
+
+WalletLocation::WalletLocation(const std::string& name)
+ : m_name(name)
+ , m_path(fs::absolute(name, GetWalletDir()))
+{
+}
+
+bool WalletLocation::Exists() const
+{
+ return fs::symlink_status(m_path).type() != fs::file_not_found;
+}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index 77f5ca428d..ba2f913841 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -15,4 +15,24 @@ fs::path GetWalletDir();
//! Get wallets in wallet directory.
std::vector<fs::path> ListWalletDir();
+//! The WalletLocation class provides wallet information.
+class WalletLocation final
+{
+ std::string m_name;
+ fs::path m_path;
+
+public:
+ explicit WalletLocation() {}
+ explicit WalletLocation(const std::string& name);
+
+ //! Get wallet name.
+ const std::string& GetName() const { return m_name; }
+
+ //! Get wallet absolute path.
+ const fs::path& GetPath() const { return m_path; }
+
+ //! Return whether the wallet exists.
+ bool Exists() const;
+};
+
#endif // BITCOIN_WALLET_WALLETUTIL_H
diff --git a/src/warnings.cpp b/src/warnings.cpp
index 9f10c48eef..1c6ba13f60 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -5,7 +5,7 @@
#include <sync.h>
#include <clientversion.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
CCriticalSection cs_warnings;
diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp
index 0eeef8cf1d..6a9661e3e8 100644
--- a/src/zmq/zmqabstractnotifier.cpp
+++ b/src/zmq/zmqabstractnotifier.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <zmq/zmqabstractnotifier.h>
-#include <util.h>
+#include <util/system.h>
const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM;
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 680e38bd77..6826cf62d6 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -8,7 +8,7 @@
#include <version.h>
#include <validation.h>
#include <streams.h>
-#include <util.h>
+#include <util/system.h>
void zmqError(const char *str)
{
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 280cd1642e..15d4ac1b89 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -7,7 +7,7 @@
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
-#include <util.h>
+#include <util/system.h>
#include <rpc/server.h>
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;