aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am29
-rw-r--r--src/Makefile.qt.include4
-rw-r--r--src/Makefile.test.include15
-rw-r--r--src/addrdb.cpp2
-rw-r--r--src/addrman.h2
-rw-r--r--src/arith_uint256.cpp2
-rw-r--r--src/base58.cpp2
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/bench/bench_bitcoin.cpp4
-rw-r--r--src/bench/block_assemble.cpp3
-rw-r--r--src/bench/checkqueue.cpp2
-rw-r--r--src/bench/coin_selection.cpp7
-rw-r--r--src/bench/crypto_hash.cpp3
-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.cpp12
-rw-r--r--src/blockencodings.cpp5
-rw-r--r--src/blockfilter.cpp1
-rw-r--r--src/blockfilter.h5
-rw-r--r--src/chainparams.cpp4
-rw-r--r--src/chainparamsbase.cpp4
-rw-r--r--src/coins.cpp1
-rw-r--r--src/coins.h2
-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/crypto/siphash.cpp173
-rw-r--r--src/crypto/siphash.h47
-rw-r--r--src/dbwrapper.h4
-rw-r--r--src/dummywallet.cpp10
-rw-r--r--src/hash.cpp168
-rw-r--r--src/hash.h35
-rw-r--r--src/httprpc.cpp4
-rw-r--r--src/httpserver.cpp26
-rw-r--r--src/index/base.cpp2
-rw-r--r--src/index/txindex.cpp2
-rw-r--r--src/init.cpp56
-rw-r--r--src/init.h19
-rw-r--r--src/interfaces/README.md2
-rw-r--r--src/interfaces/chain.cpp44
-rw-r--r--src/interfaces/chain.h84
-rw-r--r--src/interfaces/handler.cpp2
-rw-r--r--src/interfaces/node.cpp10
-rw-r--r--src/interfaces/wallet.cpp147
-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.h1
-rw-r--r--src/net_processing.cpp23
-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/policy/rbf.cpp2
-rw-r--r--src/primitives/block.cpp2
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/protocol.cpp4
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoingui.cpp2
-rw-r--r--src/qt/clientmodel.cpp2
-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.cpp2
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/qt/test/addressbooktests.cpp4
-rw-r--r--src/qt/test/paymentservertests.cpp4
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/test/test_main.cpp2
-rw-r--r--src/qt/test/wallettests.cpp6
-rw-r--r--src/qt/transactiondesc.cpp9
-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.cpp2
-rw-r--r--src/qt/walletmodel.cpp2
-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.cpp4
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/mining.cpp4
-rw-r--r--src/rpc/misc.cpp4
-rw-r--r--src/rpc/net.cpp4
-rw-r--r--src/rpc/protocol.cpp6
-rw-r--r--src/rpc/rawtransaction.cpp31
-rw-r--r--src/rpc/rawtransaction.h6
-rw-r--r--src/rpc/server.cpp4
-rw-r--r--src/rpc/util.cpp4
-rw-r--r--src/rpc/util.h6
-rw-r--r--src/script/descriptor.cpp4
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/script.h6
-rw-r--r--src/script/sigcache.cpp2
-rw-r--r--src/script/sign.cpp51
-rw-r--r--src/script/sign.h36
-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/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.cpp2
-rw-r--r--src/test/getarg_tests.cpp2
-rw-r--r--src/test/hash_tests.cpp3
-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.cpp4
-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.cpp4
-rw-r--r--src/test/rpc_tests.cpp7
-rw-r--r--src/test/script_tests.cpp4
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/skiplist_tests.cpp3
-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/threadsafety.h11
-rw-r--r--src/timedata.cpp4
-rw-r--r--src/torcontrol.cpp4
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txmempool.cpp6
-rw-r--r--src/txmempool.h1
-rw-r--r--src/ui_interface.cpp2
-rw-r--r--src/uint256.cpp2
-rw-r--r--src/undo.h1
-rw-r--r--src/util/bytevectorhash.cpp18
-rw-r--r--src/util/bytevectorhash.h26
-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)4
-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)3
-rw-r--r--src/util/strencodings.h (renamed from src/utilstrencodings.h)7
-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.cpp6
-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.cpp2
-rw-r--r--src/wallet/db.h2
-rw-r--r--src/wallet/feebumper.cpp27
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/init.cpp76
-rw-r--r--src/wallet/rpcdump.cpp36
-rw-r--r--src/wallet/rpcwallet.cpp264
-rw-r--r--src/wallet/rpcwallet.h2
-rw-r--r--src/wallet/test/coinselector_tests.cpp3
-rw-r--r--src/wallet/test/init_test_fixture.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.h3
-rw-r--r--src/wallet/test/init_tests.cpp14
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp8
-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_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp50
-rw-r--r--src/wallet/wallet.cpp237
-rw-r--r--src/wallet/wallet.h90
-rw-r--r--src/wallet/walletdb.cpp4
-rw-r--r--src/wallet/walletutil.cpp13
-rw-r--r--src/wallet/walletutil.h20
-rw-r--r--src/walletinitinterface.h17
-rw-r--r--src/warnings.cpp2
-rw-r--r--src/zmq/zmqabstractnotifier.cpp3
-rw-r--r--src/zmq/zmqabstractnotifier.h11
-rw-r--r--src/zmq/zmqnotificationinterface.cpp9
-rw-r--r--src/zmq/zmqpublishnotifier.cpp18
-rw-r--r--src/zmq/zmqpublishnotifier.h2
-rw-r--r--src/zmq/zmqrpc.cpp4
195 files changed, 1510 insertions, 949 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6141919007..8dd0d31839 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -125,6 +125,7 @@ BITCOIN_CORE_H = \
index/txindex.h \
indirectmap.h \
init.h \
+ interfaces/chain.h \
interfaces/handler.h \
interfaces/node.h \
interfaces/wallet.h \
@@ -183,10 +184,11 @@ BITCOIN_CORE_H = \
txmempool.h \
ui_interface.h \
undo.h \
- util.h \
- utilmemory.h \
- utilmoneystr.h \
- utiltime.h \
+ util/bytevectorhash.h \
+ util/system.h \
+ util/memory.h \
+ util/moneystr.h \
+ util/time.h \
validation.h \
validationinterface.h \
versionbits.h \
@@ -232,6 +234,7 @@ libbitcoin_server_a_SOURCES = \
httpserver.cpp \
index/base.cpp \
index/txindex.cpp \
+ interfaces/chain.cpp \
interfaces/handler.cpp \
interfaces/node.cpp \
init.cpp \
@@ -321,7 +324,9 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
crypto/sha256.cpp \
crypto/sha256.h \
crypto/sha512.cpp \
- crypto/sha512.h
+ crypto/sha512.h \
+ crypto/siphash.cpp \
+ crypto/siphash.h
if USE_ASM
crypto_libbitcoin_crypto_base_a_SOURCES += crypto/sha256_sse4.cpp
@@ -377,8 +382,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 +432,11 @@ libbitcoin_util_a_SOURCES = \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
- util.cpp \
- utilmoneystr.cpp \
- utilstrencodings.cpp \
- utiltime.cpp \
+ util/bytevectorhash.cpp \
+ util/system.cpp \
+ util/moneystr.cpp \
+ util/strencodings.cpp \
+ util/time.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
@@ -461,6 +467,7 @@ endif
bitcoind_LDADD = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 73538e8bc9..445849e3d8 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -423,6 +423,10 @@ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL)
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
if ENABLE_BIP70
qt_bitcoin_qt_LDADD += $(SSL_LIBS)
+else
+if TARGET_WINDOWS
+qt_bitcoin_qt_LDADD += $(SSL_LIBS)
+endif
endif
qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS)
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 4506d5dd6a..a31852c94f 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -169,7 +169,15 @@ CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) $(BITCOIN_T
CLEANFILES += $(CLEAN_BITCOIN_TEST)
+if TARGET_WINDOWS
bitcoin_test: $(TEST_BINARY)
+else
+if ENABLE_BENCH
+bitcoin_test: $(TEST_BINARY) $(BENCH_BINARY)
+else
+bitcoin_test: $(TEST_BINARY)
+endif
+endif
bitcoin_test_check: $(TEST_BINARY) FORCE
$(MAKE) check-TESTS TESTS=$^
@@ -184,6 +192,13 @@ if BUILD_BITCOIN_TX
endif
@echo "Running test/util/rpcauth-test.py..."
$(PYTHON) $(top_builddir)/test/util/rpcauth-test.py
+if TARGET_WINDOWS
+else
+if ENABLE_BENCH
+ @echo "Running bench/bench_bitcoin -evals=1 -scaling=0..."
+ $(BENCH_BINARY) -evals=1 -scaling=0 > /dev/null
+endif
+endif
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
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 eac763394b..e3d2853399 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -6,7 +6,7 @@
#include <hash.h>
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <assert.h>
#include <string.h>
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..2def0b23e2 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -7,13 +7,14 @@
#include <coins.h>
#include <consensus/merkle.h>
#include <consensus/validation.h>
+#include <crypto/sha256.h>
#include <miner.h>
#include <policy/policy.h>
#include <pow.h>
#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..8552ed34fd 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
+#include <interfaces/chain.h>
#include <wallet/wallet.h>
#include <wallet/coinselection.h>
@@ -33,7 +34,8 @@ 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());
+ auto chain = interfaces::MakeChain();
+ const CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet.cs_wallet);
// Add coins.
@@ -57,7 +59,8 @@ static void CoinSelection(benchmark::State& state)
}
typedef std::set<CInputCoin> CoinSet;
-static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static auto testChain = interfaces::MakeChain();
+static const CWallet testWallet(*testChain, 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..dc0b054420 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -9,11 +9,12 @@
#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>
#include <crypto/sha512.h>
+#include <crypto/siphash.h>
/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;
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 6d86581ac6..bc91ca3641 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>
@@ -255,7 +255,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
throw std::runtime_error("invalid TX input vout '" + strVout + "'");
// extract the optional sequence number
- uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
+ uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
if (vStrInputParts.size() > 2)
nSequenceIn = std::stoul(vStrInputParts[2]);
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 18fcd9bc2a..1306ba3821 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -11,14 +11,15 @@
#include <clientversion.h>
#include <compat.h>
#include <fs.h>
+#include <interfaces/chain.h>
#include <rpc/server.h>
#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>
@@ -58,6 +59,9 @@ static void WaitForShutdown()
//
static bool AppInit(int argc, char* argv[])
{
+ InitInterfaces interfaces;
+ interfaces.chain = interfaces::MakeChain();
+
bool fRet = false;
//
@@ -164,7 +168,7 @@ static bool AppInit(int argc, char* argv[])
// If locking the data directory failed, exit immediately
return false;
}
- fRet = AppInitMain();
+ fRet = AppInitMain(interfaces);
}
catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
@@ -178,7 +182,7 @@ static bool AppInit(int argc, char* argv[])
} else {
WaitForShutdown();
}
- Shutdown();
+ Shutdown(interfaces);
return fRet;
}
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index 4c57965bec..10f51931f0 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -6,12 +6,13 @@
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <chainparams.h>
-#include <hash.h>
+#include <crypto/sha256.h>
+#include <crypto/siphash.h>
#include <random.h>
#include <streams.h>
#include <txmempool.h>
#include <validation.h>
-#include <util.h>
+#include <util/system.h>
#include <unordered_map>
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 91623fe70a..163e2a52ef 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <blockfilter.h>
+#include <crypto/siphash.h>
#include <hash.h>
#include <primitives/transaction.h>
#include <script/script.h>
diff --git a/src/blockfilter.h b/src/blockfilter.h
index 46833ac0be..871be11769 100644
--- a/src/blockfilter.h
+++ b/src/blockfilter.h
@@ -5,14 +5,15 @@
#ifndef BITCOIN_BLOCKFILTER_H
#define BITCOIN_BLOCKFILTER_H
-#include <set>
#include <stdint.h>
+#include <unordered_set>
#include <vector>
#include <primitives/block.h>
#include <serialize.h>
#include <uint256.h>
#include <undo.h>
+#include <util/bytevectorhash.h>
/**
* This implements a Golomb-coded set as defined in BIP 158. It is a
@@ -22,7 +23,7 @@ class GCSFilter
{
public:
typedef std::vector<unsigned char> Element;
- typedef std::set<Element> ElementSet;
+ typedef std::unordered_set<Element, ByteVectorHash> ElementSet;
private:
uint64_t m_siphash_k0;
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/coins.cpp b/src/coins.cpp
index f125b483bb..3ef9e0463c 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -6,6 +6,7 @@
#include <consensus/consensus.h>
#include <random.h>
+#include <version.h>
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
diff --git a/src/coins.h b/src/coins.h
index 3867a37b39..94493453f0 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -9,7 +9,7 @@
#include <primitives/transaction.h>
#include <compressor.h>
#include <core_memusage.h>
-#include <hash.h>
+#include <crypto/siphash.h>
#include <memusage.h>
#include <serialize.h>
#include <uint256.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/crypto/siphash.cpp b/src/crypto/siphash.cpp
new file mode 100644
index 0000000000..e81957111a
--- /dev/null
+++ b/src/crypto/siphash.cpp
@@ -0,0 +1,173 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/siphash.h>
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define SIPROUND do { \
+ v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \
+ v0 = ROTL(v0, 32); \
+ v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \
+ v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \
+ v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \
+ v2 = ROTL(v2, 32); \
+} while (0)
+
+CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
+{
+ v[0] = 0x736f6d6570736575ULL ^ k0;
+ v[1] = 0x646f72616e646f6dULL ^ k1;
+ v[2] = 0x6c7967656e657261ULL ^ k0;
+ v[3] = 0x7465646279746573ULL ^ k1;
+ count = 0;
+ tmp = 0;
+}
+
+CSipHasher& CSipHasher::Write(uint64_t data)
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+
+ assert(count % 8 == 0);
+
+ v3 ^= data;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= data;
+
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+
+ count += 8;
+ return *this;
+}
+
+CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+ uint64_t t = tmp;
+ int c = count;
+
+ while (size--) {
+ t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
+ c++;
+ if ((c & 7) == 0) {
+ v3 ^= t;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= t;
+ t = 0;
+ }
+ }
+
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+ count = c;
+ tmp = t;
+
+ return *this;
+}
+
+uint64_t CSipHasher::Finalize() const
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+
+ uint64_t t = tmp | (((uint64_t)count) << 56);
+
+ v3 ^= t;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= t;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+
+uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
+{
+ /* Specialized implementation for efficiency */
+ uint64_t d = val.GetUint64(0);
+
+ uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
+ uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
+ uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
+ uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
+
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(1);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(2);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(3);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ v3 ^= ((uint64_t)4) << 59;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= ((uint64_t)4) << 59;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+
+uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
+{
+ /* Specialized implementation for efficiency */
+ uint64_t d = val.GetUint64(0);
+
+ uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
+ uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
+ uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
+ uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
+
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(1);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(2);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(3);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = (((uint64_t)36) << 56) | extra;
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h
new file mode 100644
index 0000000000..b312f913f9
--- /dev/null
+++ b/src/crypto/siphash.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_SIPHASH_H
+#define BITCOIN_CRYPTO_SIPHASH_H
+
+#include <stdint.h>
+
+#include <uint256.h>
+
+/** SipHash-2-4 */
+class CSipHasher
+{
+private:
+ uint64_t v[4];
+ uint64_t tmp;
+ int count;
+
+public:
+ /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
+ CSipHasher(uint64_t k0, uint64_t k1);
+ /** Hash a 64-bit integer worth of data
+ * It is treated as if this was the little-endian interpretation of 8 bytes.
+ * This function can only be used when a multiple of 8 bytes have been written so far.
+ */
+ CSipHasher& Write(uint64_t data);
+ /** Hash arbitrary bytes. */
+ CSipHasher& Write(const unsigned char* data, size_t size);
+ /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */
+ uint64_t Finalize() const;
+};
+
+/** Optimized SipHash-2-4 implementation for uint256.
+ *
+ * It is identical to:
+ * SipHasher(k0, k1)
+ * .Write(val.GetUint64(0))
+ * .Write(val.GetUint64(1))
+ * .Write(val.GetUint64(2))
+ * .Write(val.GetUint64(3))
+ * .Finalize()
+ */
+uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val);
+uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra);
+
+#endif // BITCOIN_CRYPTO_SIPHASH_H
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..9211a7596b 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;
@@ -14,13 +14,7 @@ public:
bool HasWalletSupport() const override {return false;}
void AddWalletOptions() const override;
bool ParameterInteraction() const override {return true;}
- void RegisterRPC(CRPCTable &) const override {}
- bool Verify() const override {return true;}
- bool Open() const override {LogPrintf("No wallet support compiled in!\n"); return true;}
- void Start(CScheduler& scheduler) const override {}
- void Flush() const override {}
- void Stop() const override {}
- void Close() const override {}
+ void Construct(InitInterfaces& interfaces) const override {LogPrintf("No wallet support compiled in!\n");}
};
void DummyWalletInit::AddWalletOptions() const
diff --git a/src/hash.cpp b/src/hash.cpp
index c049eea716..26150e5ca8 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -77,171 +77,3 @@ void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char he
num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output);
}
-
-#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
-
-#define SIPROUND do { \
- v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \
- v0 = ROTL(v0, 32); \
- v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \
- v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \
- v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \
- v2 = ROTL(v2, 32); \
-} while (0)
-
-CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
-{
- v[0] = 0x736f6d6570736575ULL ^ k0;
- v[1] = 0x646f72616e646f6dULL ^ k1;
- v[2] = 0x6c7967656e657261ULL ^ k0;
- v[3] = 0x7465646279746573ULL ^ k1;
- count = 0;
- tmp = 0;
-}
-
-CSipHasher& CSipHasher::Write(uint64_t data)
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
-
- assert(count % 8 == 0);
-
- v3 ^= data;
- SIPROUND;
- SIPROUND;
- v0 ^= data;
-
- v[0] = v0;
- v[1] = v1;
- v[2] = v2;
- v[3] = v3;
-
- count += 8;
- return *this;
-}
-
-CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
- uint64_t t = tmp;
- int c = count;
-
- while (size--) {
- t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
- c++;
- if ((c & 7) == 0) {
- v3 ^= t;
- SIPROUND;
- SIPROUND;
- v0 ^= t;
- t = 0;
- }
- }
-
- v[0] = v0;
- v[1] = v1;
- v[2] = v2;
- v[3] = v3;
- count = c;
- tmp = t;
-
- return *this;
-}
-
-uint64_t CSipHasher::Finalize() const
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
-
- uint64_t t = tmp | (((uint64_t)count) << 56);
-
- v3 ^= t;
- SIPROUND;
- SIPROUND;
- v0 ^= t;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
-
-uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
-{
- /* Specialized implementation for efficiency */
- uint64_t d = val.GetUint64(0);
-
- uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
- uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
- uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
- uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
-
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(1);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(2);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(3);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- v3 ^= ((uint64_t)4) << 59;
- SIPROUND;
- SIPROUND;
- v0 ^= ((uint64_t)4) << 59;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
-
-uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
-{
- /* Specialized implementation for efficiency */
- uint64_t d = val.GetUint64(0);
-
- uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
- uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
- uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
- uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
-
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(1);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(2);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(3);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = (((uint64_t)36) << 56) | extra;
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
diff --git a/src/hash.h b/src/hash.h
index 3534a400b3..6acab0b161 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -194,39 +194,4 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
-/** SipHash-2-4 */
-class CSipHasher
-{
-private:
- uint64_t v[4];
- uint64_t tmp;
- int count;
-
-public:
- /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
- CSipHasher(uint64_t k0, uint64_t k1);
- /** Hash a 64-bit integer worth of data
- * It is treated as if this was the little-endian interpretation of 8 bytes.
- * This function can only be used when a multiple of 8 bytes have been written so far.
- */
- CSipHasher& Write(uint64_t data);
- /** Hash arbitrary bytes. */
- CSipHasher& Write(const unsigned char* data, size_t size);
- /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */
- uint64_t Finalize() const;
-};
-
-/** Optimized SipHash-2-4 implementation for uint256.
- *
- * It is identical to:
- * SipHasher(k0, k1)
- * .Write(val.GetUint64(0))
- * .Write(val.GetUint64(1))
- * .Write(val.GetUint64(2))
- * .Write(val.GetUint64(3))
- * .Finalize()
- */
-uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val);
-uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra);
-
#endif // BITCOIN_HASH_H
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 42c6b0373d..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>
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 f9efaf7dc1..3ab97be329 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -19,6 +19,7 @@
#include <fs.h>
#include <httpserver.h>
#include <httprpc.h>
+#include <interfaces/chain.h>
#include <index/txindex.h>
#include <key.h>
#include <validation.h>
@@ -32,6 +33,7 @@
#include <rpc/server.h>
#include <rpc/register.h>
#include <rpc/blockchain.h>
+#include <rpc/util.h>
#include <script/standard.h>
#include <script/sigcache.h>
#include <scheduler.h>
@@ -41,8 +43,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>
@@ -62,6 +64,7 @@
#include <openssl/crypto.h>
#if ENABLE_ZMQ
+#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqrpc.h>
#endif
@@ -156,7 +159,7 @@ void Interrupt()
}
}
-void Shutdown()
+void Shutdown(InitInterfaces& interfaces)
{
LogPrintf("%s: In progress...\n", __func__);
static CCriticalSection cs_Shutdown;
@@ -175,7 +178,9 @@ void Shutdown()
StopREST();
StopRPC();
StopHTTPServer();
- g_wallet_init_interface.Flush();
+ for (const auto& client : interfaces.chain_clients) {
+ client->flush();
+ }
StopMapPort();
// Because these depend on each-other, we make sure that neither can be
@@ -238,7 +243,9 @@ void Shutdown()
pcoinsdbview.reset();
pblocktree.reset();
}
- g_wallet_init_interface.Stop();
+ for (const auto& client : interfaces.chain_clients) {
+ client->stop();
+ }
#if ENABLE_ZMQ
if (g_zmq_notification_interface) {
@@ -258,7 +265,7 @@ void Shutdown()
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
- g_wallet_init_interface.Close();
+ interfaces.chain_clients.clear();
globalVerifyHandle.reset();
ECC_Stop();
LogPrintf("%s: done\n", __func__);
@@ -418,11 +425,19 @@ void SetupServerArgs()
gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", false, OptionsCategory::ZMQ);
gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", false, OptionsCategory::ZMQ);
gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
#else
hidden_args.emplace_back("-zmqpubhashblock=<address>");
hidden_args.emplace_back("-zmqpubhashtx=<address>");
hidden_args.emplace_back("-zmqpubrawblock=<address>");
hidden_args.emplace_back("-zmqpubrawtx=<address>");
+ hidden_args.emplace_back("-zmqpubhashblockhwm=<n>");
+ hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
+ hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
+ hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
#endif
gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
@@ -1149,7 +1164,7 @@ bool AppInitLockDataDirectory()
return true;
}
-bool AppInitMain()
+bool AppInitMain(InitInterfaces& interfaces)
{
const CChainParams& chainparams = Params();
// ********************************************************* Step 4a: application initialization
@@ -1212,11 +1227,20 @@ bool AppInitMain()
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool);
+ // Create client interfaces for wallets that are supposed to be loaded
+ // according to -wallet and -disablewallet options. This only constructs
+ // the interfaces, it doesn't load wallet data. Wallets actually get loaded
+ // when load() and start() interface methods are called below.
+ g_wallet_init_interface.Construct(interfaces);
+
/* Register RPC commands regardless of -server setting so they will be
* available in the GUI RPC console even if external calls are disabled.
*/
RegisterAllCoreRPCCommands(tableRPC);
- g_wallet_init_interface.RegisterRPC(tableRPC);
+ for (const auto& client : interfaces.chain_clients) {
+ client->registerRpcs();
+ }
+ g_rpc_interfaces = &interfaces;
#if ENABLE_ZMQ
RegisterZMQRPCCommands(tableRPC);
#endif
@@ -1234,7 +1258,11 @@ bool AppInitMain()
}
// ********************************************************* Step 5: verify wallet database integrity
- if (!g_wallet_init_interface.Verify()) return false;
+ for (const auto& client : interfaces.chain_clients) {
+ if (!client->verify()) {
+ return false;
+ }
+ }
// ********************************************************* Step 6: network initialization
// Note that we absolutely cannot open any actual connections
@@ -1553,7 +1581,11 @@ bool AppInitMain()
}
// ********************************************************* Step 9: load wallet
- if (!g_wallet_init_interface.Open()) return false;
+ for (const auto& client : interfaces.chain_clients) {
+ if (!client->load()) {
+ return false;
+ }
+ }
// ********************************************************* Step 10: data directory maintenance
@@ -1699,7 +1731,9 @@ bool AppInitMain()
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading"));
- g_wallet_init_interface.Start(scheduler);
+ for (const auto& client : interfaces.chain_clients) {
+ client->start(scheduler);
+ }
return true;
}
diff --git a/src/init.h b/src/init.h
index c58ba5cfd3..1c59ca069e 100644
--- a/src/init.h
+++ b/src/init.h
@@ -8,10 +8,19 @@
#include <memory>
#include <string>
-#include <util.h>
+#include <util/system.h>
-class CScheduler;
-class CWallet;
+namespace interfaces {
+class Chain;
+class ChainClient;
+} // namespace interfaces
+
+//! Pointers to interfaces used during init and destroyed on shutdown.
+struct InitInterfaces
+{
+ std::unique_ptr<interfaces::Chain> chain;
+ std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
+};
namespace boost
{
@@ -20,7 +29,7 @@ class thread_group;
/** Interrupt threads */
void Interrupt();
-void Shutdown();
+void Shutdown(InitInterfaces& interfaces);
//!Initialize the logging infrastructure
void InitLogging();
//!Parameter interaction: change current parameters depending on various rules
@@ -54,7 +63,7 @@ bool AppInitLockDataDirectory();
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
*/
-bool AppInitMain();
+bool AppInitMain(InitInterfaces& interfaces);
/**
* Setup the arguments for gArgs
diff --git a/src/interfaces/README.md b/src/interfaces/README.md
index e93b91d23c..57d41df746 100644
--- a/src/interfaces/README.md
+++ b/src/interfaces/README.md
@@ -4,7 +4,7 @@ The following interfaces are defined here:
* [`Chain`](chain.h) — used by wallet to access blockchain and mempool state. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
-* [`Chain::Client`](chain.h) — used by node to start & stop `Chain` clients. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
+* [`ChainClient`](chain.h) — used by node to start & stop `Chain` clients. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
* [`Node`](node.h) — used by GUI to start & stop bitcoin node. Added in [#10244](https://github.com/bitcoin/bitcoin/pull/10244).
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
new file mode 100644
index 0000000000..2571a91031
--- /dev/null
+++ b/src/interfaces/chain.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <interfaces/chain.h>
+
+#include <sync.h>
+#include <util/system.h>
+#include <validation.h>
+
+#include <memory>
+#include <utility>
+
+namespace interfaces {
+namespace {
+
+class LockImpl : public Chain::Lock
+{
+};
+
+class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
+{
+ using UniqueLock::UniqueLock;
+};
+
+class ChainImpl : public Chain
+{
+public:
+ std::unique_ptr<Chain::Lock> lock(bool try_lock) override
+ {
+ auto result = MakeUnique<LockingStateImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
+ if (try_lock && result && !*result) return {};
+ // std::move necessary on some compilers due to conversion from
+ // LockingStateImpl to Lock pointer
+ return std::move(result);
+ }
+ std::unique_ptr<Chain::Lock> assumeLocked() override { return MakeUnique<LockImpl>(); }
+};
+
+} // namespace
+
+std::unique_ptr<Chain> MakeChain() { return MakeUnique<ChainImpl>(); }
+
+} // namespace interfaces
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
new file mode 100644
index 0000000000..fe5658de4b
--- /dev/null
+++ b/src/interfaces/chain.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_INTERFACES_CHAIN_H
+#define BITCOIN_INTERFACES_CHAIN_H
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class CScheduler;
+
+namespace interfaces {
+
+//! Interface for giving wallet processes access to blockchain state.
+class Chain
+{
+public:
+ virtual ~Chain() {}
+
+ //! Interface for querying locked chain state, used by legacy code that
+ //! assumes state won't change between calls. New code should avoid using
+ //! the Lock interface and instead call higher-level Chain methods
+ //! that return more information so the chain doesn't need to stay locked
+ //! between calls.
+ class Lock
+ {
+ public:
+ virtual ~Lock() {}
+ };
+
+ //! Return Lock interface. Chain is locked when this is called, and
+ //! unlocked when the returned interface is freed.
+ virtual std::unique_ptr<Lock> lock(bool try_lock = false) = 0;
+
+ //! Return Lock interface assuming chain is already locked. This
+ //! method is temporary and is only used in a few places to avoid changing
+ //! behavior while code is transitioned to use the Chain::Lock interface.
+ virtual std::unique_ptr<Lock> assumeLocked() = 0;
+};
+
+//! Interface to let node manage chain clients (wallets, or maybe tools for
+//! monitoring and analysis in the future).
+class ChainClient
+{
+public:
+ virtual ~ChainClient() {}
+
+ //! Register rpcs.
+ virtual void registerRpcs() = 0;
+
+ //! Check for errors before loading.
+ virtual bool verify() = 0;
+
+ //! Load saved state.
+ virtual bool load() = 0;
+
+ //! Start client execution and provide a scheduler.
+ virtual void start(CScheduler& scheduler) = 0;
+
+ //! Save state to disk.
+ virtual void flush() = 0;
+
+ //! Shut down client.
+ virtual void stop() = 0;
+};
+
+//! Return implementation of Chain interface.
+std::unique_ptr<Chain> MakeChain();
+
+//! Return implementation of ChainClient interface for a wallet client. This
+//! function will be undefined in builds where ENABLE_WALLET is false.
+//!
+//! Currently, wallets are the only chain clients. But in the future, other
+//! types of chain clients could be added, such as tools for monitoring,
+//! analysis, or fee estimation. These clients need to expose their own
+//! MakeXXXClient functions returning their implementations of the ChainClient
+//! interface.
+std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames);
+
+} // namespace interfaces
+
+#endif // BITCOIN_INTERFACES_CHAIN_H
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..1919e16a66 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -9,6 +9,7 @@
#include <chain.h>
#include <chainparams.h>
#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <interfaces/wallet.h>
#include <net.h>
@@ -25,7 +26,7 @@
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <warnings.h>
@@ -50,6 +51,8 @@ namespace {
class NodeImpl : public Node
{
+public:
+ NodeImpl() { m_interfaces.chain = MakeChain(); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
return gArgs.ParseParameters(argc, argv, error);
@@ -68,11 +71,11 @@ class NodeImpl : public Node
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
AppInitLockDataDirectory();
}
- bool appInitMain() override { return AppInitMain(); }
+ bool appInitMain() override { return AppInitMain(m_interfaces); }
void appShutdown() override
{
Interrupt();
- Shutdown();
+ Shutdown(m_interfaces);
}
void startShutdown() override { StartShutdown(); }
bool shutdownRequested() override { return ShutdownRequested(); }
@@ -291,6 +294,7 @@ class NodeImpl : public Node
GuessVerificationProgress(Params().TxData(), block));
}));
}
+ InitInterfaces m_interfaces;
};
} // namespace
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 84079fdc3c..672a557d41 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -7,12 +7,16 @@
#include <amount.h>
#include <chain.h>
#include <consensus/validation.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <net.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
+#include <rpc/server.h>
+#include <scheduler.h>
#include <script/ismine.h>
#include <script/standard.h>
#include <support/allocators/secure.h>
@@ -20,10 +24,18 @@
#include <timedata.h>
#include <ui_interface.h>
#include <uint256.h>
+#include <util/system.h>
#include <validation.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
+#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
+#include <wallet/walletutil.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace interfaces {
namespace {
@@ -41,7 +53,8 @@ public:
WalletOrderForm order_form,
std::string& reject_reason) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
CValidationState state;
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, g_connman.get(), state)) {
reject_reason = state.GetRejectReason();
@@ -56,7 +69,7 @@ public:
};
//! Construct wallet tx struct.
-static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, const CWalletTx& wtx)
{
WalletTx result;
result.tx = wtx.tx;
@@ -74,7 +87,7 @@ static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LO
IsMine(wallet, result.txout_address.back()) :
ISMINE_NO);
}
- result.credit = wtx.GetCredit(ISMINE_ALL);
+ result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL);
result.debit = wtx.GetDebit(ISMINE_ALL);
result.change = wtx.GetChange();
result.time = wtx.GetTxTime();
@@ -84,32 +97,38 @@ static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LO
}
//! Construct wallet tx status struct.
-static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx)
{
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+
WalletTxStatus result;
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr;
result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max());
- result.blocks_to_maturity = wtx.GetBlocksToMaturity();
- result.depth_in_main_chain = wtx.GetDepthInMainChain();
+ result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain);
+ result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain);
result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime;
result.is_final = CheckFinalTx(*wtx.tx);
- result.is_trusted = wtx.IsTrusted();
+ result.is_trusted = wtx.IsTrusted(locked_chain);
result.is_abandoned = wtx.isAbandoned();
result.is_coinbase = wtx.IsCoinBase();
- result.is_in_main_chain = wtx.IsInMainChain();
+ result.is_in_main_chain = wtx.IsInMainChain(locked_chain);
return result;
}
//! Construct wallet TxOut struct.
-static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet.cs_wallet)
+WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain,
+ CWallet& wallet,
+ const CWalletTx& wtx,
+ int n,
+ int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
WalletTxOut result;
result.txout = wtx.tx->vout[n];
result.time = wtx.GetTxTime();
result.depth_in_main_chain = depth;
- result.is_spent = wallet.IsSpent(wtx.GetHash(), n);
+ result.is_spent = wallet.IsSpent(locked_chain, wtx.GetHash(), n);
return result;
}
@@ -197,22 +216,26 @@ public:
}
void lockCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.IsLockedCoin(output.hash, output.n);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.ListLockedCoins(outputs);
}
std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
@@ -222,9 +245,10 @@ public:
CAmount& fee,
std::string& fail_reason) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
- if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_key, fee, change_pos,
+ if (!m_wallet.CreateTransaction(*locked_chain, recipients, pending->m_tx, pending->m_key, fee, change_pos,
fail_reason, coin_control, sign)) {
return {};
}
@@ -233,8 +257,9 @@ public:
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.AbandonTransaction(txid);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
+ return m_wallet.AbandonTransaction(*locked_chain, txid);
}
bool transactionCanBeBumped(const uint256& txid) override
{
@@ -262,7 +287,8 @@ public:
}
CTransactionRef getTx(const uint256& txid) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
return mi->second.tx;
@@ -271,29 +297,30 @@ public:
}
WalletTx getWalletTx(const uint256& txid) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
- return MakeWalletTx(m_wallet, mi->second);
+ return MakeWalletTx(*locked_chain, m_wallet, mi->second);
}
return {};
}
std::vector<WalletTx> getWalletTxs() override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
std::vector<WalletTx> result;
result.reserve(m_wallet.mapWallet.size());
for (const auto& entry : m_wallet.mapWallet) {
- result.emplace_back(MakeWalletTx(m_wallet, entry.second));
+ result.emplace_back(MakeWalletTx(*locked_chain, m_wallet, entry.second));
}
return result;
}
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);
+ auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
if (!locked_chain) {
return false;
}
@@ -306,26 +333,24 @@ public:
return false;
}
num_blocks = ::chainActive.Height();
- adjusted_time = GetAdjustedTime();
- tx_status = MakeWalletTxStatus(mi->second);
+ tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return true;
}
WalletTx getWalletTxDetails(const uint256& txid,
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 locked_chain = m_wallet.chain().lock();
+ LOCK(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);
- return MakeWalletTx(m_wallet, mi->second);
+ tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
+ return MakeWalletTx(*locked_chain, m_wallet, mi->second);
}
return {};
}
@@ -345,7 +370,7 @@ public:
}
bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
{
- TRY_LOCK(cs_main, locked_chain);
+ auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
if (!locked_chain) return false;
TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
if (!locked_wallet) {
@@ -362,49 +387,55 @@ public:
}
isminetype txinIsMine(const CTxIn& txin) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.IsMine(txin);
}
isminetype txoutIsMine(const CTxOut& txout) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.IsMine(txout);
}
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.GetDebit(txin, filter);
}
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
return m_wallet.GetCredit(txout, filter);
}
CoinsList listCoins() override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
CoinsList result;
- for (const auto& entry : m_wallet.ListCoins()) {
+ for (const auto& entry : m_wallet.ListCoins(*locked_chain)) {
auto& group = result[entry.first];
for (const auto& coin : entry.second) {
- group.emplace_back(
- COutPoint(coin.tx->GetHash(), coin.i), MakeWalletTxOut(m_wallet, *coin.tx, coin.i, coin.nDepth));
+ group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i),
+ MakeWalletTxOut(*locked_chain, m_wallet, *coin.tx, coin.i, coin.nDepth));
}
}
return result;
}
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
std::vector<WalletTxOut> result;
result.reserve(outputs.size());
for (const auto& output : outputs) {
result.emplace_back();
auto it = m_wallet.mapWallet.find(output.hash);
if (it != m_wallet.mapWallet.end()) {
- int depth = it->second.GetDepthInMainChain();
+ int depth = it->second.GetDepthInMainChain(*locked_chain);
if (depth >= 0) {
- result.back() = MakeWalletTxOut(m_wallet, it->second, output.n, depth);
+ result.back() = MakeWalletTxOut(*locked_chain, m_wallet, it->second, output.n, depth);
}
}
}
@@ -460,8 +491,32 @@ public:
CWallet& m_wallet;
};
+class WalletClientImpl : public ChainClient
+{
+public:
+ WalletClientImpl(Chain& chain, std::vector<std::string> wallet_filenames)
+ : m_chain(chain), m_wallet_filenames(std::move(wallet_filenames))
+ {
+ }
+ void registerRpcs() override { return RegisterWalletRPCCommands(::tableRPC); }
+ bool verify() override { return VerifyWallets(m_chain, m_wallet_filenames); }
+ bool load() override { return LoadWallets(m_chain, m_wallet_filenames); }
+ void start(CScheduler& scheduler) override { return StartWallets(scheduler); }
+ void flush() override { return FlushWallets(); }
+ void stop() override { return StopWallets(); }
+ ~WalletClientImpl() override { UnloadWallets(); }
+
+ Chain& m_chain;
+ std::vector<std::string> m_wallet_filenames;
+};
+
} // namespace
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
+std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames)
+{
+ return MakeUnique<WalletClientImpl>(chain, std::move(wallet_filenames));
+}
+
} // namespace interfaces
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.h b/src/net.h
index 49360a7206..164ec9080c 100644
--- a/src/net.h
+++ b/src/net.h
@@ -11,6 +11,7 @@
#include <amount.h>
#include <bloom.h>
#include <compat.h>
+#include <crypto/siphash.h>
#include <hash.h>
#include <limitedmap.h>
#include <netaddress.h>
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index a1b6e021ae..f4ab3aa153 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>
@@ -2357,6 +2357,23 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
for (const CTransactionRef& removedTx : lRemovedTxn)
AddToCompactExtraTransactions(removedTx);
+ // If a tx has been detected by recentRejects, we will have reached
+ // this point and the tx will have been ignored. Because we haven't run
+ // the tx through AcceptToMemoryPool, we won't have computed a DoS
+ // score for it or determined exactly why we consider it invalid.
+ //
+ // This means we won't penalize any peer subsequently relaying a DoSy
+ // tx (even if we penalized the first peer who gave it to us) because
+ // we have to account for recentRejects showing false positives. In
+ // other words, we shouldn't penalize a peer if we aren't *sure* they
+ // submitted a DoSy tx.
+ //
+ // Note that recentRejects doesn't just record DoSy or invalid
+ // transactions, but any tx not accepted by the mempool, which may be
+ // due to node policy (vs. consensus). So we can't blanket penalize a
+ // peer simply for relaying a tx that our recentRejects has caught,
+ // regardless of false positives.
+
int nDoS = 0;
if (state.IsInvalid(nDoS))
{
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/policy/rbf.cpp b/src/policy/rbf.cpp
index 18f9c0c2a8..0dc130d104 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -7,7 +7,7 @@
bool SignalsOptInRBF(const CTransaction &tx)
{
for (const CTxIn &txin : tx.vin) {
- if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) {
+ if (txin.nSequence <= MAX_BIP125_RBF_SEQUENCE) {
return true;
}
}
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/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 c0f9b3d5d3..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>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 1e80777c15..89b80bd5c9 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/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/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 3f118e37f1..8148986b51 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -17,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>
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/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 e6777c068d..3e414df1f0 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -2,6 +2,7 @@
#include <qt/test/util.h>
#include <test/test_bitcoin.h>
+#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <qt/addressbookpage.h>
#include <qt/addresstablemodel.h>
@@ -56,7 +57,8 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook()
{
TestChain100Setup test;
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
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 28df4ebf26..b6523604fd 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -8,7 +8,7 @@
#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>
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index fcc5806b81..f02fd8aea7 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -1,6 +1,7 @@
#include <qt/test/wallettests.h>
#include <qt/test/util.h>
+#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <base58.h>
#include <qt/bitcoinamountfield.h>
@@ -132,7 +133,8 @@ 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());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
{
@@ -141,7 +143,7 @@ void TestGUI()
wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
}
{
- LOCK(cs_main);
+ auto locked_chain = wallet->chain().lock();
WalletRescanReserver reserver(wallet.get());
reserver.reserve();
wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 3c5617bfa8..0d070d9e87 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -19,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>
@@ -27,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)
{
@@ -53,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;
@@ -69,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>";
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 faeed87ec4..ebf7bad795 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -22,7 +22,7 @@
#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 71b2d321e2..353da0c9b4 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -20,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>
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 e940134fb5..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>
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index a550f693e6..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>
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 25cfc69da9..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>
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index b53c1a5199..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>
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..94a9ea20da 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -9,6 +9,7 @@
#include <consensus/validation.h>
#include <core_io.h>
#include <index/txindex.h>
+#include <init.h>
#include <keystore.h>
#include <validation.h>
#include <validationinterface.h>
@@ -20,13 +21,14 @@
#include <primitives/transaction.h>
#include <rpc/rawtransaction.h>
#include <rpc/server.h>
+#include <rpc/util.h>
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
#include <script/standard.h>
#include <txmempool.h>
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <future>
#include <stdint.h>
@@ -346,7 +348,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
if (!locktime.isNull()) {
int64_t nLockTime = locktime.get_int64();
- if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max())
+ if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
rawTx.nLockTime = nLockTime;
}
@@ -368,18 +370,18 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
uint32_t nSequence;
if (rbfOptIn) {
- nSequence = MAX_BIP125_RBF_SEQUENCE;
+ nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */
} else if (rawTx.nLockTime) {
- nSequence = std::numeric_limits<uint32_t>::max() - 1;
+ nSequence = CTxIn::SEQUENCE_FINAL - 1;
} else {
- nSequence = std::numeric_limits<uint32_t>::max();
+ nSequence = CTxIn::SEQUENCE_FINAL;
}
// set the sequence number if passed in the parameters object
const UniValue& sequenceObj = find_value(o, "sequence");
if (sequenceObj.isNum()) {
int64_t seqNr64 = sequenceObj.get_int64();
- if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
+ if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
} else {
nSequence = (uint32_t)seqNr64;
@@ -754,7 +756,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
return EncodeHexTx(mergedTx);
}
-UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
+UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
{
// Fetch previous transactions (inputs):
CCoinsView viewDummy;
@@ -969,7 +971,7 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
keystore.AddKey(key);
}
- return SignTransaction(mtx, request.params[2], &keystore, true, request.params[3]);
+ return SignTransaction(*g_rpc_interfaces->chain, mtx, request.params[2], &keystore, true, request.params[3]);
}
UniValue signrawtransaction(const JSONRPCRequest& request)
@@ -1536,12 +1538,13 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
- // Get all of the previous transactions
+ // Finalize input signatures -- in case we have partial signatures that add up to a complete
+ // signature, but have not combined them yet (e.g. because the combiner that created this
+ // PartiallySignedTransaction did not understand them), this will combine them into a final
+ // script.
bool complete = true;
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
- PSBTInput& input = psbtx.inputs.at(i);
-
- complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, *psbtx.tx, input, i, 1);
+ complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, SIGHASH_ALL);
}
UniValue result(UniValue::VOBJ);
@@ -1554,10 +1557,10 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
mtx.vin[i].scriptWitness = psbtx.inputs[i].final_script_witness;
}
ssTx << mtx;
- result.pushKV("hex", HexStr(ssTx.begin(), ssTx.end()));
+ result.pushKV("hex", HexStr(ssTx.str()));
} else {
ssTx << psbtx;
- result.pushKV("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()));
+ result.pushKV("psbt", EncodeBase64(ssTx.str()));
}
result.pushKV("complete", complete);
diff --git a/src/rpc/rawtransaction.h b/src/rpc/rawtransaction.h
index 924611ed5a..52d701d1c3 100644
--- a/src/rpc/rawtransaction.h
+++ b/src/rpc/rawtransaction.h
@@ -9,8 +9,12 @@ class CBasicKeyStore;
struct CMutableTransaction;
class UniValue;
+namespace interfaces {
+class Chain;
+} // namespace interfaces
+
/** Sign a transaction with the given keystore and previous transactions */
-UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore *keystore, bool tempKeystore, const UniValue& hashType);
+UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore *keystore, bool tempKeystore, const UniValue& hashType);
/** Create a transaction from univalue parameters */
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf);
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..ef2d14b90e 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -7,7 +7,9 @@
#include <rpc/protocol.h>
#include <rpc/util.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+
+InitInterfaces* g_rpc_interfaces = nullptr;
// Converts a hex string to a public key if possible
CPubKey HexToPubKey(const std::string& hex_in)
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 0a3a156e45..e21b5ba22a 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -17,6 +17,12 @@
class CKeyStore;
class CPubKey;
class CScript;
+struct InitInterfaces;
+
+//! Pointers to interfaces that need to be accessible from RPC methods. Due to
+//! limitations of the RPC framework, there's currently no direct way to pass in
+//! state to RPC method implementations.
+extern InitInterfaces* g_rpc_interfaces;
CPubKey HexToPubKey(const std::string& hex_in);
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 478797e958..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>
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/script.h b/src/script/script.h
index 00065a24be..1d8ddba2f2 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -38,6 +38,12 @@ static const int MAX_STACK_SIZE = 1000;
// otherwise as UNIX timestamp.
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
+// Maximum nLockTime. Since a lock time indicates the last invalid timestamp, a
+// transaction with this lock time will never be valid unless lock time
+// checking is disabled (by setting all input sequence numbers to
+// SEQUENCE_FINAL).
+static const uint32_t LOCKTIME_MAX = 0xFFFFFFFFU;
+
template <typename T>
std::vector<unsigned char> ToByteVector(const T& in)
{
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 89cc7c808c..2795dc96d3 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -123,7 +123,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TX_PUBKEYHASH: {
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
CPubKey pubkey;
- GetPubKey(provider, sigdata, keyID, pubkey);
+ if (!GetPubKey(provider, sigdata, keyID, pubkey)) return false;
if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
ret.push_back(std::move(sig));
ret.push_back(ToByteVector(pubkey));
@@ -239,10 +239,17 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
return sigdata.complete;
}
-bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, int index, int sighash)
+bool PSBTInputSigned(PSBTInput& input)
{
- // if this input has a final scriptsig or scriptwitness, don't do anything with it
- if (!input.final_script_sig.empty() || !input.final_script_witness.IsNull()) {
+ return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
+}
+
+bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash)
+{
+ PSBTInput& input = psbt.inputs.at(index);
+ const CMutableTransaction& tx = *psbt.tx;
+
+ if (PSBTInputSigned(input)) {
return true;
}
@@ -253,15 +260,19 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t
// Get UTXO
bool require_witness_sig = false;
CTxOut utxo;
+
+ // Verify input sanity, which checks that at most one of witness or non-witness utxos is provided.
+ if (!input.IsSane()) {
+ return false;
+ }
+
if (input.non_witness_utxo) {
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
- if (input.non_witness_utxo->GetHash() != tx.vin[index].prevout.hash) return false;
- // If both witness and non-witness UTXO are provided, verify that they match. This check shouldn't
- // matter, as the PSBT deserializer enforces only one of both is provided, and the only way both
- // can be present is when they're added simultaneously by FillPSBT (in which case they always match).
- // Still, check in order to not rely on callers to enforce this.
- if (!input.witness_utxo.IsNull() && input.non_witness_utxo->vout[tx.vin[index].prevout.n] != input.witness_utxo) return false;
- utxo = input.non_witness_utxo->vout[tx.vin[index].prevout.n];
+ COutPoint prevout = tx.vin[index].prevout;
+ if (input.non_witness_utxo->GetHash() != prevout.hash) {
+ return false;
+ }
+ utxo = input.non_witness_utxo->vout[prevout.n];
} else if (!input.witness_utxo.IsNull()) {
utxo = input.witness_utxo;
// When we're taking our information from a witness UTXO, we can't verify it is actually data from
@@ -280,18 +291,10 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t
if (require_witness_sig && !sigdata.witness) return false;
input.FromSignatureData(sigdata);
+ // If we have a witness signature, use the smaller witness UTXO.
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) {
- input.non_witness_utxo = nullptr;
- } else {
- input.witness_utxo.SetNull();
- }
+ input.non_witness_utxo = nullptr;
}
return sig_complete;
@@ -513,6 +516,12 @@ bool IsSolvable(const SigningProvider& provider, const CScript& script)
return false;
}
+PartiallySignedTransaction::PartiallySignedTransaction(const CTransaction& tx) : tx(tx)
+{
+ inputs.resize(tx.vin.size());
+ outputs.resize(tx.vout.size());
+}
+
bool PartiallySignedTransaction::IsNull() const
{
return !tx && inputs.empty() && outputs.empty() && unknown.empty();
diff --git a/src/script/sign.h b/src/script/sign.h
index 689501269d..e71f43f96d 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -302,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;
@@ -309,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];
@@ -424,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>
@@ -477,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;
@@ -484,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];
@@ -529,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>
@@ -550,6 +566,7 @@ struct PartiallySignedTransaction
bool IsSane() const;
PartiallySignedTransaction() {}
PartiallySignedTransaction(const PartiallySignedTransaction& psbt_in) : tx(psbt_in.tx), inputs(psbt_in.inputs), outputs(psbt_in.outputs), unknown(psbt_in.unknown) {}
+ explicit PartiallySignedTransaction(const CTransaction& tx);
// Only checks if they refer to the same transaction
friend bool operator==(const PartiallySignedTransaction& a, const PartiallySignedTransaction &b)
@@ -604,6 +621,7 @@ struct PartiallySignedTransaction
}
// Read global data
+ bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
@@ -611,7 +629,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];
@@ -651,6 +672,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");
@@ -705,8 +730,11 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
+/** Checks whether a PSBTInput is already signed. */
+bool PSBTInputSigned(PSBTInput& input);
+
/** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
-bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, int index, int sighash = SIGHASH_ALL);
+bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash = SIGHASH_ALL);
/** Extract signature data from a transaction input, and insert it. */
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
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/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 f3083bab4a..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 {
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..e8e5040855 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -2,8 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <crypto/siphash.h>
#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 354ca7507e..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>
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..26cdc9bc5c 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -1,12 +1,12 @@
// Copyright (c) 2015-2018 The Bitcoin Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#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/rpc_tests.cpp b/src/test/rpc_tests.cpp
index a49796d6f4..121b72a5f7 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -4,8 +4,11 @@
#include <rpc/server.h>
#include <rpc/client.h>
+#include <rpc/util.h>
#include <core_io.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <key_io.h>
#include <netbase.h>
@@ -112,10 +115,14 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
std::string notsigned = r.get_str();
std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
+ InitInterfaces interfaces;
+ interfaces.chain = interfaces::MakeChain();
+ g_rpc_interfaces = &interfaces;
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
+ g_rpc_interfaces = nullptr;
}
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
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..5c46976ace 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>
@@ -170,7 +170,6 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::min())->nHeight, 0);
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
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/threadsafety.h b/src/threadsafety.h
index 47e6b2ea38..33acddc65c 100644
--- a/src/threadsafety.h
+++ b/src/threadsafety.h
@@ -54,4 +54,15 @@
#define ASSERT_EXCLUSIVE_LOCK(...)
#endif // __GNUC__
+// Utility class for indicating to compiler thread analysis that a mutex is
+// locked (when it couldn't be determined otherwise).
+struct SCOPED_LOCKABLE LockAnnotation
+{
+ template <typename Mutex>
+ explicit LockAnnotation(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex)
+ {
+ }
+ ~LockAnnotation() UNLOCK_FUNCTION() {}
+};
+
#endif // BITCOIN_THREADSAFETY_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 34a1e539df..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,
diff --git a/src/txmempool.h b/src/txmempool.h
index cda78ea90c..fadb554723 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -15,6 +15,7 @@
#include <amount.h>
#include <coins.h>
+#include <crypto/siphash.h>
#include <indirectmap.h>
#include <policy/feerate.h>
#include <primitives/transaction.h>
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 e940f90cf0..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>
diff --git a/src/undo.h b/src/undo.h
index 4ed3dc4ca0..3f50f4caad 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -11,6 +11,7 @@
#include <consensus/consensus.h>
#include <primitives/transaction.h>
#include <serialize.h>
+#include <version.h>
/** Undo information for a CTxIn
*
diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
new file mode 100644
index 0000000000..f87d0e04b3
--- /dev/null
+++ b/src/util/bytevectorhash.cpp
@@ -0,0 +1,18 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/siphash.h>
+#include <random.h>
+#include <util/bytevectorhash.h>
+
+ByteVectorHash::ByteVectorHash()
+{
+ GetRandBytes(reinterpret_cast<unsigned char*>(&m_k0), sizeof(m_k0));
+ GetRandBytes(reinterpret_cast<unsigned char*>(&m_k1), sizeof(m_k1));
+}
+
+size_t ByteVectorHash::operator()(const std::vector<unsigned char>& input) const
+{
+ return CSipHasher(m_k0, m_k1).Write(input.data(), input.size()).Finalize();
+}
diff --git a/src/util/bytevectorhash.h b/src/util/bytevectorhash.h
new file mode 100644
index 0000000000..b88c17460b
--- /dev/null
+++ b/src/util/bytevectorhash.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_BYTEVECTORHASH_H
+#define BITCOIN_UTIL_BYTEVECTORHASH_H
+
+#include <stdint.h>
+#include <vector>
+
+/**
+ * Implementation of Hash named requirement for types that internally store a byte array. This may
+ * be used as the hash function in std::unordered_set or std::unordered_map over such types.
+ * Internally, this uses a random instance of SipHash-2-4.
+ */
+class ByteVectorHash final
+{
+private:
+ uint64_t m_k0, m_k1;
+
+public:
+ ByteVectorHash();
+ size_t operator()(const std::vector<unsigned char>& input) const;
+};
+
+#endif // BITCOIN_UTIL_BYTEVECTORHASH_H
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 7bae161a1d..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)
{
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 a1700d2514..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)
diff --git a/src/utilstrencodings.h b/src/util/strencodings.h
index 1610c8c268..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)
};
/**
@@ -245,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 0c446c262d..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>
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 25880f3529..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>
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 68a59607ae..8f96483a18 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -11,7 +11,7 @@
#include <serialize.h>
#include <streams.h>
#include <sync.h>
-#include <util.h>
+#include <util/system.h>
#include <version.h>
#include <atomic>
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 677bf74b5d..7a71aea715 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/validation.h>
+#include <interfaces/chain.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
@@ -12,13 +13,13 @@
#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
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
-static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet->cs_wallet)
+static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
{
if (wallet->HasWalletSpend(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the wallet");
@@ -34,7 +35,7 @@ static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWallet
}
}
- if (wtx.GetDepthInMainChain() != 0) {
+ if (wtx.GetDepthInMainChain(locked_chain) != 0) {
errors.push_back("Transaction has been mined, or is conflicted with a mined transaction");
return feebumper::Result::WALLET_ERROR;
}
@@ -64,19 +65,21 @@ namespace feebumper {
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
const CWalletTx* wtx = wallet->GetWalletTx(txid);
if (wtx == nullptr) return false;
std::vector<std::string> errors_dummy;
- feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy);
+ feebumper::Result res = PreconditionChecks(*locked_chain, wallet, *wtx, errors_dummy);
return res == feebumper::Result::OK;
}
Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
errors.clear();
auto it = wallet->mapWallet.find(txid);
if (it == wallet->mapWallet.end()) {
@@ -85,7 +88,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
}
const CWalletTx& wtx = it->second;
- Result result = PreconditionChecks(wallet, wtx, errors);
+ Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors);
if (result != Result::OK) {
return result;
}
@@ -212,13 +215,15 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
}
bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) {
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
return wallet->SignTransaction(mtx);
}
Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
if (!errors.empty()) {
return Result::MISC_ERROR;
}
@@ -230,7 +235,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
CWalletTx& oldWtx = it->second;
// make sure the transaction still has no descendants and hasn't been mined in the meantime
- Result result = PreconditionChecks(wallet, oldWtx, errors);
+ Result result = PreconditionChecks(*locked_chain, wallet, oldWtx, errors);
if (result != Result::OK) {
return result;
}
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..14d811c6cd 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -5,11 +5,12 @@
#include <chainparams.h>
#include <init.h>
+#include <interfaces/chain.h>
#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>
@@ -28,28 +29,8 @@ public:
//! Wallets parameter interaction
bool ParameterInteraction() const override;
- //! Register wallet RPCs.
- void RegisterRPC(CRPCTable &tableRPC) const override;
-
- //! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
- // This function will perform salvage on the wallet if requested, as long as only one wallet is
- // being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
- bool Verify() const override;
-
- //! Load wallet databases.
- bool Open() const override;
-
- //! Complete startup of wallets.
- void Start(CScheduler& scheduler) const override;
-
- //! Flush all wallets in preparation for shutdown.
- void Flush() const override;
-
- //! Stop all wallets. Wallets will be flushed first.
- void Stop() const override;
-
- //! Close all wallets.
- void Close() const override;
+ //! Add wallets that should be opened to list of init interfaces.
+ void Construct(InitInterfaces& interfaces) const override;
};
const WalletInitInterface& g_wallet_init_interface = WalletInit();
@@ -57,7 +38,7 @@ const WalletInitInterface& g_wallet_init_interface = WalletInit();
void WalletInit::AddWalletOptions() const
{
gArgs.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), false, OptionsCategory::WALLET);
- gArgs.AddArg("-avoidpartialspends", strprintf(_("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)"), DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)", DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
gArgs.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", false, OptionsCategory::WALLET);
gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
@@ -99,7 +80,6 @@ bool WalletInit::ParameterInteraction() const
return true;
}
- gArgs.SoftSetArg("-wallet", "");
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
@@ -165,21 +145,8 @@ bool WalletInit::ParameterInteraction() const
return true;
}
-void WalletInit::RegisterRPC(CRPCTable &t) const
-{
- if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
- return;
- }
-
- RegisterWalletRPCCommands(t);
-}
-
-bool WalletInit::Verify() const
+bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
- if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
- return true;
- }
-
if (gArgs.IsArgSet("-walletdir")) {
fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
boost::system::error_code error;
@@ -200,8 +167,6 @@ bool WalletInit::Verify() const
uiInterface.InitMessage(_("Verifying wallet(s)..."));
- std::vector<std::string> wallet_files = gArgs.GetArgs("-wallet");
-
// Parameter interaction code should have thrown an error if -salvagewallet
// was enabled with more than wallet file, so the wallet_files size check
// here should have no effect.
@@ -211,15 +176,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(chain, 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;
@@ -228,15 +193,20 @@ bool WalletInit::Verify() const
return true;
}
-bool WalletInit::Open() const
+void WalletInit::Construct(InitInterfaces& interfaces) const
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
LogPrintf("Wallet disabled!\n");
- return true;
+ return;
}
+ gArgs.SoftSetArg("-wallet", "");
+ interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet")));
+}
- for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
- std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
+bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
+{
+ for (const std::string& walletFile : wallet_files) {
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
if (!pwallet) {
return false;
}
@@ -246,7 +216,7 @@ bool WalletInit::Open() const
return true;
}
-void WalletInit::Start(CScheduler& scheduler) const
+void StartWallets(CScheduler& scheduler)
{
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->postInitProcess();
@@ -256,21 +226,21 @@ void WalletInit::Start(CScheduler& scheduler) const
scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
}
-void WalletInit::Flush() const
+void FlushWallets()
{
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(false);
}
}
-void WalletInit::Stop() const
+void StopWallets()
{
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(true);
}
}
-void WalletInit::Close() const
+void UnloadWallets()
{
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
RemoveWallet(pwallet);
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index c17d5b48d4..e1e4fc51fe 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -3,14 +3,15 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
+#include <interfaces/chain.h>
#include <key_io.h>
#include <rpc/server.h>
#include <validation.h>
#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>
@@ -133,7 +134,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
WalletRescanReserver reserver(pwallet);
bool fRescan = true;
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -305,7 +307,8 @@ UniValue importaddress(const JSONRPCRequest& request)
fP2SH = request.params[3].get_bool();
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (IsValidDestination(dest)) {
@@ -362,7 +365,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
unsigned int txnIndex = 0;
if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
- LOCK(cs_main);
+ auto locked_chain = pwallet->chain().lock();
const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
if (!pindex || !chainActive.Contains(pindex)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
@@ -382,7 +385,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
wtx.nIndex = txnIndex;
wtx.hashBlock = merkleBlock.header.GetHash();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (pwallet->IsMine(*wtx.tx)) {
pwallet->AddToWallet(wtx, false);
@@ -412,7 +416,8 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
+ HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
std::vector<uint256> vHash;
@@ -483,7 +488,8 @@ UniValue importpubkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
ImportAddress(pwallet, dest, strLabel);
@@ -535,7 +541,8 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nTimeBegin = 0;
bool fGood = true;
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -653,7 +660,8 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -700,7 +708,8 @@ UniValue dumpwallet(const JSONRPCRequest& request)
+ HelpExampleRpc("dumpwallet", "\"test\"")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -723,7 +732,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
std::map<CTxDestination, int64_t> mapKeyBirth;
const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys();
- pwallet->GetKeyBirthTimes(mapKeyBirth);
+ pwallet->GetKeyBirthTimes(*locked_chain, mapKeyBirth);
std::set<CScriptID> scripts = pwallet->GetCScripts();
// TODO: include scripts in GetKeyBirthTimes() output instead of separate
@@ -1134,7 +1143,8 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
int64_t nLowestTimestamp = 0;
UniValue response(UniValue::VARR);
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
// Verify all timestamps are present before importing any keys.
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 2aeb5c2984..bfac990639 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -8,6 +8,8 @@
#include <consensus/validation.h>
#include <core_io.h>
#include <httpserver.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <validation.h>
#include <key_io.h>
#include <net.h>
@@ -23,8 +25,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>
@@ -89,9 +91,9 @@ void EnsureWalletIsUnlocked(CWallet * const pwallet)
}
}
-static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry)
{
- int confirms = wtx.GetDepthInMainChain();
+ int confirms = wtx.GetDepthInMainChain(locked_chain);
entry.pushKV("confirmations", confirms);
if (wtx.IsCoinBase())
entry.pushKV("generated", true);
@@ -101,7 +103,7 @@ static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) EXCLUSIVE_LOCK
entry.pushKV("blockindex", wtx.nIndex);
entry.pushKV("blocktime", LookupBlockIndex(wtx.hashBlock)->GetBlockTime());
} else {
- entry.pushKV("trusted", wtx.IsTrusted());
+ entry.pushKV("trusted", wtx.IsTrusted(locked_chain));
}
uint256 hash = wtx.GetHash();
entry.pushKV("txid", hash.GetHex());
@@ -290,7 +292,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
}
-static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
+static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
{
CAmount curBalance = pwallet->GetBalance();
@@ -317,7 +319,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
CTransactionRef tx;
- if (!pwallet->CreateTransaction(vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
+ if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
@@ -373,7 +375,8 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (!IsValidDestination(dest)) {
@@ -415,7 +418,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
+ CTransactionRef tx = SendMoney(*locked_chain, pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
return tx->GetHash().GetHex();
}
@@ -455,10 +458,11 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
UniValue jsonGroupings(UniValue::VARR);
- std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
+ std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances(*locked_chain);
for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
for (const CTxDestination& address : grouping)
@@ -508,7 +512,8 @@ static UniValue signmessage(const JSONRPCRequest& request)
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -574,7 +579,9 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Bitcoin address
CTxDestination dest = DecodeDestination(request.params[0].get_str());
@@ -600,7 +607,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
for (const CTxOut& txout : wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey)
- if (wtx.GetDepthInMainChain() >= nMinDepth)
+ if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth)
nAmount += txout.nValue;
}
@@ -641,7 +648,9 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Minimum confirmations
int nMinDepth = 1;
@@ -663,7 +672,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
- if (wtx.GetDepthInMainChain() >= nMinDepth)
+ if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth)
nAmount += txout.nValue;
}
}
@@ -707,7 +716,8 @@ static UniValue getbalance(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
const UniValue& dummy_value = request.params[0];
if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
@@ -745,7 +755,8 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
return ValueFromAmount(pwallet->GetUnconfirmedBalance());
}
@@ -806,7 +817,8 @@ static UniValue sendmany(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (pwallet->GetBroadcastTransactions() && !g_connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -892,7 +904,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
int nChangePosRet = -1;
std::string strFailReason;
CTransactionRef tx;
- bool fCreated = pwallet->CreateTransaction(vecSend, tx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
+ bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
@@ -945,7 +957,8 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
throw std::runtime_error(msg);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::string label;
if (!request.params[2].isNull())
@@ -996,8 +1009,10 @@ struct tallyitem
}
};
-static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)
+static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+
// Minimum confirmations
int nMinDepth = 1;
if (!params[0].isNull())
@@ -1031,7 +1046,7 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
- int nDepth = wtx.GetDepthInMainChain();
+ int nDepth = wtx.GetDepthInMainChain(locked_chain);
if (nDepth < nMinDepth)
continue;
@@ -1185,9 +1200,10 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- return ListReceived(pwallet, request.params, false);
+ return ListReceived(*locked_chain, pwallet, request.params, false);
}
static UniValue listreceivedbylabel(const JSONRPCRequest& request)
@@ -1229,9 +1245,10 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- return ListReceived(pwallet, request.params, true);
+ return ListReceived(*locked_chain, pwallet, request.params, true);
}
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
@@ -1251,7 +1268,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
* @param ret The UniValue into which the result is stored.
* @param filter The "is mine" filter bool.
*/
-static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
std::list<COutputEntry> listReceived;
@@ -1279,14 +1296,14 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int n
entry.pushKV("vout", s.vout);
entry.pushKV("fee", ValueFromAmount(-nFee));
if (fLong)
- WalletTxToJSON(wtx, entry);
+ WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
entry.pushKV("abandoned", wtx.isAbandoned());
ret.push_back(entry);
}
}
// Received
- if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ if (listReceived.size() > 0 && wtx.GetDepthInMainChain(locked_chain) >= nMinDepth)
{
for (const COutputEntry& r : listReceived)
{
@@ -1301,9 +1318,9 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int n
MaybePushAddress(entry, r.destination);
if (wtx.IsCoinBase())
{
- if (wtx.GetDepthInMainChain() < 1)
+ if (wtx.GetDepthInMainChain(locked_chain) < 1)
entry.pushKV("category", "orphan");
- else if (wtx.IsImmatureCoinBase())
+ else if (wtx.IsImmatureCoinBase(locked_chain))
entry.pushKV("category", "immature");
else
entry.pushKV("category", "generate");
@@ -1318,7 +1335,7 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, int n
}
entry.pushKV("vout", r.vout);
if (fLong)
- WalletTxToJSON(wtx, entry);
+ WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
ret.push_back(entry);
}
}
@@ -1405,7 +1422,8 @@ UniValue listtransactions(const JSONRPCRequest& request)
UniValue ret(UniValue::VARR);
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
@@ -1413,7 +1431,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second;
- ListTransactions(pwallet, *pwtx, 0, true, ret, filter);
+ ListTransactions(*locked_chain, pwallet, *pwtx, 0, true, ret, filter);
if ((int)ret.size() >= (nCount+nFrom)) break;
}
}
@@ -1505,7 +1523,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
@@ -1548,8 +1567,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
CWalletTx tx = pairWtx.second;
- if (depth == -1 || tx.GetDepthInMainChain() < depth) {
- ListTransactions(pwallet, tx, 0, true, transactions, filter);
+ if (depth == -1 || tx.GetDepthInMainChain(*locked_chain) < depth) {
+ ListTransactions(*locked_chain, pwallet, tx, 0, true, transactions, filter);
}
}
@@ -1566,7 +1585,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
if (it != pwallet->mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(pwallet, it->second, -100000000, true, removed, filter);
+ ListTransactions(*locked_chain, pwallet, it->second, -100000000, true, removed, filter);
}
}
paltindex = paltindex->pprev;
@@ -1640,7 +1659,8 @@ static UniValue gettransaction(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
@@ -1656,7 +1676,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
}
const CWalletTx& wtx = it->second;
- CAmount nCredit = wtx.GetCredit(filter);
+ CAmount nCredit = wtx.GetCredit(*locked_chain, filter);
CAmount nDebit = wtx.GetDebit(filter);
CAmount nNet = nCredit - nDebit;
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
@@ -1665,10 +1685,10 @@ static UniValue gettransaction(const JSONRPCRequest& request)
if (wtx.IsFromMe(filter))
entry.pushKV("fee", ValueFromAmount(nFee));
- WalletTxToJSON(wtx, entry);
+ WalletTxToJSON(pwallet->chain(), *locked_chain, wtx, entry);
UniValue details(UniValue::VARR);
- ListTransactions(pwallet, wtx, 0, false, details, filter);
+ ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter);
entry.pushKV("details", details);
std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags());
@@ -1707,14 +1727,15 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
uint256 hash(ParseHashV(request.params[0], "txid"));
if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
}
- if (!pwallet->AbandonTransaction(hash)) {
+ if (!pwallet->AbandonTransaction(*locked_chain, hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
}
@@ -1746,7 +1767,8 @@ static UniValue backupwallet(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::string strDest = request.params[0].get_str();
if (!pwallet->BackupWallet(strDest)) {
@@ -1782,7 +1804,8 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
unsigned int kpSize = 0;
@@ -1833,7 +1856,8 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
@@ -1911,7 +1935,8 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
@@ -1967,7 +1992,8 @@ static UniValue walletlock(const JSONRPCRequest& request)
);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
@@ -2013,7 +2039,8 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
@@ -2087,7 +2114,8 @@ static UniValue lockunspent(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
@@ -2136,7 +2164,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
}
- if (pwallet->IsSpent(outpt.hash, outpt.n)) {
+ if (pwallet->IsSpent(*locked_chain, outpt.hash, outpt.n)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
}
@@ -2197,7 +2225,8 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listlockunspent", "")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::vector<COutPoint> vOutpts;
pwallet->ListLockedCoins(vOutpts);
@@ -2238,7 +2267,8 @@ static UniValue settxfee(const JSONRPCRequest& request)
);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CAmount nAmount = AmountFromValue(request.params[0]);
CFeeRate tx_fee_rate(nAmount, 1000);
@@ -2293,7 +2323,8 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
UniValue obj(UniValue::VOBJ);
@@ -2405,26 +2436,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(*g_rpc_interfaces->chain, 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(*g_rpc_interfaces->chain, location);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
}
@@ -2458,7 +2489,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;
@@ -2467,17 +2497,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(*g_rpc_interfaces->chain, 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(*g_rpc_interfaces->chain, location, (disable_privatekeys ? (uint64_t)WALLET_FLAG_DISABLE_PRIVATE_KEYS : 0));
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
}
@@ -2563,13 +2593,14 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request)
if (!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->GetBroadcastTransactions()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast");
}
- std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
+ std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(*locked_chain, GetTime(), g_connman.get());
UniValue result(UniValue::VARR);
for (const uint256& txid : txids)
{
@@ -2700,8 +2731,9 @@ static UniValue listunspent(const JSONRPCRequest& request)
UniValue results(UniValue::VARR);
std::vector<COutput> vecOutputs;
{
- LOCK2(cs_main, pwallet->cs_wallet);
- pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ pwallet->AvailableCoins(*locked_chain, vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
}
LOCK(pwallet->cs_wallet);
@@ -3019,10 +3051,11 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
}
// Sign the transaction
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
- return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]);
+ return SignTransaction(pwallet->chain(), mtx, request.params[1], pwallet, false, request.params[2]);
}
static UniValue bumpfee(const JSONRPCRequest& request)
@@ -3124,7 +3157,8 @@ static UniValue bumpfee(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -3264,7 +3298,7 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
CBlockIndex *pindexStop = nullptr;
CBlockIndex *pChainTip = nullptr;
{
- LOCK(cs_main);
+ auto locked_chain = pwallet->chain().lock();
pindexStart = chainActive.Genesis();
pChainTip = chainActive.Tip();
@@ -3288,7 +3322,7 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
// We can't rescan beyond non-pruned blocks, stop and throw an error
if (fPruneMode) {
- LOCK(cs_main);
+ auto locked_chain = pwallet->chain().lock();
CBlockIndex *block = pindexStop ? pindexStop : pChainTip;
while (block && block->nHeight >= pindexStart->nHeight) {
if (!(block->nStatus & BLOCK_HAVE_DATA)) {
@@ -3458,6 +3492,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" \"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"
@@ -3516,6 +3551,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
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()) {
@@ -3686,7 +3722,8 @@ UniValue sethdseed(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Do not do anything to non-HD wallets
if (!pwallet->IsHDEnabled()) {
@@ -3735,24 +3772,34 @@ void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubK
hd_keypaths.emplace(vchPubKey, std::move(info));
}
-bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type, bool sign, bool bip32derivs)
+bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs)
{
LOCK(pwallet->cs_wallet);
// Get all of the previous transactions
bool complete = true;
- for (unsigned int i = 0; i < txConst->vin.size(); ++i) {
- const CTxIn& txin = txConst->vin[i];
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = psbtx.tx->vin[i];
PSBTInput& input = psbtx.inputs.at(i);
- // If we don't know about this input, skip it and let someone else deal with it
- const uint256& txhash = txin.prevout.hash;
- const auto it = pwallet->mapWallet.find(txhash);
- if (it != pwallet->mapWallet.end()) {
- const CWalletTx& wtx = it->second;
- CTxOut utxo = wtx.tx->vout[txin.prevout.n];
- // Update both UTXOs from the wallet.
- input.non_witness_utxo = wtx.tx;
- input.witness_utxo = utxo;
+ if (PSBTInputSigned(input)) {
+ continue;
+ }
+
+ // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
+ if (!input.IsSane()) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "PSBT input is not sane.");
+ }
+
+ // If we have no utxo, grab it from the wallet.
+ if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
+ const uint256& txhash = txin.prevout.hash;
+ const auto it = pwallet->mapWallet.find(txhash);
+ if (it != pwallet->mapWallet.end()) {
+ const CWalletTx& wtx = it->second;
+ // We only need the non_witness_utxo, which is a superset of the witness_utxo.
+ // The signing code will switch to the smaller witness_utxo if this is ok.
+ input.non_witness_utxo = wtx.tx;
+ }
}
// Get the Sighash type
@@ -3760,12 +3807,12 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const C
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Specified Sighash and sighash in PSBT do not match.");
}
- complete &= SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), *psbtx.tx, input, i, sighash_type);
+ complete &= SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), psbtx, i, sighash_type);
}
// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
- for (unsigned int i = 0; i < txConst->vout.size(); ++i) {
- const CTxOut& out = txConst->vout.at(i);
+ for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
+ const CTxOut& out = psbtx.tx->vout.at(i);
PSBTOutput& psbt_out = psbtx.outputs.at(i);
// Fill a SignatureData with output info
@@ -3830,19 +3877,15 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
// Get the sighash type
int nHashType = ParseSighashString(request.params[2]);
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
-
// Fill transaction with our data and also sign
bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
bool bip32derivs = request.params[3].isNull() ? false : request.params[3].get_bool();
- bool complete = FillPSBT(pwallet, psbtx, &txConst, nHashType, sign, bip32derivs);
+ bool complete = FillPSBT(pwallet, psbtx, nHashType, sign, bip32derivs);
UniValue result(UniValue::VOBJ);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
- result.pushKV("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()));
+ result.pushKV("psbt", EncodeBase64(ssTx.str()));
result.pushKV("complete", complete);
return result;
@@ -3934,29 +3977,18 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]);
// Make a blank psbt
- PartiallySignedTransaction psbtx;
- psbtx.tx = rawTx;
- for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
- }
- for (unsigned int i = 0; i < rawTx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
- }
-
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
+ PartiallySignedTransaction psbtx(rawTx);
// Fill transaction with out data but don't sign
bool bip32derivs = request.params[4].isNull() ? false : request.params[4].get_bool();
- FillPSBT(pwallet, psbtx, &txConst, 1, false, bip32derivs);
+ FillPSBT(pwallet, psbtx, 1, false, bip32derivs);
// Serialize the PSBT
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
UniValue result(UniValue::VOBJ);
- result.pushKV("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()));
+ result.pushKV("psbt", EncodeBase64(ssTx.str()));
result.pushKV("fee", ValueFromAmount(fee));
result.pushKV("changepos", change_position);
return result;
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 9b9a159b86..abd7750874 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -30,5 +30,5 @@ bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
UniValue getaddressinfo(const JSONRPCRequest& request);
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
-bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type = 1, bool sign = true, bool bip32derivs = false);
+bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false);
#endif //BITCOIN_WALLET_RPCWALLET_H
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 21857df081..5c65acf601 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -28,7 +28,8 @@ std::vector<std::unique_ptr<CWalletTx>> wtxn;
typedef std::set<CInputCoin> CoinSet;
static std::vector<COutput> vCoins;
-static CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static auto testChain = interfaces::MakeChain();
+static CWallet testWallet(*testChain, WalletLocation(), WalletDatabase::CreateDummy());
static CAmount balance = 0;
CoinEligibilityFilter filter_standard(1, 6, 0);
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index 1453029c9c..3b828d57f9 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -8,6 +8,8 @@
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName): BasicTestingSetup(chainName)
{
+ m_chain_client = MakeWalletClient(*m_chain, {});
+
std::string sep;
sep += fs::path::preferred_separator;
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index 5684adbece..cd47b31da1 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
+#include <interfaces/chain.h>
#include <test/test_bitcoin.h>
@@ -16,6 +17,8 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
fs::path m_datadir;
fs::path m_cwd;
std::map<std::string, fs::path> m_walletdir_path_cases;
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ std::unique_ptr<interfaces::ChainClient> m_chain_client;
};
#endif // BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
index 7048547b2b..5852d3ef84 100644
--- a/src/wallet/test/init_tests.cpp
+++ b/src/wallet/test/init_tests.cpp
@@ -17,7 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(init_tests, InitWalletDirTestingSetup)
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
{
SetWalletDir(m_walletdir_path_cases["default"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == true);
fs::path walletdir = gArgs.GetArg("-walletdir", "");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
@@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
{
SetWalletDir(m_walletdir_path_cases["custom"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == true);
fs::path walletdir = gArgs.GetArg("-walletdir", "");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
@@ -37,28 +37,28 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_does_not_exist)
{
SetWalletDir(m_walletdir_path_cases["nonexistent"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == false);
}
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_directory)
{
SetWalletDir(m_walletdir_path_cases["file"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == false);
}
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_relative)
{
SetWalletDir(m_walletdir_path_cases["relative"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == false);
}
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
{
SetWalletDir(m_walletdir_path_cases["trailing"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == true);
fs::path walletdir = gArgs.GetArg("-walletdir", "");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
@@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
{
SetWalletDir(m_walletdir_path_cases["trailing2"]);
- bool result = g_wallet_init_interface.Verify();
+ bool result = m_chain_client->verify();
BOOST_CHECK(result == true);
fs::path walletdir = gArgs.GetArg("-walletdir", "");
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 34d6e1b87c..9918eeb89f 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>
@@ -59,12 +59,8 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
CDataStream ssData(ParseHex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000"), SER_NETWORK, PROTOCOL_VERSION);
ssData >> psbtx;
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
-
// Fill transaction with our data
- FillPSBT(&m_wallet, psbtx, &txConst, 1, false, true);
+ FillPSBT(&m_wallet, psbtx, SIGHASH_ALL, false, true);
// Get the final tx
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
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..a5fb1db86c 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(*m_chain, WalletLocation(), WalletDatabase::CreateMock())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index ff8ec32b03..e6fe8c9473 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -7,6 +7,8 @@
#include <test/test_bitcoin.h>
+#include <interfaces/chain.h>
+#include <interfaces/wallet.h>
#include <wallet/wallet.h>
#include <memory>
@@ -17,6 +19,7 @@ struct WalletTestingSetup: public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~WalletTestingSetup();
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
CWallet m_wallet;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 3a8e6f751a..c6aac8aad5 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -11,6 +11,7 @@
#include <vector>
#include <consensus/validation.h>
+#include <interfaces/chain.h>
#include <rpc/server.h>
#include <test/test_bitcoin.h>
#include <validation.h>
@@ -34,6 +35,8 @@ static void AddKey(CWallet& wallet, const CKey& key)
BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
{
+ auto chain = interfaces::MakeChain();
+
// Cap last block file size, and mine new block in a new block file.
CBlockIndex* const nullBlock = nullptr;
CBlockIndex* oldTip = chainActive.Tip();
@@ -41,12 +44,12 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = chainActive.Tip();
- LOCK(cs_main);
+ auto locked_chain = chain->lock();
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
@@ -61,7 +64,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
@@ -73,7 +76,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>(*chain, WalletLocation(), WalletDatabase::CreateDummy());
AddWallet(wallet);
UniValue keys;
keys.setArray();
@@ -115,6 +118,8 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// than or equal to key birthday.
BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
{
+ auto chain = interfaces::MakeChain();
+
// Create two blocks with same timestamp to verify that importwallet rescan
// will pick up both blocks, not just the first.
const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5;
@@ -128,13 +133,13 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- LOCK(cs_main);
+ auto locked_chain = chain->lock();
std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string();
// 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>(*chain, WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet->cs_wallet);
wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
@@ -150,7 +155,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>(*chain, WalletLocation(), WalletDatabase::CreateDummy());
JSONRPCRequest request;
request.params.setArray();
@@ -180,21 +185,23 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ auto chain = interfaces::MakeChain();
+ CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy());
CWalletTx wtx(&wallet, m_coinbase_txns.back());
- LOCK2(cs_main, wallet.cs_wallet);
+ auto locked_chain = chain->lock();
+ LOCK(wallet.cs_wallet);
wtx.hashBlock = chainActive.Tip()->GetBlockHash();
wtx.nIndex = 0;
// Call GetImmatureCredit() once before adding the key to the wallet to
// cache the current immature credit amount, which is 0.
- BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 0);
+ BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 0);
// Invalidate the cached value, add the key, and make sure a new immature
// credit amount is calculated.
wtx.MarkDirty();
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
- BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 50*COIN);
+ BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50*COIN);
}
static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
@@ -204,7 +211,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
SetMockTime(mockTime);
CBlockIndex* block = nullptr;
if (blockTime > 0) {
- LOCK(cs_main);
+ auto locked_chain = wallet.chain().lock();
auto inserted = mapBlockIndex.emplace(GetRandHash(), new CBlockIndex);
assert(inserted.second);
const uint256& hash = inserted.first->first;
@@ -273,7 +280,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>("mock", WalletDatabase::CreateMock());
+ wallet = MakeUnique<CWallet>(*m_chain, WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
AddKey(*wallet, coinbaseKey);
@@ -295,7 +302,7 @@ public:
int changePos = -1;
std::string error;
CCoinControl dummy;
- BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, reservekey, fee, changePos, error, dummy));
+ BOOST_CHECK(wallet->CreateTransaction(*m_locked_chain, {recipient}, tx, reservekey, fee, changePos, error, dummy));
CValidationState state;
BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, nullptr, state));
CMutableTransaction blocktx;
@@ -311,6 +318,8 @@ public:
return it->second;
}
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ std::unique_ptr<interfaces::Chain::Lock> m_locked_chain = m_chain->assumeLocked(); // Temporary. Removed in upcoming lock cleanup
std::unique_ptr<CWallet> wallet;
};
@@ -323,7 +332,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
std::map<CTxDestination, std::vector<COutput>> list;
{
LOCK2(cs_main, wallet->cs_wallet);
- list = wallet->ListCoins();
+ list = wallet->ListCoins(*m_locked_chain);
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
@@ -339,7 +348,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */});
{
LOCK2(cs_main, wallet->cs_wallet);
- list = wallet->ListCoins();
+ list = wallet->ListCoins(*m_locked_chain);
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
@@ -349,7 +358,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
{
LOCK2(cs_main, wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(available);
+ wallet->AvailableCoins(*m_locked_chain, available);
BOOST_CHECK_EQUAL(available.size(), 2U);
}
for (const auto& group : list) {
@@ -361,14 +370,14 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
{
LOCK2(cs_main, wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(available);
+ wallet->AvailableCoins(*m_locked_chain, available);
BOOST_CHECK_EQUAL(available.size(), 0U);
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
{
LOCK2(cs_main, wallet->cs_wallet);
- list = wallet->ListCoins();
+ list = wallet->ListCoins(*m_locked_chain);
}
BOOST_CHECK_EQUAL(list.size(), 1U);
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
@@ -377,7 +386,8 @@ 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());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, 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 29014790e9..8ea4c5c495 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -11,6 +11,7 @@
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <fs.h>
+#include <interfaces/chain.h>
#include <key.h>
#include <key_io.h>
#include <keystore.h>
@@ -25,9 +26,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>
@@ -594,7 +594,7 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
* Outpoint is spent if any non-conflicted transaction
* spends it:
*/
-bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
+bool CWallet::IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const
{
const COutPoint outpoint(hash, n);
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
@@ -605,7 +605,7 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) {
- int depth = mit->second.GetDepthInMainChain();
+ int depth = mit->second.GetDepthInMainChain(locked_chain);
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
return true; // Spent
}
@@ -1006,9 +1006,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
const CWalletTx* wtx = GetWalletTx(hashTx);
- return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
+ return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain(*locked_chain) == 0 && !wtx->InMempool();
}
void CWallet::MarkInputsDirty(const CTransactionRef& tx)
@@ -1021,9 +1022,10 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx)
}
}
-bool CWallet::AbandonTransaction(const uint256& hashTx)
+bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx)
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain_recursive = chain().lock(); // Temporary. Removed in upcoming lock cleanup
+ LOCK(cs_wallet);
WalletBatch batch(*database, "r+");
@@ -1034,7 +1036,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
auto it = mapWallet.find(hashTx);
assert(it != mapWallet.end());
CWalletTx& origtx = it->second;
- if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
+ if (origtx.GetDepthInMainChain(locked_chain) != 0 || origtx.InMempool()) {
return false;
}
@@ -1047,7 +1049,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
auto it = mapWallet.find(now);
assert(it != mapWallet.end());
CWalletTx& wtx = it->second;
- int currentconfirm = wtx.GetDepthInMainChain();
+ int currentconfirm = wtx.GetDepthInMainChain(locked_chain);
// If the orig tx was not in block, none of its spends can be
assert(currentconfirm <= 0);
// if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
@@ -1078,7 +1080,8 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
int conflictconfirms = 0;
CBlockIndex* pindex = LookupBlockIndex(hashBlock);
@@ -1107,7 +1110,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
auto it = mapWallet.find(now);
assert(it != mapWallet.end());
CWalletTx& wtx = it->second;
- int currentconfirm = wtx.GetDepthInMainChain();
+ int currentconfirm = wtx.GetDepthInMainChain(*locked_chain);
if (conflictconfirms < currentconfirm) {
// Block is 'more conflicted' than current confirm; update.
// Mark transaction as conflicted with this block.
@@ -1141,7 +1144,8 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin
}
void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
SyncTransaction(ptx);
auto it = mapWallet.find(ptx->GetHash());
@@ -1159,7 +1163,8 @@ void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
}
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
// TODO: Temporarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
@@ -1181,7 +1186,8 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
}
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const CTransactionRef& ptx : pblock->vtx) {
SyncTransaction(ptx);
@@ -1200,7 +1206,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
// We could also take cs_wallet here, and call m_last_block_processed
// protected by cs_wallet instead of cs_main, but as long as we need
// cs_main here anyway, it's easier to just call it cs_main-protected.
- LOCK(cs_main);
+ auto locked_chain = chain().lock();
const CBlockIndex* initialChainTip = chainActive.Tip();
if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
@@ -1262,6 +1268,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 +1280,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);
@@ -1596,7 +1607,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
// to be scanned.
CBlockIndex* startBlock = nullptr;
{
- LOCK(cs_main);
+ auto locked_chain = chain().lock();
startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
}
@@ -1648,7 +1659,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
double progress_begin;
double progress_end;
{
- LOCK(cs_main);
+ auto locked_chain = chain().lock();
progress_begin = GuessVerificationProgress(chainParams.TxData(), pindex);
if (pindexStop == nullptr) {
tip = chainActive.Tip();
@@ -1670,7 +1681,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
CBlock block;
if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
if (pindex && !chainActive.Contains(pindex)) {
// Abort scan if current block is no longer active, to prevent
// marking transactions as coming from the wrong block.
@@ -1687,7 +1699,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
break;
}
{
- LOCK(cs_main);
+ auto locked_chain = chain().lock();
pindex = chainActive.Next(pindex);
progress_current = GuessVerificationProgress(chainParams.TxData(), pindex);
if (pindexStop == nullptr && tip != chainActive.Tip()) {
@@ -1712,7 +1724,8 @@ void CWallet::ReacceptWalletTransactions()
// If transactions aren't being broadcasted, don't let them into local mempool either
if (!fBroadcastTransactions)
return;
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
std::map<int64_t, CWalletTx*> mapSorted;
// Sort pending wallet transactions based on their initial wallet insertion order
@@ -1722,7 +1735,7 @@ void CWallet::ReacceptWalletTransactions()
CWalletTx& wtx = item.second;
assert(wtx.GetHash() == wtxid);
- int nDepth = wtx.GetDepthInMainChain();
+ int nDepth = wtx.GetDepthInMainChain(*locked_chain);
if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
@@ -1733,18 +1746,18 @@ void CWallet::ReacceptWalletTransactions()
for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
CWalletTx& wtx = *(item.second);
CValidationState state;
- wtx.AcceptToMemoryPool(maxTxFee, state);
+ wtx.AcceptToMemoryPool(*locked_chain, maxTxFee, state);
}
}
-bool CWalletTx::RelayWalletTransaction(CConnman* connman)
+bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain, CConnman* connman)
{
assert(pwallet->GetBroadcastTransactions());
- if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain() == 0)
+ if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain(locked_chain) == 0)
{
CValidationState state;
/* GetDepthInMainChain already catches known conflicts. */
- if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) {
+ if (InMempool() || AcceptToMemoryPool(locked_chain, maxTxFee, state)) {
pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString());
if (connman) {
CInv inv(MSG_TX, GetHash());
@@ -1802,10 +1815,10 @@ CAmount CWalletTx::GetDebit(const isminefilter& filter) const
return debit;
}
-CAmount CWalletTx::GetCredit(const isminefilter& filter) const
+CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsImmatureCoinBase())
+ if (IsImmatureCoinBase(locked_chain))
return 0;
CAmount credit = 0;
@@ -1835,9 +1848,9 @@ CAmount CWalletTx::GetCredit(const isminefilter& filter) const
return credit;
}
-CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
+CAmount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache) const
{
- if (IsImmatureCoinBase() && IsInMainChain()) {
+ if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
if (fUseCache && fImmatureCreditCached)
return nImmatureCreditCached;
nImmatureCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE);
@@ -1848,13 +1861,13 @@ CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
return 0;
}
-CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const
+CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache, const isminefilter& filter) const
{
if (pwallet == nullptr)
return 0;
// Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsImmatureCoinBase())
+ if (IsImmatureCoinBase(locked_chain))
return 0;
CAmount* cache = nullptr;
@@ -1876,7 +1889,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
uint256 hashTx = GetHash();
for (unsigned int i = 0; i < tx->vout.size(); i++)
{
- if (!pwallet->IsSpent(hashTx, i))
+ if (!pwallet->IsSpent(locked_chain, hashTx, i))
{
const CTxOut &txout = tx->vout[i];
nCredit += pwallet->GetCredit(txout, filter);
@@ -1893,9 +1906,9 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
return nCredit;
}
-CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
+CAmount CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache) const
{
- if (IsImmatureCoinBase() && IsInMainChain()) {
+ if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
if (fUseCache && fImmatureWatchCreditCached)
return nImmatureWatchCreditCached;
nImmatureWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY);
@@ -1920,12 +1933,14 @@ bool CWalletTx::InMempool() const
return fInMempool;
}
-bool CWalletTx::IsTrusted() const
+bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const
{
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+
// Quick answer in most cases
if (!CheckFinalTx(*tx))
return false;
- int nDepth = GetDepthInMainChain();
+ int nDepth = GetDepthInMainChain(locked_chain);
if (nDepth >= 1)
return true;
if (nDepth < 0)
@@ -1960,7 +1975,7 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
return CTransaction(tx1) == CTransaction(tx2);
}
-std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman)
+std::vector<uint256> CWallet::ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime, CConnman* connman)
{
std::vector<uint256> result;
@@ -1979,7 +1994,7 @@ std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon
for (const std::pair<const unsigned int, CWalletTx*>& item : mapSorted)
{
CWalletTx& wtx = *item.second;
- if (wtx.RelayWalletTransaction(connman))
+ if (wtx.RelayWalletTransaction(locked_chain, connman))
result.push_back(wtx.GetHash());
}
return result;
@@ -2003,7 +2018,8 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
// Rebroadcast unconfirmed txes older than 5 minutes before the last
// block was found:
- std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60, connman);
+ auto locked_chain = chain().assumeLocked(); // Temporary. Removed in upcoming lock cleanup
+ std::vector<uint256> relayed = ResendWalletTransactionsBefore(*locked_chain, nBestBlockTime-5*60, connman);
if (!relayed.empty())
WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
}
@@ -2023,12 +2039,13 @@ CAmount CWallet::GetBalance(const isminefilter& filter, const int min_depth) con
{
CAmount nTotal = 0;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx* pcoin = &entry.second;
- if (pcoin->IsTrusted() && pcoin->GetDepthInMainChain() >= min_depth) {
- nTotal += pcoin->GetAvailableCredit(true, filter);
+ if (pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) >= min_depth) {
+ nTotal += pcoin->GetAvailableCredit(*locked_chain, true, filter);
}
}
}
@@ -2040,12 +2057,13 @@ CAmount CWallet::GetUnconfirmedBalance() const
{
CAmount nTotal = 0;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx* pcoin = &entry.second;
- if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
- nTotal += pcoin->GetAvailableCredit();
+ if (!pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) == 0 && pcoin->InMempool())
+ nTotal += pcoin->GetAvailableCredit(*locked_chain);
}
}
return nTotal;
@@ -2055,11 +2073,12 @@ CAmount CWallet::GetImmatureBalance() const
{
CAmount nTotal = 0;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx* pcoin = &entry.second;
- nTotal += pcoin->GetImmatureCredit();
+ nTotal += pcoin->GetImmatureCredit(*locked_chain);
}
}
return nTotal;
@@ -2069,12 +2088,13 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
{
CAmount nTotal = 0;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx* pcoin = &entry.second;
- if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
- nTotal += pcoin->GetAvailableCredit(true, ISMINE_WATCH_ONLY);
+ if (!pcoin->IsTrusted(*locked_chain) && pcoin->GetDepthInMainChain(*locked_chain) == 0 && pcoin->InMempool())
+ nTotal += pcoin->GetAvailableCredit(*locked_chain, true, ISMINE_WATCH_ONLY);
}
}
return nTotal;
@@ -2084,11 +2104,12 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
{
CAmount nTotal = 0;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx* pcoin = &entry.second;
- nTotal += pcoin->GetImmatureWatchOnlyCredit();
+ nTotal += pcoin->GetImmatureWatchOnlyCredit(*locked_chain);
}
}
return nTotal;
@@ -2102,13 +2123,15 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
// trusted.
CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const
{
- LOCK2(cs_main, cs_wallet);
+ LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CAmount balance = 0;
for (const auto& entry : mapWallet) {
const CWalletTx& wtx = entry.second;
- const int depth = wtx.GetDepthInMainChain();
- if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.IsImmatureCoinBase()) {
+ const int depth = wtx.GetDepthInMainChain(*locked_chain);
+ if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.IsImmatureCoinBase(*locked_chain)) {
continue;
}
@@ -2135,11 +2158,12 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) cons
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CAmount balance = 0;
std::vector<COutput> vCoins;
- AvailableCoins(vCoins, true, coinControl);
+ AvailableCoins(*locked_chain, vCoins, true, coinControl);
for (const COutput& out : vCoins) {
if (out.fSpendable) {
balance += out.tx->tx->vout[out.i].nValue;
@@ -2148,7 +2172,7 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
return balance;
}
-void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const
+void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const
{
AssertLockHeld(cs_main);
AssertLockHeld(cs_wallet);
@@ -2164,10 +2188,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (!CheckFinalTx(*pcoin->tx))
continue;
- if (pcoin->IsImmatureCoinBase())
+ if (pcoin->IsImmatureCoinBase(locked_chain))
continue;
- int nDepth = pcoin->GetDepthInMainChain();
+ int nDepth = pcoin->GetDepthInMainChain(locked_chain);
if (nDepth < 0)
continue;
@@ -2176,7 +2200,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (nDepth == 0 && !pcoin->InMempool())
continue;
- bool safeTx = pcoin->IsTrusted();
+ bool safeTx = pcoin->IsTrusted(locked_chain);
// We should not consider coins from transactions that are replacing
// other transactions.
@@ -2226,7 +2250,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (IsLockedCoin(entry.first, i))
continue;
- if (IsSpent(wtxid, i))
+ if (IsSpent(locked_chain, wtxid, i))
continue;
isminetype mine = IsMine(pcoin->tx->vout[i]);
@@ -2257,7 +2281,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
}
}
-std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
+std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Chain::Lock& locked_chain) const
{
AssertLockHeld(cs_main);
AssertLockHeld(cs_wallet);
@@ -2265,7 +2289,7 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
std::map<CTxDestination, std::vector<COutput>> result;
std::vector<COutput> availableCoins;
- AvailableCoins(availableCoins);
+ AvailableCoins(locked_chain, availableCoins);
for (const COutput& coin : availableCoins) {
CTxDestination address;
@@ -2280,7 +2304,7 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
for (const COutPoint& output : lockedCoins) {
auto it = mapWallet.find(output.hash);
if (it != mapWallet.end()) {
- int depth = it->second.GetDepthInMainChain();
+ int depth = it->second.GetDepthInMainChain(locked_chain);
if (depth >= 0 && output.n < it->second.tx->vout.size() &&
IsMine(it->second.tx->vout[output.n]) == ISMINE_SPENDABLE) {
CTxDestination address;
@@ -2495,11 +2519,12 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
// Acquire the locks to prevent races to the new locked unspents between the
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CReserveKey reservekey(this);
CTransactionRef tx_new;
- if (!CreateTransaction(vecSend, tx_new, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
+ if (!CreateTransaction(*locked_chain, vecSend, tx_new, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
return false;
}
@@ -2558,7 +2583,7 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec
return m_default_address_type;
}
-bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet,
+bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet,
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
{
CAmount nValue = 0;
@@ -2620,10 +2645,11 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
int nBytes;
{
std::set<CInputCoin> setCoins;
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
{
std::vector<COutput> vAvailableCoins;
- AvailableCoins(vAvailableCoins, true, &coin_control);
+ AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control);
CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
// Create change script that will be used if we need change
@@ -2958,7 +2984,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state)
{
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CWalletTx wtxNew(this, std::move(tx));
wtxNew.mapValue = std::move(mapValue);
@@ -2991,11 +3018,11 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
if (fBroadcastTransactions)
{
// Broadcast
- if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
+ if (!wtx.AcceptToMemoryPool(*locked_chain, maxTxFee, state)) {
WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
} else {
- wtx.RelayWalletTransaction(connman);
+ wtx.RelayWalletTransaction(*locked_chain, connman);
}
}
}
@@ -3004,7 +3031,8 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
fFirstRunRet = false;
DBErrors nLoadWalletRet = WalletBatch(*database,"cr+").LoadWallet(this);
@@ -3388,7 +3416,7 @@ int64_t CWallet::GetOldestKeyPoolTime()
return oldestKey;
}
-std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
+std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain)
{
std::map<CTxDestination, CAmount> balances;
@@ -3398,13 +3426,13 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
{
const CWalletTx *pcoin = &walletEntry.second;
- if (!pcoin->IsTrusted())
+ if (!pcoin->IsTrusted(locked_chain))
continue;
- if (pcoin->IsImmatureCoinBase())
+ if (pcoin->IsImmatureCoinBase(locked_chain))
continue;
- int nDepth = pcoin->GetDepthInMainChain();
+ int nDepth = pcoin->GetDepthInMainChain(locked_chain);
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
continue;
@@ -3416,7 +3444,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr))
continue;
- CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
+ CAmount n = IsSpent(locked_chain, walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
if (!balances.count(addr))
balances[addr] = 0;
@@ -3641,7 +3669,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
/** @} */ // end of Actions
-void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const {
+void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CTxDestination, int64_t> &mapKeyBirth) const {
AssertLockHeld(cs_wallet); // mapKeyMetadata
mapKeyBirth.clear();
@@ -3821,7 +3849,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(interfaces::Chain& chain, 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 +3858,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 +3884,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(chain, WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename;
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false;
@@ -3872,9 +3900,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(interfaces::Chain& chain, 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 +3910,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>(chain, 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 +3924,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(chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
@@ -4006,6 +4034,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
return nullptr;
}
+ auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup
walletInstance->ChainStateFlushed(chainActive.GetLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
@@ -4093,7 +4122,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
- LOCK2(cs_main, walletInstance->cs_wallet);
+ LockAnnotation lock(::cs_main); // Temporary, for FindForkInGlobalIndex below. Removed in upcoming commit.
+ auto locked_chain = chain.lock();
+ LOCK(walletInstance->cs_wallet);
CBlockIndex *pindexRescan = chainActive.Genesis();
if (!gArgs.GetBoolArg("-rescan", false))
@@ -4228,7 +4259,7 @@ void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
nIndex = posInBlock;
}
-int CMerkleTx::GetDepthInMainChain() const
+int CMerkleTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const
{
if (hashUnset())
return 0;
@@ -4243,23 +4274,25 @@ int CMerkleTx::GetDepthInMainChain() const
return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
}
-int CMerkleTx::GetBlocksToMaturity() const
+int CMerkleTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const
{
if (!IsCoinBase())
return 0;
- int chain_depth = GetDepthInMainChain();
+ int chain_depth = GetDepthInMainChain(locked_chain);
assert(chain_depth >= 0); // coinbase tx should not be conflicted
return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
}
-bool CMerkleTx::IsImmatureCoinBase() const
+bool CMerkleTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const
{
// note GetBlocksToMaturity is 0 for non-coinbase tx
- return GetBlocksToMaturity() > 0;
+ return GetBlocksToMaturity(locked_chain) > 0;
}
-bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
+bool CWalletTx::AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, const CAmount& nAbsurdFee, CValidationState& state)
{
+ LockAnnotation lock(::cs_main); // Temporary, for AcceptToMemoryPool below. Removed in upcoming commit.
+
// We must set fInMempool here - while it will be re-set to true by the
// entered-mempool callback, if we did not there would be a race where a
// user could call sendmoney in a loop and hit spurious out of funds errors
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index e6e23ab247..f96798201f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -7,20 +7,21 @@
#define BITCOIN_WALLET_WALLET_H
#include <amount.h>
+#include <interfaces/chain.h>
#include <outputtype.h>
#include <policy/feerate.h>
#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>
@@ -33,6 +34,26 @@
#include <utility>
#include <vector>
+//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
+// This function will perform salvage on the wallet if requested, as long as only one wallet is
+// being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
+
+//! Load wallet databases.
+bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
+
+//! Complete startup of wallets.
+void StartWallets(CScheduler& scheduler);
+
+//! Flush all wallets in preparation for shutdown.
+void FlushWallets();
+
+//! Stop all wallets. Wallets will be flushed first.
+void StopWallets();
+
+//! Close all wallets.
+void UnloadWallets();
+
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
@@ -264,22 +285,22 @@ public:
* 0 : in memory pool, waiting to be included in a block
* >=1 : this many blocks deep in the main chain
*/
- int GetDepthInMainChain() const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool IsInMainChain() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return GetDepthInMainChain() > 0; }
+ int GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const;
+ bool IsInMainChain(interfaces::Chain::Lock& locked_chain) const { return GetDepthInMainChain(locked_chain) > 0; }
/**
* @return number of blocks to maturity for this transaction:
* 0 : is not a coinbase transaction, or is a mature coinbase transaction
* >0 : is a coinbase transaction which matures in this many blocks
*/
- int GetBlocksToMaturity() const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ int GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const;
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
void setAbandoned() { hashBlock = ABANDON_HASH; }
const uint256& GetHash() const { return tx->GetHash(); }
bool IsCoinBase() const { return tx->IsCoinBase(); }
- bool IsImmatureCoinBase() const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const;
};
//Get the marginal bytes of spending the specified output
@@ -458,14 +479,14 @@ public:
//! filter decides which addresses will count towards the debit
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 GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const;
+ CAmount GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true) const;
// 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 GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
+ CAmount GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache=true) const;
CAmount GetChange() const;
// Get the marginal bytes if spending the specified output from this transaction
@@ -486,15 +507,15 @@ public:
bool IsEquivalentTo(const CWalletTx& tx) const;
bool InMempool() const;
- bool IsTrusted() const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool IsTrusted(interfaces::Chain::Lock& locked_chain) const;
int64_t GetTxTime() const;
// RelayWalletTransaction may only be called if fBroadcastTransactions!
- bool RelayWalletTransaction(CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool RelayWalletTransaction(interfaces::Chain::Lock& locked_chain, CConnman* connman);
/** 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);
+ bool AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, const CAmount& nAbsurdFee, CValidationState& state);
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
@@ -676,12 +697,11 @@ 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;
+ /** Interface for accessing chain state. */
+ interfaces::Chain& m_chain;
+
+ /** Wallet location which includes wallet name (see WalletLocation). */
+ WalletLocation m_location;
/** Internal database handle. */
std::unique_ptr<WalletDatabase> database;
@@ -721,9 +741,11 @@ public:
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 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() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -739,7 +761,7 @@ public:
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(interfaces::Chain& chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_chain(chain), m_location(location), database(std::move(database))
{
}
@@ -761,6 +783,9 @@ public:
std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
+ /** Interface for accessing chain state. */
+ interfaces::Chain& chain() const { return m_chain; }
+
const CWalletTx* GetWalletTx(const uint256& hash) const;
//! check whether we are allowed to upgrade (or already support) to the named feature
@@ -769,12 +794,12 @@ public:
/**
* populate vCoins with vector of available COutputs.
*/
- void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_main, cs_wallet);
+ void AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Return list of available coins and locked coins grouped by non-change output address.
*/
- std::map<CTxDestination, std::vector<COutput>> ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_main, cs_wallet);
+ std::map<CTxDestination, std::vector<COutput>> ListCoins(interfaces::Chain::Lock& locked_chain) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Find non-change parent output.
@@ -790,7 +815,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, cs_wallet);
+ bool IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(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);
@@ -854,7 +879,7 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
- void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CTxDestination, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
@@ -876,7 +901,7 @@ public:
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// ResendWalletTransactionsBefore may only be called if fBroadcastTransactions!
- std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ std::vector<uint256> ResendWalletTransactionsBefore(interfaces::Chain::Lock& locked_chain, int64_t nTime, CConnman* connman);
CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const;
CAmount GetUnconfirmedBalance() const;
CAmount GetImmatureBalance() const;
@@ -899,7 +924,7 @@ public:
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
+ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
@@ -958,7 +983,7 @@ public:
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::map<CTxDestination, CAmount> GetAddressBalances() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ std::map<CTxDestination, CAmount> GetAddressBalances(interfaces::Chain::Lock& locked_chain);
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
@@ -971,6 +996,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 */
@@ -1052,16 +1078,16 @@ public:
bool TransactionCanBeAbandoned(const uint256& hashTx) const;
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
- bool AbandonTransaction(const uint256& hashTx);
+ bool AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx);
/** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
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(interfaces::Chain& chain, 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(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0);
/**
* Wallet post-init setup
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 d66d8a3775..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()
{
@@ -80,3 +80,14 @@ std::vector<fs::path> ListWalletDir()
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/walletinitinterface.h b/src/walletinitinterface.h
index 6f12551273..22aca65990 100644
--- a/src/walletinitinterface.h
+++ b/src/walletinitinterface.h
@@ -9,6 +9,7 @@
class CScheduler;
class CRPCTable;
+struct InitInterfaces;
class WalletInitInterface {
public:
@@ -18,20 +19,8 @@ public:
virtual void AddWalletOptions() const = 0;
/** Check wallet parameter interaction */
virtual bool ParameterInteraction() const = 0;
- /** Register wallet RPC*/
- virtual void RegisterRPC(CRPCTable &) const = 0;
- /** Verify wallets */
- virtual bool Verify() const = 0;
- /** Open wallets*/
- virtual bool Open() const = 0;
- /** Start wallets*/
- virtual void Start(CScheduler& scheduler) const = 0;
- /** Flush Wallets*/
- virtual void Flush() const = 0;
- /** Stop Wallets*/
- virtual void Stop() const = 0;
- /** Close wallets */
- virtual void Close() const = 0;
+ /** Add wallets that should be opened to list of init interfaces. */
+ virtual void Construct(InitInterfaces& interfaces) const = 0;
virtual ~WalletInitInterface() {}
};
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 39cc8968d2..6a9661e3e8 100644
--- a/src/zmq/zmqabstractnotifier.cpp
+++ b/src/zmq/zmqabstractnotifier.cpp
@@ -3,8 +3,9 @@
// 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;
CZMQAbstractNotifier::~CZMQAbstractNotifier()
{
diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h
index 5081c6cd02..887dde7b27 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -15,7 +15,9 @@ typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)();
class CZMQAbstractNotifier
{
public:
- CZMQAbstractNotifier() : psocket(nullptr) { }
+ static const int DEFAULT_ZMQ_SNDHWM {1000};
+
+ CZMQAbstractNotifier() : psocket(nullptr), outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) { }
virtual ~CZMQAbstractNotifier();
template <typename T>
@@ -28,6 +30,12 @@ public:
void SetType(const std::string &t) { type = t; }
std::string GetAddress() const { return address; }
void SetAddress(const std::string &a) { address = a; }
+ int GetOutboundMessageHighWaterMark() const { return outbound_message_high_water_mark; }
+ void SetOutboundMessageHighWaterMark(const int sndhwm) {
+ if (sndhwm >= 0) {
+ outbound_message_high_water_mark = sndhwm;
+ }
+ }
virtual bool Initialize(void *pcontext) = 0;
virtual void Shutdown() = 0;
@@ -39,6 +47,7 @@ protected:
void *psocket;
std::string type;
std::string address;
+ int outbound_message_high_water_mark; // aka SNDHWM
};
#endif // BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 1d9f86d450..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)
{
@@ -59,6 +59,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
CZMQAbstractNotifier *notifier = factory();
notifier->SetType(entry.first);
notifier->SetAddress(address);
+ notifier->SetOutboundMessageHighWaterMark(static_cast<int>(gArgs.GetArg(arg + "hwm", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM)));
notifiers.push_back(notifier);
}
}
@@ -102,11 +103,11 @@ bool CZMQNotificationInterface::Initialize()
CZMQAbstractNotifier *notifier = *i;
if (notifier->Initialize(pcontext))
{
- LogPrint(BCLog::ZMQ, " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
}
else
{
- LogPrint(BCLog::ZMQ, " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
break;
}
}
@@ -128,7 +129,7 @@ void CZMQNotificationInterface::Shutdown()
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
{
CZMQAbstractNotifier *notifier = *i;
- LogPrint(BCLog::ZMQ, " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
notifier->Shutdown();
}
zmq_ctx_term(pcontext);
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 36a6458f67..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;
@@ -76,8 +76,18 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
return false;
}
- int rc = zmq_bind(psocket, address.c_str());
- if (rc!=0)
+ LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);
+
+ int rc = zmq_setsockopt(psocket, ZMQ_SNDHWM, &outbound_message_high_water_mark, sizeof(outbound_message_high_water_mark));
+ if (rc != 0)
+ {
+ zmqError("Failed to set outbound message high water mark");
+ zmq_close(psocket);
+ return false;
+ }
+
+ rc = zmq_bind(psocket, address.c_str());
+ if (rc != 0)
{
zmqError("Failed to bind address");
zmq_close(psocket);
@@ -120,7 +130,7 @@ void CZMQAbstractPublishNotifier::Shutdown()
if (count == 1)
{
- LogPrint(BCLog::ZMQ, "Close socket at address %s\n", address);
+ LogPrint(BCLog::ZMQ, "zmq: Close socket at address %s\n", address);
int linger = 0;
zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
zmq_close(psocket);
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index 0f5b43d726..278fdb94d2 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -12,7 +12,7 @@ class CBlockIndex;
class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
{
private:
- uint32_t nSequence; //!< upcounting per message sequence number
+ uint32_t nSequence {0U}; //!< upcounting per message sequence number
public:
diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp
index 4f88bf4eb9..0e0b745375 100644
--- a/src/zmq/zmqrpc.cpp
+++ b/src/zmq/zmqrpc.cpp
@@ -22,7 +22,8 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
"[\n"
" { (json object)\n"
" \"type\": \"pubhashtx\", (string) Type of notification\n"
- " \"address\": \"...\" (string) Address of the publisher\n"
+ " \"address\": \"...\", (string) Address of the publisher\n"
+ " \"hwm\": n (numeric) Outbound message high water mark\n"
" },\n"
" ...\n"
"]\n"
@@ -38,6 +39,7 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ);
obj.pushKV("type", n->GetType());
obj.pushKV("address", n->GetAddress());
+ obj.pushKV("hwm", n->GetOutboundMessageHighWaterMark());
result.push_back(obj);
}
}