aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/bench/block_assemble.cpp116
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/bitcoind.cpp3
-rw-r--r--src/core_io.h1
-rw-r--r--src/core_read.cpp8
-rw-r--r--src/crypto/sha256.cpp129
-rw-r--r--src/init.cpp59
-rw-r--r--src/interfaces/wallet.cpp4
-rw-r--r--src/interfaces/wallet.h4
-rw-r--r--src/miner.cpp4
-rw-r--r--src/netbase.cpp6
-rw-r--r--src/primitives/transaction.h5
-rw-r--r--src/qt/README.md8
-rw-r--r--src/qt/addressbookpage.cpp5
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp54
-rw-r--r--src/qt/bitcoingui.cpp92
-rw-r--r--src/qt/bitcoingui.h101
-rw-r--r--src/qt/coincontroldialog.cpp10
-rw-r--r--src/qt/guiutil.cpp32
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/macdockiconhandler.mm8
-rw-r--r--src/qt/networkstyle.cpp4
-rw-r--r--src/qt/openuridialog.cpp2
-rw-r--r--src/qt/optionsdialog.cpp12
-rw-r--r--src/qt/paymentrequestplus.cpp2
-rw-r--r--src/qt/paymentserver.cpp15
-rw-r--r--src/qt/peertablemodel.cpp2
-rw-r--r--src/qt/platformstyle.cpp2
-rw-r--r--src/qt/receiverequestdialog.cpp3
-rwxr-xr-xsrc/qt/res/movies/makespinner.sh1
-rw-r--r--src/qt/rpcconsole.cpp14
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/test/test_main.cpp7
-rw-r--r--src/qt/test/wallettests.cpp13
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp1
-rw-r--r--src/qt/walletmodel.cpp8
-rw-r--r--src/qt/walletmodel.h4
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/qt/winshutdownmonitor.h2
-rw-r--r--src/rpc/blockchain.cpp6
-rw-r--r--src/rpc/mining.cpp13
-rw-r--r--src/rpc/net.cpp2
-rw-r--r--src/test/mempool_tests.cpp15
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/txmempool.h2
-rw-r--r--src/util.cpp7
-rw-r--r--src/util.h5
-rw-r--r--src/validation.cpp28
-rw-r--r--src/validation.h19
-rw-r--r--src/wallet/db.cpp5
-rw-r--r--src/wallet/init.cpp2
-rw-r--r--src/wallet/rpcdump.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp114
-rw-r--r--src/wallet/wallet.cpp44
-rw-r--r--src/wallet/wallet.h4
61 files changed, 595 insertions, 438 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e03c21f16e..a2599d33e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -235,6 +235,7 @@ libbitcoin_server_a_SOURCES = \
rpc/net.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
+ rpc/util.cpp \
script/sigcache.cpp \
timedata.cpp \
torcontrol.cpp \
@@ -392,7 +393,6 @@ libbitcoin_util_a_SOURCES = \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
- rpc/util.cpp \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index bc2c46f228..d70df3c9e8 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -15,6 +15,7 @@ bench_bench_bitcoin_SOURCES = \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
+ bench/block_assemble.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/examples.cpp \
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
new file mode 100644
index 0000000000..36fa175a76
--- /dev/null
+++ b/src/bench/block_assemble.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2011-2017 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 <bench/bench.h>
+#include <chainparams.h>
+#include <coins.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <miner.h>
+#include <policy/policy.h>
+#include <pow.h>
+#include <scheduler.h>
+#include <txdb.h>
+#include <txmempool.h>
+#include <utiltime.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <boost/thread.hpp>
+
+#include <list>
+#include <vector>
+
+static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = std::make_shared<CBlock>(
+ BlockAssembler{Params()}
+ .CreateNewBlock(coinbase_scriptPubKey, /* fMineWitnessTx */ true)
+ ->block);
+
+ block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
+ block->hashMerkleRoot = BlockMerkleRoot(*block);
+
+ return block;
+}
+
+
+static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = PrepareBlock(coinbase_scriptPubKey);
+
+ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
+ assert(++block->nNonce);
+ }
+
+ bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ assert(processed);
+
+ return CTxIn{block->vtx[0]->GetHash(), 0};
+}
+
+
+static void AssembleBlock(benchmark::State& state)
+{
+ const std::vector<unsigned char> op_true{OP_TRUE};
+ CScriptWitness witness;
+ witness.stack.push_back(op_true);
+
+ uint256 witness_program;
+ CSHA256().Write(&op_true[0], op_true.size()).Finalize(witness_program.begin());
+
+ const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
+
+ // Switch to regtest so we can mine faster
+ // Also segwit is active, so we can include witness transactions
+ SelectParams(CBaseChainParams::REGTEST);
+
+ InitScriptExecutionCache();
+
+ boost::thread_group thread_group;
+ CScheduler scheduler;
+ {
+ ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
+ ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
+
+ const CChainParams& chainparams = Params();
+ thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+ LoadGenesisBlock(chainparams);
+ CValidationState state;
+ ActivateBestChain(state, chainparams);
+ assert(::chainActive.Tip() != nullptr);
+ const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
+ assert(witness_enabled);
+ }
+
+ // Collect some loose transactions that spend the coinbases of our mined blocks
+ constexpr size_t NUM_BLOCKS{200};
+ std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
+ for (size_t b{0}; b < NUM_BLOCKS; ++b) {
+ CMutableTransaction tx;
+ tx.vin.push_back(MineBlock(SCRIPT_PUB));
+ tx.vin.back().scriptWitness = witness;
+ tx.vout.emplace_back(1337, SCRIPT_PUB);
+ if (NUM_BLOCKS - b >= COINBASE_MATURITY)
+ txs.at(b) = MakeTransactionRef(tx);
+ }
+ for (const auto& txr : txs) {
+ CValidationState state;
+ bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
+ assert(ret);
+ }
+
+ while (state.KeepRunning()) {
+ PrepareBlock(SCRIPT_PUB);
+ }
+
+ thread_group.interrupt_all();
+ thread_group.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+}
+
+BENCHMARK(AssembleBlock, 700);
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 2a594c3051..e6eb723cf4 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -591,7 +591,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
if (!prevOut.checkObject(types))
throw std::runtime_error("prevtxs internal object typecheck fail");
- uint256 txid = ParseHashUV(prevOut["txid"], "txid");
+ uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid");
int nOut = atoi(prevOut["vout"].getValStr());
if (nOut < 0)
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index a9b952e5a4..4b9abb2a1b 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -62,9 +62,6 @@ static bool AppInit(int argc, char* argv[])
//
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
SetupServerArgs();
-#if HAVE_DECL_DAEMON
- gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", false, OptionsCategory::OPTIONS);
-#endif
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
diff --git a/src/core_io.h b/src/core_io.h
index 377633ac77..1d87d21d40 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -22,7 +22,6 @@ CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
-uint256 ParseHashUV(const UniValue& v, const std::string& strName);
uint256 ParseHashStr(const std::string&, const std::string& strName);
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
diff --git a/src/core_read.cpp b/src/core_read.cpp
index aade7e21ca..4d851610ef 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -160,14 +160,6 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
return true;
}
-uint256 ParseHashUV(const UniValue& v, const std::string& strName)
-{
- std::string strHex;
- if (v.isStr())
- strHex = v.getValStr();
- return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
-}
-
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
{
if (!IsHex(strHex)) // Note: IsHex("") is false
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 51824fbe9f..e62ddc125e 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -446,44 +446,104 @@ void TransformD64Wrapper(unsigned char* out, const unsigned char* in)
WriteBE32(out + 28, s[7]);
}
-bool SelfTest(TransformType tr) {
- static const unsigned char in1[65] = {0, 0x80};
- static const unsigned char in2[129] = {
- 0,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0
- };
- static const uint32_t init[8] = {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul};
- static const uint32_t out1[8] = {0xe3b0c442ul, 0x98fc1c14ul, 0x9afbf4c8ul, 0x996fb924ul, 0x27ae41e4ul, 0x649b934cul, 0xa495991bul, 0x7852b855ul};
- static const uint32_t out2[8] = {0xce4153b0ul, 0x147c2a86ul, 0x3ed4298eul, 0xe0676bc8ul, 0x79fc77a1ul, 0x2abe1f49ul, 0xb2b055dful, 0x1069523eul};
- uint32_t buf[8];
- memcpy(buf, init, sizeof(buf));
- // Process nothing, and check we remain in the initial state.
- tr(buf, nullptr, 0);
- if (memcmp(buf, init, sizeof(buf))) return false;
- // Process the padded empty string (unaligned)
- tr(buf, in1 + 1, 1);
- if (memcmp(buf, out1, sizeof(buf))) return false;
- // Process 64 spaces (unaligned)
- memcpy(buf, init, sizeof(buf));
- tr(buf, in2 + 1, 2);
- if (memcmp(buf, out2, sizeof(buf))) return false;
- return true;
-}
-
TransformType Transform = sha256::Transform;
TransformD64Type TransformD64 = sha256::TransformD64;
TransformD64Type TransformD64_4way = nullptr;
TransformD64Type TransformD64_8way = nullptr;
+bool SelfTest() {
+ // Input state (equal to the initial SHA256 state)
+ static const uint32_t init[8] = {
+ 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
+ };
+ // Some random input data to test with
+ static const unsigned char data[641] = "-" // Intentionally not aligned
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
+ "eiusmod tempor incididunt ut labore et dolore magna aliqua. Et m"
+ "olestie ac feugiat sed lectus vestibulum mattis ullamcorper. Mor"
+ "bi blandit cursus risus at ultrices mi tempus imperdiet nulla. N"
+ "unc congue nisi vita suscipit tellus mauris. Imperdiet proin fer"
+ "mentum leo vel orci. Massa tempor nec feugiat nisl pretium fusce"
+ " id velit. Telus in metus vulputate eu scelerisque felis. Mi tem"
+ "pus imperdiet nulla malesuada pellentesque. Tristique magna sit.";
+ // Expected output state for hashing the i*64 first input bytes above (excluding SHA256 padding).
+ static const uint32_t result[9][8] = {
+ {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul},
+ {0x91f8ec6bul, 0x4da10fe3ul, 0x1c9c292cul, 0x45e18185ul, 0x435cc111ul, 0x3ca26f09ul, 0xeb954caeul, 0x402a7069ul},
+ {0xcabea5acul, 0x374fb97cul, 0x182ad996ul, 0x7bd69cbful, 0x450ff900ul, 0xc1d2be8aul, 0x6a41d505ul, 0xe6212dc3ul},
+ {0xbcff09d6ul, 0x3e76f36eul, 0x3ecb2501ul, 0x78866e97ul, 0xe1c1e2fdul, 0x32f4eafful, 0x8aa6c4e5ul, 0xdfc024bcul},
+ {0xa08c5d94ul, 0x0a862f93ul, 0x6b7f2f40ul, 0x8f9fae76ul, 0x6d40439ful, 0x79dcee0cul, 0x3e39ff3aul, 0xdc3bdbb1ul},
+ {0x216a0895ul, 0x9f1a3662ul, 0xe99946f9ul, 0x87ba4364ul, 0x0fb5db2cul, 0x12bed3d3ul, 0x6689c0c7ul, 0x292f1b04ul},
+ {0xca3067f8ul, 0xbc8c2656ul, 0x37cb7e0dul, 0x9b6b8b0ful, 0x46dc380bul, 0xf1287f57ul, 0xc42e4b23ul, 0x3fefe94dul},
+ {0x3e4c4039ul, 0xbb6fca8cul, 0x6f27d2f7ul, 0x301e44a4ul, 0x8352ba14ul, 0x5769ce37ul, 0x48a1155ful, 0xc0e1c4c6ul},
+ {0xfe2fa9ddul, 0x69d0862bul, 0x1ae0db23ul, 0x471f9244ul, 0xf55c0145ul, 0xc30f9c3bul, 0x40a84ea0ul, 0x5b8a266cul},
+ };
+ // Expected output for each of the individual 8 64-byte messages under full double SHA256 (including padding).
+ static const unsigned char result_d64[256] = {
+ 0x09, 0x3a, 0xc4, 0xd0, 0x0f, 0xf7, 0x57, 0xe1, 0x72, 0x85, 0x79, 0x42, 0xfe, 0xe7, 0xe0, 0xa0,
+ 0xfc, 0x52, 0xd7, 0xdb, 0x07, 0x63, 0x45, 0xfb, 0x53, 0x14, 0x7d, 0x17, 0x22, 0x86, 0xf0, 0x52,
+ 0x48, 0xb6, 0x11, 0x9e, 0x6e, 0x48, 0x81, 0x6d, 0xcc, 0x57, 0x1f, 0xb2, 0x97, 0xa8, 0xd5, 0x25,
+ 0x9b, 0x82, 0xaa, 0x89, 0xe2, 0xfd, 0x2d, 0x56, 0xe8, 0x28, 0x83, 0x0b, 0xe2, 0xfa, 0x53, 0xb7,
+ 0xd6, 0x6b, 0x07, 0x85, 0x83, 0xb0, 0x10, 0xa2, 0xf5, 0x51, 0x3c, 0xf9, 0x60, 0x03, 0xab, 0x45,
+ 0x6c, 0x15, 0x6e, 0xef, 0xb5, 0xac, 0x3e, 0x6c, 0xdf, 0xb4, 0x92, 0x22, 0x2d, 0xce, 0xbf, 0x3e,
+ 0xe9, 0xe5, 0xf6, 0x29, 0x0e, 0x01, 0x4f, 0xd2, 0xd4, 0x45, 0x65, 0xb3, 0xbb, 0xf2, 0x4c, 0x16,
+ 0x37, 0x50, 0x3c, 0x6e, 0x49, 0x8c, 0x5a, 0x89, 0x2b, 0x1b, 0xab, 0xc4, 0x37, 0xd1, 0x46, 0xe9,
+ 0x3d, 0x0e, 0x85, 0xa2, 0x50, 0x73, 0xa1, 0x5e, 0x54, 0x37, 0xd7, 0x94, 0x17, 0x56, 0xc2, 0xd8,
+ 0xe5, 0x9f, 0xed, 0x4e, 0xae, 0x15, 0x42, 0x06, 0x0d, 0x74, 0x74, 0x5e, 0x24, 0x30, 0xce, 0xd1,
+ 0x9e, 0x50, 0xa3, 0x9a, 0xb8, 0xf0, 0x4a, 0x57, 0x69, 0x78, 0x67, 0x12, 0x84, 0x58, 0xbe, 0xc7,
+ 0x36, 0xaa, 0xee, 0x7c, 0x64, 0xa3, 0x76, 0xec, 0xff, 0x55, 0x41, 0x00, 0x2a, 0x44, 0x68, 0x4d,
+ 0xb6, 0x53, 0x9e, 0x1c, 0x95, 0xb7, 0xca, 0xdc, 0x7f, 0x7d, 0x74, 0x27, 0x5c, 0x8e, 0xa6, 0x84,
+ 0xb5, 0xac, 0x87, 0xa9, 0xf3, 0xff, 0x75, 0xf2, 0x34, 0xcd, 0x1a, 0x3b, 0x82, 0x2c, 0x2b, 0x4e,
+ 0x6a, 0x46, 0x30, 0xa6, 0x89, 0x86, 0x23, 0xac, 0xf8, 0xa5, 0x15, 0xe9, 0x0a, 0xaa, 0x1e, 0x9a,
+ 0xd7, 0x93, 0x6b, 0x28, 0xe4, 0x3b, 0xfd, 0x59, 0xc6, 0xed, 0x7c, 0x5f, 0xa5, 0x41, 0xcb, 0x51
+ };
+
+
+ // Test Transform() for 0 through 8 transformations.
+ for (size_t i = 0; i <= 8; ++i) {
+ uint32_t state[8];
+ std::copy(init, init + 8, state);
+ Transform(state, data + 1, i);
+ if (!std::equal(state, state + 8, result[i])) return false;
+ }
+
+ // Test TransformD64
+ unsigned char out[32];
+ TransformD64(out, data + 1);
+ if (!std::equal(out, out + 32, result_d64)) return false;
+
+ // Test TransformD64_4way, if available.
+ if (TransformD64_4way) {
+ unsigned char out[128];
+ TransformD64_4way(out, data + 1);
+ if (!std::equal(out, out + 128, result_d64)) return false;
+ }
+
+ // Test TransformD64_8way, if available.
+ if (TransformD64_8way) {
+ unsigned char out[256];
+ TransformD64_8way(out, data + 1);
+ if (!std::equal(out, out + 256, result_d64)) return false;
+ }
+
+ return true;
+}
+
+
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
// We can't use cpuid.h's __get_cpuid as it does not support subleafs.
void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d)
{
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
}
+
+/** Check whether the OS has enabled AVX registers. */
+bool AVXEnabled()
+{
+ uint32_t a, d;
+ __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
+ return (a & 6) == 6;
+}
#endif
} // namespace
@@ -492,6 +552,7 @@ std::string SHA256AutoDetect()
{
std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
+ (void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx);
if ((ecx >> 19) & 1) {
@@ -503,10 +564,14 @@ std::string SHA256AutoDetect()
TransformD64_4way = sha256d64_sse41::Transform_4way;
ret = "sse4(1way+4way)";
#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
- cpuid(7, 0, eax, ebx, ecx, edx);
- if ((ebx >> 5) & 1) {
- TransformD64_8way = sha256d64_avx2::Transform_8way;
- ret += ",avx2(8way)";
+ if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ if ((ebx >> 5) & 1) { // AVX2 flag
+ if (AVXEnabled()) { // OS has enabled AVX registers
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+ }
}
#endif
#else
@@ -515,7 +580,7 @@ std::string SHA256AutoDetect()
}
#endif
- assert(SelfTest(Transform));
+ assert(SelfTest());
return ret;
}
diff --git a/src/init.cpp b/src/init.cpp
index 9246f6e71c..5e45277986 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -76,7 +76,7 @@ std::unique_ptr<PeerLogicValidation> peerLogic;
class DummyWalletInit : public WalletInitInterface {
public:
- void AddWalletOptions() const override {}
+ void AddWalletOptions() const override;
bool ParameterInteraction() const override {return true;}
void RegisterRPC(CRPCTable &) const override {}
bool Verify() const override {return true;}
@@ -87,6 +87,15 @@ public:
void Close() const override {}
};
+void DummyWalletInit::AddWalletOptions() const
+{
+ std::vector<std::string> opts = {"-addresstype", "-changetype", "-disablewallet", "-discardfee=<amt>", "-fallbackfee=<amt>",
+ "-keypool=<n>", "-mintxfee=<amt>", "-paytxfee=<amt>", "-rescan", "-salvagewallet", "-spendzeroconfchange", "-txconfirmtarget=<n>",
+ "-upgradewallet", "-wallet=<path>", "-walletbroadcast", "-walletdir=<dir>", "-walletnotify=<cmd>", "-walletrbf", "-zapwallettxes=<mode>",
+ "-dblogsize=<n>", "-flushwallet", "-privdb", "-walletrejectlongchains"};
+ gArgs.AddHiddenArgs(opts);
+}
+
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
#endif
@@ -348,6 +357,12 @@ void SetupServerArgs()
const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
+ // Hidden Options
+ std::vector<std::string> hidden_args = {"-rpcssl", "-benchmark", "-h", "-help", "-socks", "-tor", "-debugnet", "-whitelistalwaysrelay",
+ "-prematurewitness", "-walletprematurewitness", "-promiscuousmempoolflags", "-blockminsize", "-dbcrashratio", "-forcecompactdb", "-usehd",
+ // GUI args. These will be overwritten by SetupUIArgs for the GUI
+ "-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
+
// Set all of the args and their help
// When adding new options to the categories, please keep and ensure alphabetical ordering.
gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
@@ -375,6 +390,8 @@ void SetupServerArgs()
gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS);
#ifndef WIN32
gArgs.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS);
+#else
+ hidden_args.emplace_back("-pid");
#endif
gArgs.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
@@ -383,6 +400,8 @@ void SetupServerArgs()
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::OPTIONS);
#ifndef WIN32
gArgs.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", false, OptionsCategory::OPTIONS);
+#else
+ hidden_args.emplace_back("-sysperms");
#endif
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
@@ -405,7 +424,7 @@ void SetupServerArgs()
gArgs.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)", false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-onlynet=<net>", "Only connect to nodes in network <net> (ipv4, ipv6 or onion)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
@@ -421,6 +440,8 @@ void SetupServerArgs()
#else
gArgs.AddArg("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", 0), false, OptionsCategory::CONNECTION);
#endif
+#else
+ hidden_args.emplace_back("-upnp");
#endif
gArgs.AddArg("-whitebind=<addr>", "Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-whitelist=<IP address or network>", "Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times."
@@ -433,6 +454,11 @@ 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);
+#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>");
#endif
gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
@@ -500,22 +526,14 @@ void SetupServerArgs()
gArgs.AddArg("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), true, OptionsCategory::RPC);
gArgs.AddArg("-server", "Accept command line and JSON-RPC commands", false, OptionsCategory::RPC);
- // Hidden options
- gArgs.AddArg("-rpcssl", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-benchmark", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-socks", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-tor", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-debugnet", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-whitelistalwaysrelay", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-prematurewitness", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-walletprematurewitness", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-promiscuousmempoolflags", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-blockminsize", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-dbcrashratio", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-forcecompactdb", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-usehd", "", false, OptionsCategory::HIDDEN);
+#if HAVE_DECL_DAEMON
+ gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", false, OptionsCategory::OPTIONS);
+#else
+ hidden_args.emplace_back("-daemon");
+#endif
+
+ // Add the hidden options
+ gArgs.AddHiddenArgs(hidden_args);
}
std::string LicenseInfo()
@@ -614,7 +632,7 @@ static void CleanupBlockRevFiles()
// keeping a separate counter. Once we hit a gap (or if 0 doesn't exist)
// start removing block files.
int nContigCounter = 0;
- for (const std::pair<std::string, fs::path>& item : mapBlockFiles) {
+ for (const std::pair<const std::string, fs::path>& item : mapBlockFiles) {
if (atoi(item.first) == nContigCounter) {
nContigCounter++;
continue;
@@ -943,7 +961,8 @@ bool AppInitParameterInteraction()
nMaxConnections = std::max(nUserMaxConnections, 0);
// Trim requested connection counts, to fit into system limitations
- nMaxConnections = std::max(std::min(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
+ // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
+ nMaxConnections = std::max(std::min<int>(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 3029dbe8e3..e98acba0df 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -429,6 +429,10 @@ public:
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
+ std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
+ {
+ return MakeHandler(m_wallet.NotifyUnload.connect(fn));
+ }
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
return MakeHandler(m_wallet.ShowProgress.connect(fn));
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index 82ae0b14b5..ce42e14eea 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -242,6 +242,10 @@ public:
// Get default change type.
virtual OutputType getDefaultChangeType() = 0;
+ //! Register handler for unload message.
+ using UnloadFn = std::function<void()>;
+ virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
+
//! Register handler for show progress messages.
using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
diff --git a/src/miner.cpp b/src/miner.cpp
index d4527a1d67..738ccad1b9 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -209,7 +209,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// segwit activation)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
- for (const CTxMemPool::txiter it : package) {
+ for (CTxMemPool::txiter it : package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
if (!fIncludeWitness && it->GetTx().HasWitness())
@@ -241,7 +241,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
indexed_modified_transaction_set &mapModifiedTx)
{
int nDescendantsUpdated = 0;
- for (const CTxMemPool::txiter it : alreadyAdded) {
+ for (CTxMemPool::txiter it : alreadyAdded) {
CTxMemPool::setEntries descendants;
mempool.CalculateDescendants(it, descendants);
// Insert all descendants (not yet in block) into the modified set
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 15f9016be8..db68e9240a 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -41,7 +41,11 @@ enum Network ParseNetwork(std::string net) {
boost::to_lower(net);
if (net == "ipv4") return NET_IPV4;
if (net == "ipv6") return NET_IPV6;
- if (net == "tor" || net == "onion") return NET_TOR;
+ if (net == "onion") return NET_TOR;
+ if (net == "tor") {
+ LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
+ return NET_TOR;
+ }
return NET_UNROUTABLE;
}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 1c846d38ec..360615ec56 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -388,11 +388,6 @@ struct CMutableTransaction
*/
uint256 GetHash() const;
- friend bool operator==(const CMutableTransaction& a, const CMutableTransaction& b)
- {
- return a.GetHash() == b.GetHash();
- }
-
bool HasWitness() const
{
for (size_t i = 0; i < vin.size(); i++) {
diff --git a/src/qt/README.md b/src/qt/README.md
index bf8139666c..3ec538b4f4 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -1,6 +1,6 @@
This directory contains the BitcoinQT graphical user interface (GUI). It uses the cross-platform framework [Qt](https://www1.qt.io/developers/).
-The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk). Qt 4 is also supported (see [#8263](https://github.com/bitcoin/bitcoin/issues/8263)).
+The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/qt.mk).
## Compile and run
@@ -16,7 +16,7 @@ To run:
### forms
-Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
+Contains [Designer UI](https://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
### locale
@@ -36,7 +36,7 @@ Represents the main window of the Bitcoin UI.
### \*model.(h/cpp)
-The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](http://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](http://doc.qt.io/qt-5/qvalidator.html).
+The model. When it has a corresponding controller, it generally inherits from [QAbstractTableModel](https://doc.qt.io/qt-5/qabstracttablemodel.html). Models that are used by controllers as helpers inherit from other Qt classes like [QValidator](https://doc.qt.io/qt-5/qvalidator.html).
ClientModel is used by the main application `bitcoingui` and several models like `peertablemodel`.
@@ -46,7 +46,7 @@ A controller. `:NAMEpage.cpp` generally includes `:NAMEmodel.h` and `forms/:NAME
### \*dialog.(h/cpp)
-Various dialogs, e.g. to open a URL. Inherit from [QDialog](http://doc.qt.io/qt-4.8/qdialog.html).
+Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt-5/qdialog.html).
### paymentserver.(h/cpp)
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index f2ddbf259b..d51069d922 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -160,13 +160,8 @@ void AddressBookPage::setModel(AddressTableModel *_model)
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
// Set column widths
-#if QT_VERSION < 0x050000
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
- ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#else
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
-#endif
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged()));
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 26cb03c2c7..aa0d4a31d3 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -52,9 +52,7 @@ public:
node.getBanned(banMap);
cachedBanlist.clear();
-#if QT_VERSION >= 0x040700
cachedBanlist.reserve(banMap.size());
-#endif
for (const auto& entry : banMap)
{
CCombinedBan banEntry;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 31d9f936e7..e3d1c746b1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -55,13 +55,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-Q_IMPORT_PLUGIN(qtaccessiblewidgets)
-#else
#if QT_VERSION < 0x050400
Q_IMPORT_PLUGIN(AccessibleFactory)
#endif
@@ -73,11 +66,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
-
-#if QT_VERSION < 0x050000
-#include <QTextCodec>
-#endif
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE(bool*)
@@ -151,16 +139,6 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
}
/* qDebug() message handler --> debug.log */
-#if QT_VERSION < 0x050000
-void DebugMessageHandler(QtMsgType type, const char *msg)
-{
- if (type == QtDebugMsg) {
- LogPrint(BCLog::QT, "GUI: %s\n", msg);
- } else {
- LogPrintf("GUI: %s\n", msg);
- }
-}
-#else
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
Q_UNUSED(context);
@@ -170,7 +148,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
LogPrintf("GUI: %s\n", msg.toStdString());
}
}
-#endif
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread.
@@ -238,6 +215,7 @@ public Q_SLOTS:
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
void handleRunawayException(const QString &message);
void addWallet(WalletModel* walletModel);
+ void removeWallet();
Q_SIGNALS:
void requestedInitialize();
@@ -467,11 +445,22 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
+ connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
m_wallet_models.push_back(walletModel);
#endif
}
+void BitcoinApplication::removeWallet()
+{
+#ifdef ENABLE_WALLET
+ WalletModel* walletModel = static_cast<WalletModel*>(sender());
+ m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
+ window->removeWallet(walletModel);
+ walletModel->deleteLater();
+#endif
+}
+
void BitcoinApplication::initializeResult(bool success)
{
qDebug() << __func__ << ": Initialization result: " << success;
@@ -491,8 +480,10 @@ void BitcoinApplication::initializeResult(bool success)
#ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
- QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection,
- Q_ARG(WalletModel*, new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel)));
+ WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
+ // Fix wallet model thread affinity.
+ wallet_model->moveToThread(thread());
+ QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
});
for (auto& wallet : m_node.getWallets()) {
@@ -572,12 +563,6 @@ int main(int argc, char *argv[])
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
/// 1. Basic Qt initialization (not dependent on parameters or configuration)
-#if QT_VERSION < 0x050000
- // Internal string conversion is all UTF-8
- QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
- QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
-#endif
-
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
@@ -708,17 +693,12 @@ int main(int argc, char *argv[])
/// 9. Main GUI initialization
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
-#if QT_VERSION < 0x050000
- // Install qDebug() message handler to route to debug.log
- qInstallMsgHandler(DebugMessageHandler);
-#else
#if defined(Q_OS_WIN)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp->installNativeEventFilter(new WinShutdownMonitor());
#endif
// Install qDebug() message handler to route to debug.log
qInstallMessageHandler(DebugMessageHandler);
-#endif
// Allow parameter interaction before we create the options model
app.parameterSetup();
// Load GUI settings from QSettings
@@ -739,7 +719,7 @@ int main(int argc, char *argv[])
// so the GUI thread won't be held up.
if (node->baseInitialize()) {
app.requestInitialize();
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
#endif
app.exec();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 9f5ea02e14..df78652376 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -55,14 +55,8 @@
#include <QStyle>
#include <QTimer>
#include <QToolBar>
-#include <QVBoxLayout>
-
-#if QT_VERSION < 0x050000
-#include <QTextDocument>
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
+#include <QVBoxLayout>
const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#if defined(Q_OS_MAC)
@@ -76,50 +70,7 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
- enableWallet(false),
m_node(node),
- clientModel(0),
- walletFrame(0),
- unitDisplayControl(0),
- labelWalletEncryptionIcon(0),
- labelWalletHDStatusIcon(0),
- labelProxyIcon(0),
- connectionsControl(0),
- labelBlocksIcon(0),
- progressBarLabel(0),
- progressBar(0),
- progressDialog(0),
- appMenuBar(0),
- appToolBar(0),
- overviewAction(0),
- historyAction(0),
- quitAction(0),
- sendCoinsAction(0),
- sendCoinsMenuAction(0),
- usedSendingAddressesAction(0),
- usedReceivingAddressesAction(0),
- signMessageAction(0),
- verifyMessageAction(0),
- aboutAction(0),
- receiveCoinsAction(0),
- receiveCoinsMenuAction(0),
- optionsAction(0),
- toggleHideAction(0),
- encryptWalletAction(0),
- backupWalletAction(0),
- changePassphraseAction(0),
- aboutQtAction(0),
- openRPCConsoleAction(0),
- openAction(0),
- showHelpMessageAction(0),
- trayIcon(0),
- trayIconMenu(0),
- notificator(0),
- rpcConsole(0),
- helpMessageDialog(0),
- modalOverlay(0),
- prevBlocks(0),
- spinnerFrame(0),
platformStyle(_platformStyle)
{
QSettings settings;
@@ -147,12 +98,6 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
#endif
setWindowTitle(windowTitle);
-#if defined(Q_OS_MAC) && QT_VERSION < 0x050000
- // This property is not implemented in Qt 5. Setting it has no effect.
- // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
- setUnifiedTitleAndToolBarOnMac(true);
-#endif
-
rpcConsole = new RPCConsole(node, _platformStyle, 0);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
@@ -229,7 +174,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Override style sheet for progress bar for styles that have a segmented progress bar,
// as they make the text unreadable (workaround for issue #1071)
- // See https://qt-project.org/doc/qt-4.8/gallery.html
+ // See https://doc.qt.io/qt-5/gallery.html
QString curStyle = QApplication::style()->metaObject()->className();
if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
{
@@ -477,6 +422,16 @@ void BitcoinGUI::createToolBars()
m_wallet_selector = new QComboBox();
connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
+
+ m_wallet_selector_label = new QLabel();
+ m_wallet_selector_label->setText(tr("Wallet:") + " ");
+ m_wallet_selector_label->setBuddy(m_wallet_selector);
+
+ m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
+ m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
+
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
#endif
}
}
@@ -556,16 +511,29 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
setWalletActionsEnabled(true);
m_wallet_selector->addItem(display_name, name);
if (m_wallet_selector->count() == 2) {
- m_wallet_selector_label = new QLabel();
- m_wallet_selector_label->setText(tr("Wallet:") + " ");
- m_wallet_selector_label->setBuddy(m_wallet_selector);
- appToolBar->addWidget(m_wallet_selector_label);
- appToolBar->addWidget(m_wallet_selector);
+ m_wallet_selector_label_action->setVisible(true);
+ m_wallet_selector_action->setVisible(true);
}
rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel);
}
+bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+{
+ if (!walletFrame) return false;
+ QString name = walletModel->getWalletName();
+ int index = m_wallet_selector->findData(name);
+ m_wallet_selector->removeItem(index);
+ if (m_wallet_selector->count() == 0) {
+ setWalletActionsEnabled(false);
+ } else if (m_wallet_selector->count() == 1) {
+ m_wallet_selector_label_action->setVisible(false);
+ m_wallet_selector_action->setVisible(false);
+ }
+ rpcConsole->removeWallet(walletModel);
+ return walletFrame->removeWallet(name);
+}
+
bool BitcoinGUI::setCurrentWallet(const QString& name)
{
if(!walletFrame)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 89c1c73a79..964e04f848 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -70,9 +70,10 @@ public:
functionality.
*/
bool addWallet(WalletModel *walletModel);
+ bool removeWallet(WalletModel* walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
- bool enableWallet;
+ bool enableWallet = false;
protected:
void changeEvent(QEvent *e);
@@ -86,56 +87,58 @@ private:
interfaces::Node& m_node;
std::unique_ptr<interfaces::Handler> m_handler_message_box;
std::unique_ptr<interfaces::Handler> m_handler_question;
- ClientModel *clientModel;
- WalletFrame *walletFrame;
-
- UnitDisplayStatusBarControl *unitDisplayControl;
- QLabel *labelWalletEncryptionIcon;
- QLabel *labelWalletHDStatusIcon;
- QLabel *labelProxyIcon;
- QLabel *connectionsControl;
- QLabel *labelBlocksIcon;
- QLabel *progressBarLabel;
- QProgressBar *progressBar;
- QProgressDialog *progressDialog;
-
- QMenuBar *appMenuBar;
- QToolBar *appToolBar;
- QAction *overviewAction;
- QAction *historyAction;
- QAction *quitAction;
- QAction *sendCoinsAction;
- QAction *sendCoinsMenuAction;
- QAction *usedSendingAddressesAction;
- QAction *usedReceivingAddressesAction;
- QAction *signMessageAction;
- QAction *verifyMessageAction;
- QAction *aboutAction;
- QAction *receiveCoinsAction;
- QAction *receiveCoinsMenuAction;
- QAction *optionsAction;
- QAction *toggleHideAction;
- QAction *encryptWalletAction;
- QAction *backupWalletAction;
- QAction *changePassphraseAction;
- QAction *aboutQtAction;
- QAction *openRPCConsoleAction;
- QAction *openAction;
- QAction *showHelpMessageAction;
-
- QLabel *m_wallet_selector_label;
- QComboBox *m_wallet_selector;
-
- QSystemTrayIcon *trayIcon;
- QMenu *trayIconMenu;
- Notificator *notificator;
- RPCConsole *rpcConsole;
- HelpMessageDialog *helpMessageDialog;
- ModalOverlay *modalOverlay;
+ ClientModel* clientModel = nullptr;
+ WalletFrame* walletFrame = nullptr;
+
+ UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
+ QLabel* labelWalletEncryptionIcon = nullptr;
+ QLabel* labelWalletHDStatusIcon = nullptr;
+ QLabel* labelProxyIcon = nullptr;
+ QLabel* connectionsControl = nullptr;
+ QLabel* labelBlocksIcon = nullptr;
+ QLabel* progressBarLabel = nullptr;
+ QProgressBar* progressBar = nullptr;
+ QProgressDialog* progressDialog = nullptr;
+
+ QMenuBar* appMenuBar = nullptr;
+ QToolBar* appToolBar = nullptr;
+ QAction* overviewAction = nullptr;
+ QAction* historyAction = nullptr;
+ QAction* quitAction = nullptr;
+ QAction* sendCoinsAction = nullptr;
+ QAction* sendCoinsMenuAction = nullptr;
+ QAction* usedSendingAddressesAction = nullptr;
+ QAction* usedReceivingAddressesAction = nullptr;
+ QAction* signMessageAction = nullptr;
+ QAction* verifyMessageAction = nullptr;
+ QAction* aboutAction = nullptr;
+ QAction* receiveCoinsAction = nullptr;
+ QAction* receiveCoinsMenuAction = nullptr;
+ QAction* optionsAction = nullptr;
+ QAction* toggleHideAction = nullptr;
+ QAction* encryptWalletAction = nullptr;
+ QAction* backupWalletAction = nullptr;
+ QAction* changePassphraseAction = nullptr;
+ QAction* aboutQtAction = nullptr;
+ QAction* openRPCConsoleAction = nullptr;
+ QAction* openAction = nullptr;
+ QAction* showHelpMessageAction = nullptr;
+ QAction* m_wallet_selector_label_action = nullptr;
+ QAction* m_wallet_selector_action = nullptr;
+
+ QLabel *m_wallet_selector_label = nullptr;
+ QComboBox* m_wallet_selector = nullptr;
+
+ QSystemTrayIcon* trayIcon = nullptr;
+ QMenu* trayIconMenu = nullptr;
+ Notificator* notificator = nullptr;
+ RPCConsole* rpcConsole = nullptr;
+ HelpMessageDialog* helpMessageDialog = nullptr;
+ ModalOverlay* modalOverlay = nullptr;
/** Keep track of previous number of blocks, to detect progress */
- int prevBlocks;
- int spinnerFrame;
+ int prevBlocks = 0;
+ int spinnerFrame = 0;
const PlatformStyle *platformStyle;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index b08de27041..9b6480a915 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -109,11 +109,7 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(viewItemChanged(QTreeWidgetItem*, int)));
// click on header
-#if QT_VERSION < 0x050000
- ui->treeWidget->header()->setClickable(true);
-#else
ui->treeWidget->header()->setSectionsClickable(true);
-#endif
connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int)));
// ok button
@@ -122,10 +118,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
// (un)select all
connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked()));
- // change coin control first column label due Qt4 bug.
- // see https://github.com/bitcoin/bitcoin/issues/5716
- ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString());
-
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110);
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190);
@@ -392,13 +384,11 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
// TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
// Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
-#if QT_VERSION >= 0x050000
else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
{
if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked && item->child(0)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked)
item->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
}
-#endif
}
// shows count of locked unspent outputs
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 563f930dec..acd9f7b35c 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -53,13 +53,9 @@
#include <QSettings>
#include <QTextDocument> // for Qt::mightBeRichText
#include <QThread>
+#include <QUrlQuery>
#include <QMouseEvent>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
-#include <QUrlQuery>
-#endif
#if QT_VERSION >= 0x50200
#include <QFontDatabase>
@@ -95,11 +91,7 @@ QFont fixedPitchFont()
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
#else
QFont font("Monospace");
-#if QT_VERSION >= 0x040800
font.setStyleHint(QFont::Monospace);
-#else
- font.setStyleHint(QFont::TypeWriter);
-#endif
return font;
#endif
}
@@ -127,12 +119,10 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
parent->setFocusProxy(widget);
widget->setFont(fixedPitchFont());
-#if QT_VERSION >= 0x040700
// We don't want translators to use own addresses in translations
// and this is the only place, where this address is supplied.
widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg(
QString::fromStdString(DummyAddress(Params()))));
-#endif
widget->setValidator(new BitcoinAddressEntryValidator(parent));
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
}
@@ -151,12 +141,8 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
}
rv.amount = 0;
-#if QT_VERSION < 0x050000
- QList<QPair<QString, QString> > items = uri.queryItems();
-#else
QUrlQuery uriQuery(uri);
QList<QPair<QString, QString> > items = uriQuery.queryItems();
-#endif
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -242,11 +228,7 @@ bool isDust(interfaces::Node& node, const QString& address, const CAmount& amoun
QString HtmlEscape(const QString& str, bool fMultiLine)
{
-#if QT_VERSION < 0x050000
- QString escaped = Qt::escape(str);
-#else
QString escaped = str.toHtmlEscaped();
-#endif
if(fMultiLine)
{
escaped = escaped.replace("\n", "<br>\n");
@@ -287,11 +269,7 @@ QString getSaveFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -337,11 +315,7 @@ QString getOpenFileName(QWidget *parent, const QString &caption, const QString &
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
-#if QT_VERSION < 0x050000
- myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
-#else
myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
-#endif
}
else
{
@@ -495,11 +469,7 @@ void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals()
// Refactored here for readability.
void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
{
-#if QT_VERSION < 0x050000
- tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
-#else
tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
-#endif
}
void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 4a26964098..e965a91d18 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -233,7 +233,7 @@ namespace GUIUtil
void mouseReleaseEvent(QMouseEvent *event);
};
-#if defined(Q_OS_MAC) && QT_VERSION >= 0x050000
+#if defined(Q_OS_MAC)
// workaround for Qt OSX Bug:
// https://bugreports.qt-project.org/browse/QTBUG-15631
// QProgressBar uses around 10% CPU even when app is in background
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index 9e7de0f98f..a0b62ae000 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -14,10 +14,6 @@
#include <objc/objc.h>
#include <objc/message.h>
-#if QT_VERSION < 0x050000
-extern void qt_mac_set_dock_menu(QMenu *);
-#endif
-
static MacDockIconHandler *s_instance = nullptr;
bool dockClickHandler(id self,SEL _cmd,...) {
@@ -54,9 +50,7 @@ MacDockIconHandler::MacDockIconHandler() : QObject()
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
this->setMainWindow(nullptr);
-#if QT_VERSION < 0x050000
- qt_mac_set_dock_menu(this->m_dockMenu);
-#elif QT_VERSION >= 0x050200
+#if QT_VERSION >= 0x050200
this->m_dockMenu->setAsDockMenu();
#endif
[pool release];
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index 2816633b0f..c4b732e3e0 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -68,11 +68,7 @@ NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift,
}
//convert back to QPixmap
-#if QT_VERSION >= 0x040700
pixmap.convertFromImage(img);
-#else
- pixmap = QPixmap::fromImage(img);
-#endif
}
appIcon = QIcon(pixmap);
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index 751cfa8b43..d211f908c8 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -15,9 +15,7 @@ OpenURIDialog::OpenURIDialog(QWidget *parent) :
ui(new Ui::OpenURIDialog)
{
ui->setupUi(this);
-#if QT_VERSION >= 0x040700
ui->uriEdit->setPlaceholderText("bitcoin:");
-#endif
}
OpenURIDialog::~OpenURIDialog()
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 108aa4f99c..3ff6f59c25 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -97,28 +97,16 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
/** check if the locale name consists of 2 parts (language_country) */
if(langStr.contains("_"))
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
else
{
-#if QT_VERSION >= 0x040800
/** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#else
- /** display language strings as "language (locale name)", e.g. "German (de)" */
- ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
-#endif
}
}
-#if QT_VERSION >= 0x040700
ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
-#endif
ui->unit->setModel(new BitcoinUnits(this));
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index b0ef475b35..dfeb70d669 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -97,12 +97,10 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
return false;
}
-#if QT_VERSION >= 0x050000
if (qCert.isBlacklisted()) {
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
return false;
}
-#endif
const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size());
if (cert)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 59bb5d5bb6..e5e6430959 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -41,12 +41,7 @@
#include <QSslSocket>
#include <QStringList>
#include <QTextDocument>
-
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#else
#include <QUrlQuery>
-#endif
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
@@ -100,11 +95,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
-#if QT_VERSION < 0x050000
- qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#else
qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-#endif
}
//
@@ -157,13 +148,11 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
continue;
}
-#if QT_VERSION >= 0x050000
// Blacklisted certificate
if (cert.isBlacklisted()) {
ReportInvalidCertificate(cert);
continue;
}
-#endif
QByteArray certData = cert.toDer();
const unsigned char *data = (const unsigned char *)certData.data();
@@ -413,11 +402,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
-#if QT_VERSION < 0x050000
- QUrl uri(s);
-#else
QUrlQuery uri((QUrl(s)));
-#endif
if (uri.hasQueryItem("r")) // payment request URI
{
QByteArray temp;
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 7e318e3035..0ca9d48bf6 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -64,9 +64,7 @@ public:
interfaces::Node::NodesStats nodes_stats;
node.getNodesStats(nodes_stats);
-#if QT_VERSION >= 0x040700
cachedNodeStats.reserve(nodes_stats.size());
-#endif
for (auto& node_stats : nodes_stats)
{
CNodeCombinedStats stats;
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index fce71f661a..a3a10aac18 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -46,7 +46,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase)
QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase)
{
QIcon new_ico;
- for (const QSize sz : ico.availableSizes())
+ for (const QSize& sz : ico.availableSizes())
{
QImage img(ico.pixmap(sz).toImage());
MakeSingleColorImage(img, colorbase);
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index 75146e2214..f9610f2d3b 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -16,9 +16,6 @@
#include <QMimeData>
#include <QMouseEvent>
#include <QPixmap>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
diff --git a/src/qt/res/movies/makespinner.sh b/src/qt/res/movies/makespinner.sh
index d0deb1238c..76e36e4f31 100755
--- a/src/qt/res/movies/makespinner.sh
+++ b/src/qt/res/movies/makespinner.sh
@@ -2,6 +2,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+export LC_ALL=C
FRAMEDIR=$(dirname $0)
for i in {0..35}
do
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4550ae9396..f222357f27 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -40,10 +40,6 @@
#include <QTimer>
#include <QStringList>
-#if QT_VERSION < 0x050000
-#include <QUrl>
-#endif
-
// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel
@@ -713,6 +709,16 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
ui->WalletSelectorLabel->setVisible(true);
}
}
+
+void RPCConsole::removeWallet(WalletModel * const walletModel)
+{
+ const QString name = walletModel->getWalletName();
+ ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
+ if (ui->WalletSelector->count() == 2) {
+ ui->WalletSelector->setVisible(false);
+ ui->WalletSelectorLabel->setVisible(false);
+ }
+}
#endif
static QString categoryClass(int category)
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a53c4c24f9..0a1a469934 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -48,6 +48,7 @@ public:
void setClientModel(ClientModel *model);
void addWallet(WalletModel * const walletModel);
+ void removeWallet(WalletModel* const walletModel);
enum MessageClass {
MC_ERROR,
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 977425f7e3..e8c85bc2a1 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -32,9 +32,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
if (platformStyle->getUseExtraSpacing())
ui->payToLayout->setSpacing(4);
-#if QT_VERSION >= 0x040700
ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
-#endif
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 94a3ad7987..c8e694e658 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -37,9 +37,7 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformS
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
-#if QT_VERSION >= 0x040700
ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
-#endif
GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 56d4d3e457..f0ac43a58c 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -26,12 +26,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050000
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-#else
#if defined(QT_QPA_PLATFORM_MINIMAL)
Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin);
#endif
@@ -43,7 +37,6 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
-#endif
extern void noui_connect();
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 33c49dc7cb..c314dadde4 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -87,17 +87,6 @@ QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
return {};
}
-//! Request context menu (call method that is public in qt5, but protected in qt4).
-void RequestContextMenu(QWidget* widget)
-{
- class Qt4Hack : public QWidget
- {
- public:
- using QWidget::customContextMenuRequested;
- };
- static_cast<Qt4Hack*>(widget)->customContextMenuRequested({});
-}
-
//! Invoke bumpfee on txid and check results.
void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, std::string expectError, bool cancel)
{
@@ -110,7 +99,7 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
QAction* action = view.findChild<QAction*>("bumpFeeAction");
table->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
action->setEnabled(expectDisabled);
- RequestContextMenu(table);
+ table->customContextMenuRequested({});
QCOMPARE(action->isEnabled(), !expectDisabled);
action->setEnabled(true);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index aa6444245a..e60a387934 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -95,15 +95,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
hlayout->addWidget(typeWidget);
search_widget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search"));
-#endif
hlayout->addWidget(search_widget);
amountWidget = new QLineEdit(this);
-#if QT_VERSION >= 0x040700
amountWidget->setPlaceholderText(tr("Min amount"));
-#endif
if (platformStyle->getUseExtraSpacing()) {
amountWidget->setFixedWidth(97);
} else {
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index eb0eba21ef..c5a13f61f4 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -94,6 +94,7 @@ bool WalletFrame::removeWallet(const QString &name)
WalletView *walletView = mapWalletViews.take(name);
walletStack->removeWidget(walletView);
+ delete walletView;
return true;
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 3418b1f1a9..389acf0a95 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -364,6 +364,12 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
}
// Handlers for core signals
+static void NotifyUnload(WalletModel* walletModel)
+{
+ qDebug() << "NotifyUnload";
+ QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
+}
+
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
{
qDebug() << "NotifyKeyStoreStatusChanged";
@@ -411,6 +417,7 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
+ m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
@@ -421,6 +428,7 @@ void WalletModel::subscribeToCoreSignals()
void WalletModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from wallet
+ m_handler_unload->disconnect();
m_handler_status_changed->disconnect();
m_handler_address_book_changed->disconnect();
m_handler_transaction_changed->disconnect();
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 9173fcae52..35ededb121 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -208,6 +208,7 @@ public:
AddressTableModel* getAddressTableModel() const { return addressTableModel; }
private:
std::unique_ptr<interfaces::Wallet> m_wallet;
+ std::unique_ptr<interfaces::Handler> m_handler_unload;
std::unique_ptr<interfaces::Handler> m_handler_status_changed;
std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
@@ -261,6 +262,9 @@ Q_SIGNALS:
// Watch-only address added
void notifyWatchonlyChanged(bool fHaveWatchonly);
+ // Signal that wallet is about to be removed
+ void unload();
+
public Q_SLOTS:
/* Wallet status might have changed */
void updateStatus();
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 1e7a76efc0..6190a74598 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -4,7 +4,7 @@
#include <qt/winshutdownmonitor.h>
-#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
+#if defined(Q_OS_WIN)
#include <init.h>
#include <util.h>
diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h
index 0bed55a2c6..c8a523a538 100644
--- a/src/qt/winshutdownmonitor.h
+++ b/src/qt/winshutdownmonitor.h
@@ -9,7 +9,6 @@
#include <QByteArray>
#include <QString>
-#if QT_VERSION >= 0x050000
#include <windef.h> // for HWND
#include <QAbstractNativeEventFilter>
@@ -24,6 +23,5 @@ public:
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);
};
#endif
-#endif
#endif // BITCOIN_QT_WINSHUTDOWNMONITOR_H
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index f70d506e13..d9d803ac7d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -95,6 +95,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.pushKV("bits", strprintf("%08x", blockindex->nBits));
result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex->nChainWork.GetHex());
+ result.pushKV("nTx", (uint64_t)blockindex->nTx);
if (blockindex->pprev)
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
@@ -140,6 +141,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.pushKV("bits", strprintf("%08x", block.nBits));
result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex->nChainWork.GetHex());
+ result.pushKV("nTx", (uint64_t)blockindex->nTx);
if (blockindex->pprev)
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
@@ -694,6 +696,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
" \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n"
+ " \"nTx\" : n, (numeric) The number of transactions in the block.\n"
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\", (string) The hash of the next block\n"
"}\n"
@@ -782,6 +785,7 @@ static UniValue getblock(const JSONRPCRequest& request)
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
" \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n"
+ " \"nTx\" : n, (numeric) The number of transactions in the block.\n"
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
"}\n"
@@ -849,7 +853,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
ss << hash;
ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
stats.nTransactions++;
- for (const auto output : outputs) {
+ for (const auto& output : outputs) {
ss << VARINT(output.first + 1);
ss << output.second.out.scriptPubKey;
ss << VARINT(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 85b864e6b9..81c4fb040f 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -725,7 +725,6 @@ static UniValue submitblock(const JSONRPCRequest& request)
}
uint256 hash = block.GetHash();
- bool fBlockPresent = false;
{
LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(hash);
@@ -736,8 +735,6 @@ static UniValue submitblock(const JSONRPCRequest& request)
if (pindex->nStatus & BLOCK_FAILED_MASK) {
return "duplicate-invalid";
}
- // Otherwise, we might only have the header - process the block before returning
- fBlockPresent = true;
}
}
@@ -749,13 +746,15 @@ static UniValue submitblock(const JSONRPCRequest& request)
}
}
+ bool new_block;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(Params(), blockptr, true, nullptr);
+ bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
UnregisterValidationInterface(&sc);
- if (fBlockPresent) {
- if (fAccepted && !sc.found) {
- return "duplicate-inconclusive";
+ if (!new_block) {
+ if (!accepted) {
+ // TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case?
+ return "invalid";
}
return "duplicate";
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 1530d8578b..8fa56e9335 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -475,7 +475,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
UniValue localAddresses(UniValue::VARR);
{
LOCK(cs_mapLocalHost);
- for (const std::pair<CNetAddr, LocalServiceInfo> &item : mapLocalHost)
+ for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
{
UniValue rec(UniValue::VOBJ);
rec.pushKV("address", item.first.ToString());
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 4070642537..0264d29455 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -587,9 +587,6 @@ inline CTransactionRef make_tx(std::vector<CAmount>&& output_values, std::vector
return MakeTransactionRef(tx);
}
-#define MK_OUTPUTS(amounts...) std::vector<CAmount>{amounts}
-#define MK_INPUTS(txs...) std::vector<CTransactionRef>{txs}
-#define MK_INPUT_IDX(idxes...) std::vector<uint32_t>{idxes}
BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
{
@@ -602,7 +599,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
//
// [tx1]
//
- CTransactionRef tx1 = make_tx(MK_OUTPUTS(10 * COIN));
+ CTransactionRef tx1 = make_tx(/* output_values */ {10 * COIN});
pool.addUnchecked(tx1->GetHash(), entry.Fee(10000LL).FromTx(tx1));
// Ancestors / descendants should be 1 / 1 (itself / itself)
@@ -614,7 +611,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
//
// [tx1].0 <- [tx2]
//
- CTransactionRef tx2 = make_tx(MK_OUTPUTS(495 * CENT, 5 * COIN), MK_INPUTS(tx1));
+ CTransactionRef tx2 = make_tx(/* output_values */ {495 * CENT, 5 * COIN}, /* inputs */ {tx1});
pool.addUnchecked(tx2->GetHash(), entry.Fee(10000LL).FromTx(tx2));
// Ancestors / descendants should be:
@@ -633,7 +630,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
//
// [tx1].0 <- [tx2].0 <- [tx3]
//
- CTransactionRef tx3 = make_tx(MK_OUTPUTS(290 * CENT, 200 * CENT), MK_INPUTS(tx2));
+ CTransactionRef tx3 = make_tx(/* output_values */ {290 * CENT, 200 * CENT}, /* inputs */ {tx2});
pool.addUnchecked(tx3->GetHash(), entry.Fee(10000LL).FromTx(tx3));
// Ancestors / descendants should be:
@@ -658,7 +655,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
// |
// \---1 <- [tx4]
//
- CTransactionRef tx4 = make_tx(MK_OUTPUTS(290 * CENT, 250 * CENT), MK_INPUTS(tx2), MK_INPUT_IDX(1));
+ CTransactionRef tx4 = make_tx(/* output_values */ {290 * CENT, 250 * CENT}, /* inputs */ {tx2}, /* input_indices */ {1});
pool.addUnchecked(tx4->GetHash(), entry.Fee(10000LL).FromTx(tx4));
// Ancestors / descendants should be:
@@ -694,14 +691,14 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
CAmount v = 5 * COIN;
for (uint64_t i = 0; i < 5; i++) {
CTransactionRef& tyi = *ty[i];
- tyi = make_tx(MK_OUTPUTS(v), i > 0 ? MK_INPUTS(*ty[i-1]) : std::vector<CTransactionRef>());
+ tyi = make_tx(/* output_values */ {v}, /* inputs */ i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
v -= 50 * CENT;
pool.addUnchecked(tyi->GetHash(), entry.Fee(10000LL).FromTx(tyi));
pool.GetTransactionAncestry(tyi->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, i+1);
BOOST_CHECK_EQUAL(descendants, i+1);
}
- CTransactionRef ty6 = make_tx(MK_OUTPUTS(5 * COIN), MK_INPUTS(tx3, ty5));
+ CTransactionRef ty6 = make_tx(/* output_values */ {5 * COIN}, /* inputs */ {tx3, ty5});
pool.addUnchecked(ty6->GetHash(), entry.Fee(10000LL).FromTx(ty6));
// Ancestors / descendants should be:
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 1c6dba0c9c..8090172e3f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -69,12 +69,12 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
setAllDescendants.insert(cit);
stageEntries.erase(cit);
const setEntries &setChildren = GetMemPoolChildren(cit);
- for (const txiter childEntry : setChildren) {
+ for (txiter childEntry : setChildren) {
cacheMap::iterator cacheIt = cachedDescendants.find(childEntry);
if (cacheIt != cachedDescendants.end()) {
// We've already calculated this one, just add the entries for this set
// but don't traverse again.
- for (const txiter cacheEntry : cacheIt->second) {
+ for (txiter cacheEntry : cacheIt->second) {
setAllDescendants.insert(cacheEntry);
}
} else if (!setAllDescendants.count(childEntry)) {
diff --git a/src/txmempool.h b/src/txmempool.h
index bda812b42f..ebfcf36e11 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -486,7 +486,7 @@ public:
mutable CCriticalSection cs;
indexed_transaction_set mapTx GUARDED_BY(cs);
- typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
+ using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator;
std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order
struct CompareIteratorByHash {
diff --git a/src/util.cpp b/src/util.cpp
index 48d64e3eec..ab262b4063 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -585,6 +585,13 @@ void ArgsManager::AddArg(const std::string& name, const std::string& help, const
assert(ret.second); // Make sure an insertion actually happened
}
+void ArgsManager::AddHiddenArgs(const std::vector<std::string>& names)
+{
+ for (const std::string& name : names) {
+ AddArg(name, "", false, OptionsCategory::HIDDEN);
+ }
+}
+
std::string ArgsManager::GetHelpMessage()
{
const bool show_debug = gArgs.GetBoolArg("-help-debug", false);
diff --git a/src/util.h b/src/util.h
index efd8a4bd9d..8094d72d6b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -264,6 +264,11 @@ public:
void AddArg(const std::string& name, const std::string& help, const bool debug_only, const OptionsCategory& cat);
/**
+ * Add many hidden arguments
+ */
+ void AddHiddenArgs(const std::vector<std::string>& args);
+
+ /**
* Clear available arguments
*/
void ClearArgs() { m_available_args.clear(); }
diff --git a/src/validation.cpp b/src/validation.cpp
index 60b48d38c3..3b8118b036 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -205,7 +205,7 @@ private:
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
CBlockIndex* FindMostWorkChain();
- bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
+ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params);
@@ -651,7 +651,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
view.SetBackend(viewMemPool);
// do all inputs exist?
- for (const CTxIn txin : tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
@@ -957,7 +957,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
// Remove conflicting transactions from the mempool
- for (const CTxMemPool::txiter it : allConflicting)
+ for (CTxMemPool::txiter it : allConflicting)
{
LogPrint(BCLog::MEMPOOL, "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
@@ -2698,6 +2698,9 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
// Block until the validation queue drains. This should largely
// never happen in normal operation, however may happen during
// reindex, causing memory blowup if we run too far ahead.
+ // Note that if a validationinterface callback ends up calling
+ // ActivateBestChain this may lead to a deadlock! We should
+ // probably have a DEBUG_LOCKORDER test for this in the future.
SyncWithValidationInterfaceQueue();
}
@@ -2950,7 +2953,7 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
}
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
-bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
+void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
{
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
@@ -2994,8 +2997,6 @@ bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationStat
mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
}
}
-
- return true;
}
static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
@@ -3507,7 +3508,6 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
// request; don't process these.
if (pindex->nChainWork < nMinimumChainWork) return true;
}
- if (fNewBlock) *fNewBlock = true;
if (!CheckBlock(block, state, chainparams.GetConsensus()) ||
!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) {
@@ -3524,14 +3524,14 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
GetMainSignals().NewPoWValidBlock(pindex, pblock);
// Write block to history file
+ if (fNewBlock) *fNewBlock = true;
try {
CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
if (blockPos.IsNull()) {
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
return false;
}
- if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
- return error("AcceptBlock(): ReceivedBlockTransactions failed");
+ ReceivedBlockTransactions(block, pindex, blockPos, chainparams.GetConsensus());
} catch (const std::runtime_error& e) {
return AbortNode(state, std::string("System error: ") + e.what());
}
@@ -3834,7 +3834,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
// Calculate nChainWork
std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size());
- for (const std::pair<uint256, CBlockIndex*>& item : mapBlockIndex)
+ for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
{
CBlockIndex* pindex = item.second;
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex));
@@ -3901,7 +3901,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams)
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
std::set<int> setBlkDataFiles;
- for (const std::pair<uint256, CBlockIndex*>& item : mapBlockIndex)
+ for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
{
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
@@ -4000,7 +4000,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
- if (pindex->nHeight < chainActive.Height()-nCheckDepth)
+ if (pindex->nHeight <= chainActive.Height()-nCheckDepth)
break;
if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
// If pruning, only go back as far as we have data.
@@ -4340,9 +4340,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
if (blockPos.IsNull())
return error("%s: writing genesis block to disk failed", __func__);
CBlockIndex *pindex = AddToBlockIndex(block);
- CValidationState state;
- if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
- return error("%s: genesis block not accepted (%s)", __func__, FormatStateMessage(state));
+ ReceivedBlockTransactions(block, pindex, blockPos, chainparams.GetConsensus());
} catch (const std::runtime_error& e) {
return error("%s: failed to write genesis block: %s", __func__, e.what());
}
diff --git a/src/validation.h b/src/validation.h
index 04f5b6cb80..b9c2f6c023 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -233,7 +233,8 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* Note that we guarantee that either the proof-of-work is valid on pblock, or
* (and possibly also) BlockChecked will have been called.
*
- * Call without cs_main held.
+ * May not be called with cs_main held. May not be called in a
+ * validationinterface callback.
*
* @param[in] pblock The block we want to process.
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
@@ -245,7 +246,8 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
/**
* Process incoming block headers.
*
- * Call without cs_main held.
+ * May not be called with cs_main held. May not be called in a
+ * validationinterface callback.
*
* @param[in] block The block headers themselves
* @param[out] state This may be set to an Error state if any error occurred processing them
@@ -278,7 +280,12 @@ void ThreadScriptCheck();
bool IsInitialBlockDownload();
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
-/** Find the best known block, and make it the tip of the block chain */
+/**
+ * Find the best known block, and make it the tip of the block chain
+ *
+ * May not be called with cs_main held. May not be called in a
+ * validationinterface callback.
+ */
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
@@ -445,7 +452,11 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash)
/** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
-/** Mark a block as precious and reorganize. */
+/** Mark a block as precious and reorganize.
+ *
+ * May not be called with cs_main held. May not be called in a
+ * validationinterface callback.
+ */
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex);
/** Mark a block as invalid. */
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 410dd5009f..01b8eacccb 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -694,8 +694,10 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
if (mapFileUseCount.empty()) {
dbenv->log_archive(&listp, DB_ARCH_REMOVE);
Close();
- if (!fMockDb)
+ if (!fMockDb) {
fs::remove_all(fs::path(strPath) / "database");
+ }
+ g_dbenvs.erase(strPath);
}
}
}
@@ -794,5 +796,6 @@ void BerkeleyDatabase::Flush(bool shutdown)
{
if (!IsDummy()) {
env->Flush(shutdown);
+ if (shutdown) env = nullptr;
}
}
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index daeff1d0e8..74312b7124 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -200,7 +200,7 @@ bool WalletInit::Verify() const
// Keep track of each wallet absolute path to detect duplicates.
std::set<fs::path> wallet_paths;
- for (const auto wallet_file : wallet_files) {
+ for (const auto& wallet_file : wallet_files) {
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
if (!wallet_paths.insert(wallet_path).second) {
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d09af1dbd1..882ddbbe4e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -441,7 +441,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 94c35e2cb1..bc381d3cda 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -40,12 +40,21 @@
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
-std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name)
{
if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used
- std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
- std::shared_ptr<CWallet> pwallet = GetWallet(requestedWallet);
+ wallet_name = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
+ return true;
+ }
+ return false;
+}
+
+std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+{
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ std::shared_ptr<CWallet> pwallet = GetWallet(wallet_name);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
@@ -66,11 +75,6 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
if (pwallet) return true;
if (avoidException) return false;
if (!HasWallets()) {
- // Note: It isn't currently possible to trigger this error because
- // wallet RPC methods aren't registered unless a wallet is loaded. But
- // this error is being kept as a precaution, because it's possible in
- // the future that wallet RPC methods might get or remain registered
- // when no wallets are loaded.
throw JSONRPCError(
RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
}
@@ -120,7 +124,7 @@ static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
}
entry.pushKV("bip125-replaceable", rbfStatus);
- for (const std::pair<std::string, std::string>& item : wtx.mapValue)
+ for (const std::pair<const std::string, std::string>& item : wtx.mapValue)
entry.pushKV(item.first, item.second);
}
@@ -343,7 +347,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
// If so, delete the account record for it. Labels, unlike addresses, can be deleted,
// and if we wouldn't do this, the record would stick around forever.
bool found_address = false;
- for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
if (item.second.name == label) {
found_address = true;
break;
@@ -440,7 +444,7 @@ static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
// Find all addresses that have the given account
UniValue ret(UniValue::VARR);
- for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
const CTxDestination& dest = item.first;
const std::string& strName = item.second.name;
if (strName == strAccount) {
@@ -753,7 +757,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
// Tally
CAmount nAmount = 0;
- for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
@@ -821,7 +825,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
// Tally
CAmount nAmount = 0;
- for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
@@ -1017,6 +1021,14 @@ static UniValue sendfrom(const JSONRPCRequest& request)
return NullUniValue;
}
+ if (!IsDeprecatedRPCEnabled("accounts")) {
+ if (request.fHelp) {
+ throw std::runtime_error("sendfrom (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
+ }
+ throw JSONRPCError(RPC_METHOD_DEPRECATED, "sendfrom is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
+ }
+
+
if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
throw std::runtime_error(
"sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
@@ -1255,9 +1267,11 @@ static UniValue sendmany(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
// Check funds
- CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
- if (totalAmount > nBalance)
+ if (IsDeprecatedRPCEnabled("accounts") && totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount)) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
+ } else if (!IsDeprecatedRPCEnabled("accounts") && totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, nullptr)) {
+ throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds");
+ }
// Shuffle recipient list
std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext());
@@ -1527,7 +1541,7 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
// Tally
std::map<CTxDestination, tallyitem> mapTally;
- for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
@@ -2106,13 +2120,13 @@ static UniValue listaccounts(const JSONRPCRequest& request)
includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
std::map<std::string, CAmount> mapAccountBalances;
- for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
if (IsMine(*pwallet, entry.first) & includeWatchonly) { // This address belongs to me
mapAccountBalances[entry.second.name] = 0;
}
}
- for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
CAmount nFee;
std::string strSentAccount;
@@ -2141,7 +2155,7 @@ static UniValue listaccounts(const JSONRPCRequest& request)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
UniValue ret(UniValue::VOBJ);
- for (const std::pair<std::string, CAmount>& accountBalance : mapAccountBalances) {
+ for (const std::pair<const std::string, CAmount>& accountBalance : mapAccountBalances) {
ret.pushKV(accountBalance.first, ValueFromAmount(accountBalance.second));
}
return ret;
@@ -2250,7 +2264,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
UniValue transactions(UniValue::VARR);
- for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
+ for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
CWalletTx tx = pairWtx.second;
if (depth == -1 || tx.GetDepthInMainChain() < depth) {
@@ -3053,7 +3067,7 @@ static UniValue listwallets(const JSONRPCRequest& request)
return obj;
}
-UniValue loadwallet(const JSONRPCRequest& request)
+static UniValue loadwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -3100,7 +3114,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
return obj;
}
-UniValue createwallet(const JSONRPCRequest& request)
+static UniValue createwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
@@ -3147,6 +3161,55 @@ UniValue createwallet(const JSONRPCRequest& request)
return obj;
}
+static UniValue unloadwallet(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 1) {
+ throw std::runtime_error(
+ "unloadwallet ( \"wallet_name\" )\n"
+ "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
+ "Specifying the wallet name on a wallet endpoint is invalid."
+ "\nArguments:\n"
+ "1. \"wallet_name\" (string, optional) The name of the wallet to unload.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("unloadwallet", "wallet_name")
+ + HelpExampleRpc("unloadwallet", "wallet_name")
+ );
+ }
+
+ std::string wallet_name;
+ if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
+ if (!request.params[0].isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
+ }
+ } else {
+ wallet_name = request.params[0].get_str();
+ }
+
+ std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
+ if (!wallet) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
+ }
+
+ // Release the "main" shared pointer and prevent further notifications.
+ // Note that any attempt to load the same wallet would fail until the wallet
+ // is destroyed (see CheckUniqueFileid).
+ if (!RemoveWallet(wallet)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
+ }
+ UnregisterValidationInterface(wallet.get());
+
+ // The wallet can be in use so it's not possible to explicitly unload here.
+ // Just notify the unload intent so that all shared pointers are released.
+ // The wallet will be destroyed once the last shared pointer is released.
+ wallet->NotifyUnload();
+
+ // There's no point in waiting for the wallet to unload.
+ // At this point this method should never fail. The unloading could only
+ // fail due to an unexpected error which would cause a process termination.
+
+ return NullUniValue;
+}
+
static UniValue resendwallettransactions(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -4187,7 +4250,7 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
- for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
if (item.second.name == label) {
ret.pushKV(EncodeDestination(item.first), AddressBookDataToJSON(item.second, false));
}
@@ -4240,7 +4303,7 @@ static UniValue listlabels(const JSONRPCRequest& request)
// Add to a set to sort by label name, then insert into Univalue array
std::set<std::string> label_set;
- for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
+ for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
if (purpose.empty() || entry.second.purpose == purpose) {
label_set.insert(entry.second.name);
}
@@ -4376,12 +4439,12 @@ static const CRPCCommand commands[] =
{ "wallet", "listwallets", &listwallets, {} },
{ "wallet", "loadwallet", &loadwallet, {"filename"} },
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
- { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
{ "wallet", "sendmany", &sendmany, {"fromaccount|dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
{ "wallet", "settxfee", &settxfee, {"amount"} },
{ "wallet", "signmessage", &signmessage, {"address","message"} },
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
+ { "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
{ "wallet", "walletlock", &walletlock, {} },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
@@ -4397,6 +4460,7 @@ static const CRPCCommand commands[] =
{ "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
{ "wallet", "listreceivedbyaccount", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
{ "wallet", "setaccount", &setlabel, {"address","account"} },
+ { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
{ "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
/** Label functions (to replace non-balance account functions) */
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 78cacc0206..842516bb0e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -79,6 +79,15 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+// Custom deleter for shared_ptr<CWallet>.
+static void ReleaseWallet(CWallet* wallet)
+{
+ LogPrintf("Releasing wallet %s\n", wallet->GetName());
+ wallet->BlockUntilSyncedToCurrentChain();
+ wallet->Flush();
+ delete wallet;
+}
+
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@@ -600,6 +609,8 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
{
mapTxSpends.insert(std::make_pair(outpoint, wtxid));
+ setLockedCoins.erase(outpoint);
+
std::pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
SyncMetaData(range);
@@ -923,11 +934,10 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
CWalletTx& wtx = (*ret.first).second;
wtx.BindWallet(this);
bool fInsertedNew = ret.second;
- if (fInsertedNew)
- {
+ if (fInsertedNew) {
wtx.nTimeReceived = GetAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(&batch);
- wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
+ wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
wtx.nTimeSmart = ComputeTimeSmart(wtx);
AddToSpends(hash);
}
@@ -998,9 +1008,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
- CWalletTx& wtx = mapWallet.emplace(hash, wtxIn).first->second;
+ const auto& ins = mapWallet.emplace(hash, wtxIn);
+ CWalletTx& wtx = ins.first->second;
wtx.BindWallet(this);
- wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
+ if (/* insertion took place */ ins.second) {
+ wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
+ }
AddToSpends(hash);
for (const CTxIn& txin : wtx.tx->vin) {
auto it = mapWallet.find(txin.prevout.hash);
@@ -1294,7 +1307,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
LOCK(cs_main);
const CBlockIndex* initialChainTip = chainActive.Tip();
- if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
+ if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
return;
}
}
@@ -3210,8 +3223,11 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
{
AssertLockHeld(cs_wallet); // mapWallet
DBErrors nZapSelectTxRet = WalletBatch(*database,"cr+").ZapSelectTx(vHashIn, vHashOut);
- for (uint256 hash : vHashOut)
- mapWallet.erase(hash);
+ for (uint256 hash : vHashOut) {
+ const auto& it = mapWallet.find(hash);
+ wtxOrdered.erase(it->second.m_it_wtxOrdered);
+ mapWallet.erase(it);
+ }
if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
{
@@ -3284,7 +3300,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
// Delete destdata tuples associated with address
std::string strAddress = EncodeDestination(address);
- for (const std::pair<std::string, std::string> &item : mapAddressBook[address].destdata)
+ for (const std::pair<const std::string, std::string> &item : mapAddressBook[address].destdata)
{
WalletBatch(*database).EraseDestData(strAddress, item.first);
}
@@ -3685,7 +3701,7 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
{
LOCK(cs_wallet);
std::set<CTxDestination> result;
- for (const std::pair<CTxDestination, CAddressBookData>& item : mapAddressBook)
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : mapAddressBook)
{
const CTxDestination& address = item.first;
const std::string& strName = item.second.name;
@@ -4061,7 +4077,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
+ // 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);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
@@ -4090,8 +4108,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
}
- uiInterface.LoadWallet(walletInstance);
-
int prev_version = walletInstance->nWalletVersion;
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
{
@@ -4341,6 +4357,8 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
}
+ uiInterface.LoadWallet(walletInstance);
+
// Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main.
RegisterValidationInterface(walletInstance.get());
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 1ec2a9e771..b829394847 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -339,6 +339,7 @@ public:
char fFromMe;
std::string strFromAccount;
int64_t nOrderPos; //!< position in ordered transaction list
+ std::multimap<int64_t, std::pair<CWalletTx*, CAccountingEntry*>>::const_iterator m_it_wtxOrdered;
// memory only
mutable bool fDebitCached;
@@ -1099,6 +1100,9 @@ public:
//! Flush wallet (bitdb flush)
void Flush(bool shutdown=false);
+ /** Wallet is about to be unloaded */
+ boost::signals2::signal<void ()> NotifyUnload;
+
/**
* Address book entry changed.
* @note called with lock cs_wallet held.