diff options
Diffstat (limited to 'src')
378 files changed, 4194 insertions, 3423 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3e43076878..4b65774fc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ else LIBUNIVALUE = $(UNIVALUE_LIBS) endif -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) @@ -168,6 +168,7 @@ BITCOIN_CORE_H = \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ + wallet/walletutil.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ @@ -249,6 +250,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ + wallet/walletutil.cpp \ $(BITCOIN_CORE_H) # crypto primitives library diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 0767ee1302..0bdde06772 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -362,8 +362,7 @@ RES_MOVIES = $(wildcard $(srcdir)/qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc -BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \ - -I$(builddir)/qt/forms -DQT_NO_KEYWORDS +BITCOIN_QT_INCLUDES = -DQT_NO_KEYWORDS qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) @@ -439,7 +438,7 @@ $(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ -CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno +CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno qt/temp_bitcoin_locale.qrc CLEANFILES += $(CLEAN_QT) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index d3e7b5da12..06175be3fc 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -80,6 +80,7 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ + test/txvalidation_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ @@ -96,7 +97,7 @@ BITCOIN_TESTS += \ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) -test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) +test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS) test_test_bitcoin_LDADD = if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 7f85c16585..7d7f34863d 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -3,17 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "addrdb.h" - -#include "addrman.h" -#include "chainparams.h" -#include "clientversion.h" -#include "fs.h" -#include "hash.h" -#include "random.h" -#include "streams.h" -#include "tinyformat.h" -#include "util.h" +#include <addrdb.h> + +#include <addrman.h> +#include <chainparams.h> +#include <clientversion.h> +#include <hash.h> +#include <random.h> +#include <streams.h> +#include <tinyformat.h> +#include <util.h> namespace { diff --git a/src/addrdb.h b/src/addrdb.h index d930de204d..098da4240e 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_ADDRDB_H #define BITCOIN_ADDRDB_H -#include "fs.h" -#include "serialize.h" +#include <fs.h> +#include <serialize.h> #include <string> #include <map> diff --git a/src/addrman.cpp b/src/addrman.cpp index a56bb4f9c1..372cac8483 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "addrman.h" +#include <addrman.h> -#include "hash.h" -#include "serialize.h" -#include "streams.h" +#include <hash.h> +#include <serialize.h> +#include <streams.h> int CAddrInfo::GetTriedBucket(const uint256& nKey) const { @@ -390,9 +390,9 @@ int CAddrMan::Check_() if (vRandom.size() != nTried + nNew) return -7; - for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - int n = (*it).first; - CAddrInfo& info = (*it).second; + for (const auto& entry : mapInfo) { + int n = entry.first; + const CAddrInfo& info = entry.second; if (info.fInTried) { if (!info.nLastSuccess) return -1; diff --git a/src/addrman.h b/src/addrman.h index f347cba6ca..ea289d508c 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -6,12 +6,12 @@ #ifndef BITCOIN_ADDRMAN_H #define BITCOIN_ADDRMAN_H -#include "netaddress.h" -#include "protocol.h" -#include "random.h" -#include "sync.h" -#include "timedata.h" -#include "util.h" +#include <netaddress.h> +#include <protocol.h> +#include <random.h> +#include <sync.h> +#include <timedata.h> +#include <util.h> #include <map> #include <set> @@ -313,9 +313,9 @@ public: s << nUBuckets; std::map<int, int> mapUnkIds; int nIds = 0; - for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - mapUnkIds[(*it).first] = nIds; - const CAddrInfo &info = (*it).second; + for (const auto& entry : mapInfo) { + mapUnkIds[entry.first] = nIds; + const CAddrInfo &info = entry.second; if (info.nRefCount) { assert(nIds != nNew); // this means nNew was wrong, oh ow s << info; @@ -323,8 +323,8 @@ public: } } nIds = 0; - for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) { - const CAddrInfo &info = (*it).second; + for (const auto& entry : mapInfo) { + const CAddrInfo &info = entry.second; if (info.fInTried) { assert(nIds != nTried); // this means nTried was wrong, oh ow s << info; diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index b4952af6f4..738224fb70 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "arith_uint256.h" +#include <arith_uint256.h> -#include "uint256.h" -#include "utilstrencodings.h" -#include "crypto/common.h" +#include <uint256.h> +#include <utilstrencodings.h> +#include <crypto/common.h> #include <stdio.h> #include <string.h> diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 5fd4fe96cf..1009fe1cc8 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -25,7 +25,7 @@ template<unsigned int BITS> class base_uint { protected: - enum { WIDTH=BITS/32 }; + static constexpr int WIDTH = BITS / 32; uint32_t pn[WIDTH]; public: diff --git a/src/base58.cpp b/src/base58.cpp index 9d5a2f4964..cd087e7997 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" +#include <base58.h> -#include "bech32.h" -#include "hash.h" -#include "script/script.h" -#include "uint256.h" -#include "utilstrencodings.h" +#include <bech32.h> +#include <hash.h> +#include <script/script.h> +#include <uint256.h> +#include <utilstrencodings.h> #include <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> diff --git a/src/base58.h b/src/base58.h index 9dc4234248..fee79f02bf 100644 --- a/src/base58.h +++ b/src/base58.h @@ -14,11 +14,11 @@ #ifndef BITCOIN_BASE58_H #define BITCOIN_BASE58_H -#include "chainparams.h" -#include "key.h" -#include "pubkey.h" -#include "script/standard.h" -#include "support/allocators/zeroafterfree.h" +#include <chainparams.h> +#include <key.h> +#include <pubkey.h> +#include <script/standard.h> +#include <support/allocators/zeroafterfree.h> #include <string> #include <vector> diff --git a/src/bech32.cpp b/src/bech32.cpp index 573eac58bb..274782e467 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bech32.h" +#include <bech32.h> namespace { diff --git a/src/bench/Examples.cpp b/src/bench/Examples.cpp index 314947d48c..536e450940 100644 --- a/src/bench/Examples.cpp +++ b/src/bench/Examples.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "validation.h" -#include "utiltime.h" +#include <bench/bench.h> +#include <validation.h> +#include <utiltime.h> // Sanity test: this should loop ten times, and // min/max/average should be close to 100ms. diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index c74a958c8b..2d9a9f2908 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" +#include <bench/bench.h> -#include "validation.h" -#include "base58.h" +#include <validation.h> +#include <base58.h> #include <array> #include <vector> diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index dd4ba5ab0e..1482452814 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "perf.h" +#include <bench/bench.h> +#include <bench/perf.h> #include <assert.h> #include <iostream> @@ -23,6 +23,9 @@ void benchmark::BenchRunner::RunAll(benchmark::duration elapsedTimeForOne) { perf_init(); + if (std::ratio_less_equal<benchmark::clock::period, std::micro>::value) { + std::cerr << "WARNING: Clock precision is worse than microsecond - benchmarks may be less accurate!\n"; + } std::cout << "#Benchmark" << "," << "count" << "," << "min(ns)" << "," << "max(ns)" << "," << "average(ns)" << "," << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; diff --git a/src/bench/bench.h b/src/bench/bench.h index d276f4ee91..071a5dc9c7 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -37,13 +37,11 @@ BENCHMARK(CODE_TO_TIME); */ namespace benchmark { - // On many systems, the high_resolution_clock offers no better resolution than the steady_clock. - // If that's the case, prefer the steady_clock. + // In case high_resolution_clock is steady, prefer that, otherwise use steady_clock. struct best_clock { using hi_res_clock = std::chrono::high_resolution_clock; using steady_clock = std::chrono::steady_clock; - static constexpr bool steady_is_high_res = std::ratio_less_equal<steady_clock::period, hi_res_clock::period>::value; - using type = std::conditional<steady_is_high_res, steady_clock, hi_res_clock>::type; + using type = std::conditional<hi_res_clock::is_steady, hi_res_clock, steady_clock>::type; }; using clock = best_clock::type; using time_point = clock::time_point; @@ -61,12 +59,17 @@ namespace benchmark { uint64_t minCycles; uint64_t maxCycles; public: - State(std::string _name, duration _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) { - minTime = duration::max(); - maxTime = duration::zero(); - minCycles = std::numeric_limits<uint64_t>::max(); - maxCycles = std::numeric_limits<uint64_t>::min(); - countMask = 1; + State(std::string _name, duration _maxElapsed) : + name(_name), + maxElapsed(_maxElapsed), + minTime(duration::max()), + maxTime(duration::zero()), + count(0), + countMask(1), + beginCycles(0), + lastCycles(0), + minCycles(std::numeric_limits<uint64_t>::max()), + maxCycles(std::numeric_limits<uint64_t>::min()) { } bool KeepRunning(); }; diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 37fd772435..84e51d809a 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" +#include <bench/bench.h> -#include "crypto/sha256.h" -#include "key.h" -#include "validation.h" -#include "util.h" -#include "random.h" +#include <crypto/sha256.h> +#include <key.h> +#include <validation.h> +#include <util.h> +#include <random.h> int main(int argc, char** argv) diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp index 5aab3381fd..89ba3d3d21 100644 --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "coins.h" -#include "policy/policy.h" -#include "wallet/crypter.h" +#include <bench/bench.h> +#include <coins.h> +#include <policy/policy.h> +#include <wallet/crypter.h> #include <vector> diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index 7bb1b93668..9533b3c711 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -2,15 +2,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" +#include <bench/bench.h> -#include "chainparams.h" -#include "validation.h" -#include "streams.h" -#include "consensus/validation.h" +#include <chainparams.h> +#include <validation.h> +#include <streams.h> +#include <consensus/validation.h> namespace block_bench { -#include "bench/data/block413567.raw.h" +#include <bench/data/block413567.raw.h> } // namespace block_bench // These are the two major time-sinks which happen after we have fully received diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 94064c9ca6..35750aa1b6 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "util.h" -#include "validation.h" -#include "checkqueue.h" -#include "prevector.h" +#include <bench/bench.h> +#include <util.h> +#include <validation.h> +#include <checkqueue.h> +#include <prevector.h> #include <vector> #include <boost/thread/thread.hpp> -#include "random.h" +#include <random.h> // This Benchmark tests the CheckQueue with the lightest diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index f8956508f6..ff57f88170 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "wallet/wallet.h" +#include <bench/bench.h> +#include <wallet/wallet.h> #include <set> diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 410a08e512..b37b5cad62 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -4,16 +4,16 @@ #include <iostream> -#include "bench.h" -#include "bloom.h" -#include "hash.h" -#include "random.h" -#include "uint256.h" -#include "utiltime.h" -#include "crypto/ripemd160.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/sha512.h" +#include <bench/bench.h> +#include <bloom.h> +#include <hash.h> +#include <random.h> +#include <uint256.h> +#include <utiltime.h> +#include <crypto/ripemd160.h> +#include <crypto/sha1.h> +#include <crypto/sha256.h> +#include <crypto/sha512.h> /* Number of bytes to hash per iteration */ static const uint64_t BUFFER_SIZE = 1000*1000; diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp index c6a05567be..b0bfa95144 100644 --- a/src/bench/lockedpool.cpp +++ b/src/bench/lockedpool.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" +#include <bench/bench.h> -#include "support/lockedpool.h" +#include <support/lockedpool.h> #include <iostream> #include <vector> diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index 073bbde016..eda6edbb23 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "policy/policy.h" -#include "txmempool.h" +#include <bench/bench.h> +#include <policy/policy.h> +#include <txmempool.h> #include <list> #include <vector> diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp index a549ec29ea..4045670a31 100644 --- a/src/bench/perf.cpp +++ b/src/bench/perf.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "perf.h" +#include <bench/perf.h> #if defined(__i386__) || defined(__x86_64__) diff --git a/src/bench/prevector_destructor.cpp b/src/bench/prevector_destructor.cpp index 55af3de4fe..de7ecab737 100644 --- a/src/bench/prevector_destructor.cpp +++ b/src/bench/prevector_destructor.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "prevector.h" +#include <bench/bench.h> +#include <prevector.h> static void PrevectorDestructor(benchmark::State& state) { diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp index a93d0fb0a5..452099b800 100644 --- a/src/bench/rollingbloom.cpp +++ b/src/bench/rollingbloom.cpp @@ -4,8 +4,8 @@ #include <iostream> -#include "bench.h" -#include "bloom.h" +#include <bench/bench.h> +#include <bloom.h> static void RollingBloom(benchmark::State& state) { diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index ef7381c120..bfa5806c9d 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bench.h" -#include "key.h" +#include <bench/bench.h> +#include <key.h> #if defined(HAVE_CONSENSUS_LIB) -#include "script/bitcoinconsensus.h" +#include <script/bitcoinconsensus.h> #endif -#include "script/script.h" -#include "script/sign.h" -#include "streams.h" +#include <script/script.h> +#include <script/sign.h> +#include <streams.h> #include <array> diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index e21a269221..136981b709 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -4,22 +4,22 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "chainparamsbase.h" -#include "clientversion.h" -#include "fs.h" -#include "rpc/client.h" -#include "rpc/protocol.h" -#include "util.h" -#include "utilstrencodings.h" +#include <chainparamsbase.h> +#include <clientversion.h> +#include <fs.h> +#include <rpc/client.h> +#include <rpc/protocol.h> +#include <util.h> +#include <utilstrencodings.h> #include <stdio.h> #include <event2/buffer.h> #include <event2/keyvalq_struct.h> -#include "support/events.h" +#include <support/events.h> #include <univalue.h> @@ -213,6 +213,9 @@ public: /** Create a simulated `getinfo` request. */ UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override { + if (!args.empty()) { + throw std::runtime_error("-getinfo takes no arguments"); + } UniValue result(UniValue::VARR); result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO)); result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO)); diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index b499b15507..c9223dbf10 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -3,24 +3,24 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "base58.h" -#include "clientversion.h" -#include "coins.h" -#include "consensus/consensus.h" -#include "core_io.h" -#include "keystore.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "primitives/transaction.h" -#include "script/script.h" -#include "script/sign.h" +#include <base58.h> +#include <clientversion.h> +#include <coins.h> +#include <consensus/consensus.h> +#include <core_io.h> +#include <keystore.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <script/sign.h> #include <univalue.h> -#include "util.h" -#include "utilmoneystr.h" -#include "utilstrencodings.h" +#include <util.h> +#include <utilmoneystr.h> +#include <utilstrencodings.h> #include <stdio.h> diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 5f88c35dbd..bc23912d2b 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -4,21 +4,21 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "chainparams.h" -#include "clientversion.h" -#include "compat.h" -#include "fs.h" -#include "rpc/server.h" -#include "init.h" -#include "noui.h" -#include "scheduler.h" -#include "util.h" -#include "httpserver.h" -#include "httprpc.h" -#include "utilstrencodings.h" +#include <chainparams.h> +#include <clientversion.h> +#include <compat.h> +#include <fs.h> +#include <rpc/server.h> +#include <init.h> +#include <noui.h> +#include <scheduler.h> +#include <util.h> +#include <httpserver.h> +#include <httprpc.h> +#include <utilstrencodings.h> #include <boost/thread.hpp> diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 6f27b7b9dc..6ff4d97bf4 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -2,16 +2,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "blockencodings.h" -#include "consensus/consensus.h" -#include "consensus/validation.h" -#include "chainparams.h" -#include "hash.h" -#include "random.h" -#include "streams.h" -#include "txmempool.h" -#include "validation.h" -#include "util.h" +#include <blockencodings.h> +#include <consensus/consensus.h> +#include <consensus/validation.h> +#include <chainparams.h> +#include <hash.h> +#include <random.h> +#include <streams.h> +#include <txmempool.h> +#include <validation.h> +#include <util.h> #include <unordered_map> diff --git a/src/blockencodings.h b/src/blockencodings.h index 50478f9f32..d034bb3080 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_BLOCK_ENCODINGS_H #define BITCOIN_BLOCK_ENCODINGS_H -#include "primitives/block.h" +#include <primitives/block.h> #include <memory> diff --git a/src/bloom.cpp b/src/bloom.cpp index fa884f0bf3..11ea099637 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bloom.h" - -#include "primitives/transaction.h" -#include "hash.h" -#include "script/script.h" -#include "script/standard.h" -#include "random.h" -#include "streams.h" +#include <bloom.h> + +#include <primitives/transaction.h> +#include <hash.h> +#include <script/script.h> +#include <script/standard.h> +#include <random.h> +#include <streams.h> #include <math.h> #include <stdlib.h> diff --git a/src/bloom.h b/src/bloom.h index 7ca9682239..d29a8dcd6f 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_BLOOM_H #define BITCOIN_BLOOM_H -#include "serialize.h" +#include <serialize.h> #include <vector> diff --git a/src/chain.cpp b/src/chain.cpp index 5e3dd9b31b..7ebc08a50b 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" +#include <chain.h> /** * CChain implementation @@ -80,12 +80,13 @@ int static inline GetSkipHeight(int height) { return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height); } -CBlockIndex* CBlockIndex::GetAncestor(int height) +const CBlockIndex* CBlockIndex::GetAncestor(int height) const { - if (height > nHeight || height < 0) + if (height > nHeight || height < 0) { return nullptr; + } - CBlockIndex* pindexWalk = this; + const CBlockIndex* pindexWalk = this; int heightWalk = nHeight; while (heightWalk > height) { int heightSkip = GetSkipHeight(heightWalk); @@ -106,9 +107,9 @@ CBlockIndex* CBlockIndex::GetAncestor(int height) return pindexWalk; } -const CBlockIndex* CBlockIndex::GetAncestor(int height) const +CBlockIndex* CBlockIndex::GetAncestor(int height) { - return const_cast<CBlockIndex*>(this)->GetAncestor(height); + return const_cast<CBlockIndex*>(static_cast<const CBlockIndex*>(this)->GetAncestor(height)); } void CBlockIndex::BuildSkip() diff --git a/src/chain.h b/src/chain.h index f1036e5d92..ca1900c22b 100644 --- a/src/chain.h +++ b/src/chain.h @@ -6,11 +6,11 @@ #ifndef BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H -#include "arith_uint256.h" -#include "primitives/block.h" -#include "pow.h" -#include "tinyformat.h" -#include "uint256.h" +#include <arith_uint256.h> +#include <primitives/block.h> +#include <pow.h> +#include <tinyformat.h> +#include <uint256.h> #include <vector> @@ -304,7 +304,7 @@ public: return (int64_t)nTimeMax; } - enum { nMedianTimeSpan=11 }; + static constexpr int nMedianTimeSpan = 11; int64_t GetMedianTimePast() const { diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 77c17c061c..e75d3be4c1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -3,16 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chainparams.h" -#include "consensus/merkle.h" +#include <chainparams.h> +#include <consensus/merkle.h> -#include "tinyformat.h" -#include "util.h" -#include "utilstrencodings.h" +#include <tinyformat.h> +#include <util.h> +#include <utilstrencodings.h> #include <assert.h> -#include "chainparamsseeds.h" +#include <chainparamsseeds.h> static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { diff --git a/src/chainparams.h b/src/chainparams.h index 3948c9163f..0d82a998b1 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -6,10 +6,10 @@ #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H -#include "chainparamsbase.h" -#include "consensus/params.h" -#include "primitives/block.h" -#include "protocol.h" +#include <chainparamsbase.h> +#include <consensus/params.h> +#include <primitives/block.h> +#include <protocol.h> #include <memory> #include <vector> diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index c966683b72..a7e87faee3 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chainparamsbase.h" +#include <chainparamsbase.h> -#include "tinyformat.h" -#include "util.h" +#include <tinyformat.h> +#include <util.h> #include <assert.h> diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 5afe3e66b6..929d864588 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -2,13 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "checkpoints.h" +#include <checkpoints.h> -#include "chain.h" -#include "chainparams.h" -#include "reverse_iterator.h" -#include "validation.h" -#include "uint256.h" +#include <chain.h> +#include <chainparams.h> +#include <reverse_iterator.h> +#include <validation.h> #include <stdint.h> diff --git a/src/checkpoints.h b/src/checkpoints.h index 7449d1063b..df97a674a8 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CHECKPOINTS_H #define BITCOIN_CHECKPOINTS_H -#include "uint256.h" +#include <uint256.h> #include <map> diff --git a/src/checkqueue.h b/src/checkqueue.h index 6377fbe942..08de336079 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CHECKQUEUE_H #define BITCOIN_CHECKQUEUE_H -#include "sync.h" +#include <sync.h> #include <algorithm> #include <vector> diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 8a4b408831..1934e71bbc 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -2,11 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "clientversion.h" +#include <clientversion.h> -#include "tinyformat.h" +#include <tinyformat.h> -#include <string> /** * Name of client reported in the 'version' message. Report the same name @@ -39,7 +38,7 @@ const std::string CLIENT_NAME("Satoshi"); //! First, include build.h if requested #ifdef HAVE_BUILD_INFO -#include "build.h" +#include <obj/build.h> #endif //! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$ diff --git a/src/clientversion.h b/src/clientversion.h index 3d5392619b..3a3d117d53 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -6,7 +6,7 @@ #define BITCOIN_CLIENTVERSION_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif //HAVE_CONFIG_H // Check that required client information is defined diff --git a/src/coins.cpp b/src/coins.cpp index b45dfc3342..afaf5ccc13 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -2,13 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "coins.h" +#include <coins.h> -#include "consensus/consensus.h" -#include "memusage.h" -#include "random.h" - -#include <assert.h> +#include <consensus/consensus.h> +#include <random.h> bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; } uint256 CCoinsView::GetBestBlock() const { return uint256(); } @@ -146,56 +143,58 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { } bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) { - for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { - if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization). - CCoinsMap::iterator itUs = cacheCoins.find(it->first); - if (itUs == cacheCoins.end()) { - // The parent cache does not have an entry, while the child does - // We can ignore it if it's both FRESH and pruned in the child - if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) { - // Otherwise we will need to create it in the parent - // and move the data up and mark it as dirty - CCoinsCacheEntry& entry = cacheCoins[it->first]; - entry.coin = std::move(it->second.coin); - cachedCoinsUsage += entry.coin.DynamicMemoryUsage(); - entry.flags = CCoinsCacheEntry::DIRTY; - // We can mark it FRESH in the parent if it was FRESH in the child - // Otherwise it might have just been flushed from the parent's cache - // and already exist in the grandparent - if (it->second.flags & CCoinsCacheEntry::FRESH) - entry.flags |= CCoinsCacheEntry::FRESH; + for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) { + // Ignore non-dirty entries (optimization). + if (!(it->second.flags & CCoinsCacheEntry::DIRTY)) { + continue; + } + CCoinsMap::iterator itUs = cacheCoins.find(it->first); + if (itUs == cacheCoins.end()) { + // The parent cache does not have an entry, while the child does + // We can ignore it if it's both FRESH and pruned in the child + if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) { + // Otherwise we will need to create it in the parent + // and move the data up and mark it as dirty + CCoinsCacheEntry& entry = cacheCoins[it->first]; + entry.coin = std::move(it->second.coin); + cachedCoinsUsage += entry.coin.DynamicMemoryUsage(); + entry.flags = CCoinsCacheEntry::DIRTY; + // We can mark it FRESH in the parent if it was FRESH in the child + // Otherwise it might have just been flushed from the parent's cache + // and already exist in the grandparent + if (it->second.flags & CCoinsCacheEntry::FRESH) { + entry.flags |= CCoinsCacheEntry::FRESH; } - } else { - // Assert that the child cache entry was not marked FRESH if the - // parent cache entry has unspent outputs. If this ever happens, - // it means the FRESH flag was misapplied and there is a logic - // error in the calling code. - if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) - throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs"); + } + } else { + // Assert that the child cache entry was not marked FRESH if the + // parent cache entry has unspent outputs. If this ever happens, + // it means the FRESH flag was misapplied and there is a logic + // error in the calling code. + if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) { + throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs"); + } - // Found the entry in the parent cache - if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) { - // The grandparent does not have an entry, and the child is - // modified and being pruned. This means we can just delete - // it from the parent. - cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage(); - cacheCoins.erase(itUs); - } else { - // A normal modification. - cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage(); - itUs->second.coin = std::move(it->second.coin); - cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage(); - itUs->second.flags |= CCoinsCacheEntry::DIRTY; - // NOTE: It is possible the child has a FRESH flag here in - // the event the entry we found in the parent is pruned. But - // we must not copy that FRESH flag to the parent as that - // pruned state likely still needs to be communicated to the - // grandparent. - } + // Found the entry in the parent cache + if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) { + // The grandparent does not have an entry, and the child is + // modified and being pruned. This means we can just delete + // it from the parent. + cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage(); + cacheCoins.erase(itUs); + } else { + // A normal modification. + cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage(); + itUs->second.coin = std::move(it->second.coin); + cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage(); + itUs->second.flags |= CCoinsCacheEntry::DIRTY; + // NOTE: It is possible the child has a FRESH flag here in + // the event the entry we found in the parent is pruned. But + // we must not copy that FRESH flag to the parent as that + // pruned state likely still needs to be communicated to the + // grandparent. } } - CCoinsMap::iterator itOld = it++; - mapCoins.erase(itOld); } hashBlock = hashBlockIn; return true; diff --git a/src/coins.h b/src/coins.h index 181b2fd4b9..0280abb56c 100644 --- a/src/coins.h +++ b/src/coins.h @@ -6,13 +6,13 @@ #ifndef BITCOIN_COINS_H #define BITCOIN_COINS_H -#include "primitives/transaction.h" -#include "compressor.h" -#include "core_memusage.h" -#include "hash.h" -#include "memusage.h" -#include "serialize.h" -#include "uint256.h" +#include <primitives/transaction.h> +#include <compressor.h> +#include <core_memusage.h> +#include <hash.h> +#include <memusage.h> +#include <serialize.h> +#include <uint256.h> #include <assert.h> #include <stdint.h> diff --git a/src/compat.h b/src/compat.h index 09657eccba..89cc4709a4 100644 --- a/src/compat.h +++ b/src/compat.h @@ -7,7 +7,7 @@ #define BITCOIN_COMPAT_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #ifdef WIN32 @@ -50,7 +50,7 @@ #ifndef WIN32 typedef unsigned int SOCKET; -#include "errno.h" +#include <errno.h> #define WSAGetLastError() errno #define WSAEINVAL EINVAL #define WSAEALREADY EALREADY diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h index d93ff7413a..a6df6ded7a 100644 --- a/src/compat/byteswap.h +++ b/src/compat/byteswap.h @@ -6,7 +6,7 @@ #define BITCOIN_COMPAT_BYTESWAP_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <stdint.h> @@ -37,7 +37,7 @@ inline uint16_t bswap_16(uint16_t x) { return (x >> 8) | (x << 8); } -#endif // HAVE_DECL_BSWAP16 +#endif // HAVE_DECL_BSWAP16 == 0 #if HAVE_DECL_BSWAP_32 == 0 inline uint32_t bswap_32(uint32_t x) @@ -45,7 +45,7 @@ inline uint32_t bswap_32(uint32_t x) return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) | ((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24)); } -#endif // HAVE_DECL_BSWAP32 +#endif // HAVE_DECL_BSWAP32 == 0 #if HAVE_DECL_BSWAP_64 == 0 inline uint64_t bswap_64(uint64_t x) @@ -59,7 +59,7 @@ inline uint64_t bswap_64(uint64_t x) | ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56)); } -#endif // HAVE_DECL_BSWAP64 +#endif // HAVE_DECL_BSWAP64 == 0 #endif // defined(__APPLE__) diff --git a/src/compat/endian.h b/src/compat/endian.h index dbf178f53c..9fabbd0bfb 100644 --- a/src/compat/endian.h +++ b/src/compat/endian.h @@ -6,10 +6,10 @@ #define BITCOIN_COMPAT_ENDIAN_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "compat/byteswap.h" +#include <compat/byteswap.h> #include <stdint.h> diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 3b9c70df7f..6633658c16 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <cstddef> diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index b4d1c90992..20d2ad3cb6 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <cstddef> diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp index 1ac266c2d1..313435a222 100644 --- a/src/compat/strnlen.cpp +++ b/src/compat/strnlen.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <cstring> diff --git a/src/compressor.cpp b/src/compressor.cpp index f4c12f38d2..a729e28f07 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "compressor.h" +#include <compressor.h> -#include "hash.h" -#include "pubkey.h" -#include "script/standard.h" +#include <hash.h> +#include <pubkey.h> +#include <script/standard.h> bool CScriptCompressor::IsToKeyID(CKeyID &hash) const { diff --git a/src/compressor.h b/src/compressor.h index 094c1bcfe1..8731eef9f7 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_COMPRESSOR_H #define BITCOIN_COMPRESSOR_H -#include "primitives/transaction.h" -#include "script/script.h" -#include "serialize.h" +#include <primitives/transaction.h> +#include <script/script.h> +#include <serialize.h> class CKeyID; class CPubKey; diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index ddd4ee9fab..6e3bac2d0e 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -24,12 +24,9 @@ static const size_t MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60; // 60 is static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction /** Flags for nSequence and nLockTime locks */ -enum { - /* Interpret sequence numbers as relative lock-time constraints. */ - LOCKTIME_VERIFY_SEQUENCE = (1 << 0), - - /* Use GetMedianTimePast() instead of nTime for end point timestamp. */ - LOCKTIME_MEDIAN_TIME_PAST = (1 << 1), -}; +/** Interpret sequence numbers as relative lock-time constraints. */ +static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0); +/** Use GetMedianTimePast() instead of nTime for end point timestamp. */ +static constexpr unsigned int LOCKTIME_MEDIAN_TIME_PAST = (1 << 1); #endif // BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 798ce4b5fd..fef4a5d560 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "merkle.h" -#include "hash.h" -#include "utilstrencodings.h" +#include <consensus/merkle.h> +#include <hash.h> +#include <utilstrencodings.h> /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index 33764c7460..c1573cc214 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -8,9 +8,9 @@ #include <stdint.h> #include <vector> -#include "primitives/transaction.h" -#include "primitives/block.h" -#include "uint256.h" +#include <primitives/transaction.h> +#include <primitives/block.h> +#include <uint256.h> uint256 ComputeMerkleRoot(const std::vector<uint256>& leaves, bool* mutated = nullptr); std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position); diff --git a/src/consensus/params.h b/src/consensus/params.h index fd0946a612..c9fbba12a2 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_CONSENSUS_PARAMS_H #define BITCOIN_CONSENSUS_PARAMS_H -#include "uint256.h" +#include <uint256.h> #include <limits> #include <map> #include <string> diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 70aa9d7006..be73d0a2f9 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -2,17 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "tx_verify.h" +#include <consensus/tx_verify.h> -#include "consensus.h" -#include "primitives/transaction.h" -#include "script/interpreter.h" -#include "validation.h" +#include <consensus/consensus.h> +#include <primitives/transaction.h> +#include <script/interpreter.h> +#include <consensus/validation.h> // TODO remove the following dependencies -#include "chain.h" -#include "coins.h" -#include "utilmoneystr.h" +#include <chain.h> +#include <coins.h> +#include <utilmoneystr.h> bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h index 288892462d..a4836ceda4 100644 --- a/src/consensus/tx_verify.h +++ b/src/consensus/tx_verify.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CONSENSUS_TX_VERIFY_H #define BITCOIN_CONSENSUS_TX_VERIFY_H -#include "amount.h" +#include <amount.h> #include <stdint.h> #include <vector> diff --git a/src/consensus/validation.h b/src/consensus/validation.h index b6740c9d9f..55f6c363fc 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -7,10 +7,10 @@ #define BITCOIN_CONSENSUS_VALIDATION_H #include <string> -#include "version.h" -#include "consensus/consensus.h" -#include "primitives/transaction.h" -#include "primitives/block.h" +#include <version.h> +#include <consensus/consensus.h> +#include <primitives/transaction.h> +#include <primitives/block.h> /** "reject" message codes */ static const unsigned char REJECT_MALFORMED = 0x01; diff --git a/src/core_io.h b/src/core_io.h index ccc72ebb32..7ed84d6665 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CORE_IO_H #define BITCOIN_CORE_IO_H -#include "amount.h" +#include <amount.h> #include <string> #include <vector> diff --git a/src/core_memusage.h b/src/core_memusage.h index f038e7b154..d234f0a9d0 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -5,9 +5,9 @@ #ifndef BITCOIN_CORE_MEMUSAGE_H #define BITCOIN_CORE_MEMUSAGE_H -#include "primitives/transaction.h" -#include "primitives/block.h" -#include "memusage.h" +#include <primitives/transaction.h> +#include <primitives/block.h> +#include <memusage.h> static inline size_t RecursiveDynamicUsage(const CScript& script) { return memusage::DynamicUsage(script); diff --git a/src/core_read.cpp b/src/core_read.cpp index 7018131a13..2f5b67b5c7 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -2,17 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "core_io.h" +#include <core_io.h> -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "script/script.h" -#include "serialize.h" -#include "streams.h" +#include <primitives/block.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <serialize.h> +#include <streams.h> #include <univalue.h> -#include "util.h" -#include "utilstrencodings.h" -#include "version.h" +#include <util.h> +#include <utilstrencodings.h> +#include <version.h> #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/predicate.hpp> diff --git a/src/core_write.cpp b/src/core_write.cpp index e16db13650..e97876bef3 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -2,19 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "core_io.h" - -#include "base58.h" -#include "consensus/consensus.h" -#include "consensus/validation.h" -#include "script/script.h" -#include "script/standard.h" -#include "serialize.h" -#include "streams.h" +#include <core_io.h> + +#include <base58.h> +#include <consensus/consensus.h> +#include <consensus/validation.h> +#include <script/script.h> +#include <script/standard.h> +#include <serialize.h> +#include <streams.h> #include <univalue.h> -#include "util.h" -#include "utilmoneystr.h" -#include "utilstrencodings.h" +#include <util.h> +#include <utilmoneystr.h> +#include <utilstrencodings.h> UniValue ValueFromAmount(const CAmount& amount) { diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 5e70d25eee..baba8bcad0 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "aes.h" -#include "crypto/common.h" +#include <crypto/aes.h> +#include <crypto/common.h> #include <assert.h> #include <string.h> extern "C" { -#include "crypto/ctaes/ctaes.c" +#include <crypto/ctaes/ctaes.c> } AES128Encrypt::AES128Encrypt(const unsigned char key[16]) diff --git a/src/crypto/aes.h b/src/crypto/aes.h index a7b63b19df..7dda94d291 100644 --- a/src/crypto/aes.h +++ b/src/crypto/aes.h @@ -8,7 +8,7 @@ #define BITCOIN_CRYPTO_AES_H extern "C" { -#include "crypto/ctaes/ctaes.h" +#include <crypto/ctaes/ctaes.h> } static const int AES_BLOCKSIZE = 16; diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp index 4038ae9f86..ac4470f04f 100644 --- a/src/crypto/chacha20.cpp +++ b/src/crypto/chacha20.cpp @@ -5,8 +5,8 @@ // Based on the public domain implementation 'merged' by D. J. Bernstein // See https://cr.yp.to/chacha.html. -#include "crypto/common.h" -#include "crypto/chacha20.h" +#include <crypto/common.h> +#include <crypto/chacha20.h> #include <string.h> diff --git a/src/crypto/common.h b/src/crypto/common.h index bd9bc9420b..5a193a4e64 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -6,13 +6,13 @@ #define BITCOIN_CRYPTO_COMMON_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <stdint.h> #include <string.h> -#include "compat/endian.h" +#include <compat/endian.h> uint16_t static inline ReadLE16(const unsigned char* ptr) { diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp index 3c791625d0..9366e216c2 100644 --- a/src/crypto/hmac_sha256.cpp +++ b/src/crypto/hmac_sha256.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/hmac_sha256.h" +#include <crypto/hmac_sha256.h> #include <string.h> diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h index 8c42fcfe14..40d40f9fb2 100644 --- a/src/crypto/hmac_sha256.h +++ b/src/crypto/hmac_sha256.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CRYPTO_HMAC_SHA256_H #define BITCOIN_CRYPTO_HMAC_SHA256_H -#include "crypto/sha256.h" +#include <crypto/sha256.h> #include <stdint.h> #include <stdlib.h> diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp index 5939c6ec47..f984201f6a 100644 --- a/src/crypto/hmac_sha512.cpp +++ b/src/crypto/hmac_sha512.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/hmac_sha512.h" +#include <crypto/hmac_sha512.h> #include <string.h> diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h index 17dee61ea8..6d3fd59f27 100644 --- a/src/crypto/hmac_sha512.h +++ b/src/crypto/hmac_sha512.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CRYPTO_HMAC_SHA512_H #define BITCOIN_CRYPTO_HMAC_SHA512_H -#include "crypto/sha512.h" +#include <crypto/sha512.h> #include <stdint.h> #include <stdlib.h> diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index 77c9acfc26..4afa9abd1e 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/ripemd160.h" +#include <crypto/ripemd160.h> -#include "crypto/common.h" +#include <crypto/common.h> #include <string.h> diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 0b895b33a2..8ccc5e112a 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/sha1.h" +#include <crypto/sha1.h> -#include "crypto/common.h" +#include <crypto/common.h> #include <string.h> diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 29afe86ec7..9a21aec20e 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/sha256.h" -#include "crypto/common.h" +#include <crypto/sha256.h> +#include <crypto/common.h> #include <assert.h> #include <string.h> diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp index 564127cc31..aa46e7ba86 100644 --- a/src/crypto/sha512.cpp +++ b/src/crypto/sha512.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/sha512.h" +#include <crypto/sha512.h> -#include "crypto/common.h" +#include <crypto/common.h> #include <string.h> diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index dfc90f3ab9..6ff740f581 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -2,11 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "dbwrapper.h" +#include <dbwrapper.h> -#include "fs.h" -#include "util.h" -#include "random.h" +#include <random.h> #include <leveldb/cache.h> #include <leveldb/env.h> @@ -64,7 +62,7 @@ public: assert(p <= limit); base[std::min(bufsize - 1, (int)(p - base))] = '\0'; - LogPrintStr(base); + LogPrintf("leveldb: %s", base); if (base != buffer) { delete[] base; } diff --git a/src/dbwrapper.h b/src/dbwrapper.h index e19fde51c1..9f4d4814eb 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -5,13 +5,13 @@ #ifndef BITCOIN_DBWRAPPER_H #define BITCOIN_DBWRAPPER_H -#include "clientversion.h" -#include "fs.h" -#include "serialize.h" -#include "streams.h" -#include "util.h" -#include "utilstrencodings.h" -#include "version.h" +#include <clientversion.h> +#include <fs.h> +#include <serialize.h> +#include <streams.h> +#include <util.h> +#include <utilstrencodings.h> +#include <version.h> #include <leveldb/db.h> #include <leveldb/write_batch.h> diff --git a/src/fs.cpp b/src/fs.cpp index a5e12f1cfc..570ed3e2ee 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,4 +1,4 @@ -#include "fs.h" +#include <fs.h> namespace fsbridge { diff --git a/src/hash.cpp b/src/hash.cpp index 5a15600be5..1363d32cf4 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "hash.h" -#include "crypto/common.h" -#include "crypto/hmac_sha512.h" -#include "pubkey.h" +#include <hash.h> +#include <crypto/common.h> +#include <crypto/hmac_sha512.h> +#include <pubkey.h> inline uint32_t ROTL32(uint32_t x, int8_t r) diff --git a/src/hash.h b/src/hash.h index 474b13d65b..55724fb636 100644 --- a/src/hash.h +++ b/src/hash.h @@ -6,12 +6,12 @@ #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H -#include "crypto/ripemd160.h" -#include "crypto/sha256.h" -#include "prevector.h" -#include "serialize.h" -#include "uint256.h" -#include "version.h" +#include <crypto/ripemd160.h> +#include <crypto/sha256.h> +#include <prevector.h> +#include <serialize.h> +#include <uint256.h> +#include <version.h> #include <vector> diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 93f0a18668..6b6849e59b 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -2,19 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "httprpc.h" - -#include "base58.h" -#include "chainparams.h" -#include "httpserver.h" -#include "rpc/protocol.h" -#include "rpc/server.h" -#include "random.h" -#include "sync.h" -#include "util.h" -#include "utilstrencodings.h" -#include "ui_interface.h" -#include "crypto/hmac_sha256.h" +#include <httprpc.h> + +#include <base58.h> +#include <chainparams.h> +#include <httpserver.h> +#include <rpc/protocol.h> +#include <rpc/server.h> +#include <random.h> +#include <sync.h> +#include <util.h> +#include <utilstrencodings.h> +#include <ui_interface.h> +#include <crypto/hmac_sha256.h> #include <stdio.h> #include <boost/algorithm/string.hpp> // boost::trim @@ -62,7 +62,7 @@ private: /* Pre-base64-encoded authentication token */ static std::string strRPCUserColonPass; /* Stored RPC timer interface (for unregistration) */ -static HTTPRPCTimerInterface* httpRPCTimerInterface = nullptr; +static std::unique_ptr<HTTPRPCTimerInterface> httpRPCTimerInterface; static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const UniValue& id) { @@ -238,8 +238,8 @@ bool StartHTTPRPC() RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC); #endif assert(EventBase()); - httpRPCTimerInterface = new HTTPRPCTimerInterface(EventBase()); - RPCSetTimerInterface(httpRPCTimerInterface); + httpRPCTimerInterface = MakeUnique<HTTPRPCTimerInterface>(EventBase()); + RPCSetTimerInterface(httpRPCTimerInterface.get()); return true; } @@ -253,8 +253,7 @@ void StopHTTPRPC() LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n"); UnregisterHTTPHandler("/", true); if (httpRPCTimerInterface) { - RPCUnsetTimerInterface(httpRPCTimerInterface); - delete httpRPCTimerInterface; - httpRPCTimerInterface = nullptr; + RPCUnsetTimerInterface(httpRPCTimerInterface.get()); + httpRPCTimerInterface.reset(); } } diff --git a/src/httpserver.cpp b/src/httpserver.cpp index f6cbaa20b7..7d590f8e1f 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -2,16 +2,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "httpserver.h" +#include <httpserver.h> -#include "chainparamsbase.h" -#include "compat.h" -#include "util.h" -#include "utilstrencodings.h" -#include "netbase.h" -#include "rpc/protocol.h" // For HTTP status codes -#include "sync.h" -#include "ui_interface.h" +#include <chainparamsbase.h> +#include <compat.h> +#include <util.h> +#include <utilstrencodings.h> +#include <netbase.h> +#include <rpc/protocol.h> // For HTTP status codes +#include <sync.h> +#include <ui_interface.h> #include <stdio.h> #include <stdlib.h> @@ -28,7 +28,7 @@ #include <event2/util.h> #include <event2/keyvalq_struct.h> -#include "support/events.h" +#include <support/events.h> #ifdef EVENT__HAVE_NETINET_IN_H #include <netinet/in.h> diff --git a/src/init.cpp b/src/init.cpp index ddac606a39..e4cad01b70 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -4,49 +4,49 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "init.h" - -#include "addrman.h" -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "compat/sanity.h" -#include "consensus/validation.h" -#include "fs.h" -#include "httpserver.h" -#include "httprpc.h" -#include "key.h" -#include "validation.h" -#include "miner.h" -#include "netbase.h" -#include "net.h" -#include "net_processing.h" -#include "policy/feerate.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "rpc/server.h" -#include "rpc/register.h" -#include "rpc/safemode.h" -#include "rpc/blockchain.h" -#include "script/standard.h" -#include "script/sigcache.h" -#include "scheduler.h" -#include "timedata.h" -#include "txdb.h" -#include "txmempool.h" -#include "torcontrol.h" -#include "ui_interface.h" -#include "util.h" -#include "utilmoneystr.h" -#include "validationinterface.h" +#include <init.h> + +#include <addrman.h> +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#include <compat/sanity.h> +#include <consensus/validation.h> +#include <fs.h> +#include <httpserver.h> +#include <httprpc.h> +#include <key.h> +#include <validation.h> +#include <miner.h> +#include <netbase.h> +#include <net.h> +#include <net_processing.h> +#include <policy/feerate.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <rpc/server.h> +#include <rpc/register.h> +#include <rpc/safemode.h> +#include <rpc/blockchain.h> +#include <script/standard.h> +#include <script/sigcache.h> +#include <scheduler.h> +#include <timedata.h> +#include <txdb.h> +#include <txmempool.h> +#include <torcontrol.h> +#include <ui_interface.h> +#include <util.h> +#include <utilmoneystr.h> +#include <validationinterface.h> #ifdef ENABLE_WALLET -#include "wallet/init.h" +#include <wallet/init.h> #endif -#include "warnings.h" +#include <warnings.h> #include <stdint.h> #include <stdio.h> #include <memory> @@ -64,7 +64,7 @@ #include <openssl/crypto.h> #if ENABLE_ZMQ -#include "zmq/zmqnotificationinterface.h" +#include <zmq/zmqnotificationinterface.h> #endif bool fFeeEstimatesInitialized = false; @@ -152,7 +152,7 @@ public: // Writes do not need similar protection, as failure to write is handled by the caller. }; -static CCoinsViewErrorCatcher *pcoinscatcher = nullptr; +static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher; static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; void Interrupt(boost::thread_group& threadGroup) @@ -193,8 +193,8 @@ void Shutdown() // Because these depend on each-other, we make sure that neither can be // using the other before destroying them. - UnregisterValidationInterface(peerLogic.get()); - if(g_connman) g_connman->Stop(); + if (peerLogic) UnregisterValidationInterface(peerLogic.get()); + if (g_connman) g_connman->Stop(); peerLogic.reset(); g_connman.reset(); @@ -235,14 +235,10 @@ void Shutdown() if (pcoinsTip != nullptr) { FlushStateToDisk(); } - delete pcoinsTip; - pcoinsTip = nullptr; - delete pcoinscatcher; - pcoinscatcher = nullptr; - delete pcoinsdbview; - pcoinsdbview = nullptr; - delete pblocktree; - pblocktree = nullptr; + pcoinsTip.reset(); + pcoinscatcher.reset(); + pcoinsdbview.reset(); + pblocktree.reset(); } #ifdef ENABLE_WALLET StopWallets(); @@ -265,6 +261,7 @@ void Shutdown() #endif UnregisterAllValidationInterfaces(); GetMainSignals().UnregisterBackgroundSignalScheduler(); + GetMainSignals().UnregisterWithMempoolSignals(mempool); #ifdef ENABLE_WALLET CloseWallets(); #endif @@ -345,6 +342,7 @@ std::string HelpMessage(HelpMessageMode mode) if (showDebug) strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER)); strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup")); + strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE)); strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY)); @@ -818,7 +816,7 @@ namespace { // Variables internal to initialization process only int nMaxConnections; int nUserMaxConnections; int nFD; -ServiceFlags nLocalServices = NODE_NETWORK; +ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED); } // namespace @@ -922,7 +920,8 @@ bool AppInitParameterInteraction() // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector<std::string> categories = gArgs.GetArgs("-debug"); - if (find(categories.begin(), categories.end(), std::string("0")) == categories.end()) { + if (std::none_of(categories.begin(), categories.end(), + [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { uint32_t flag = 0; if (!GetLogCategory(&flag, &cat)) { @@ -1033,11 +1032,6 @@ bool AppInitParameterInteraction() fPruneMode = true; } - RegisterAllCoreRPCCommands(tableRPC); -#ifdef ENABLE_WALLET - RegisterWalletRPC(tableRPC); -#endif - nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); if (nConnectTimeout <= 0) nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; @@ -1216,8 +1210,11 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) ShrinkDebugFile(); } - if (fPrintToDebugLog) - OpenDebugLog(); + if (fPrintToDebugLog) { + if (!OpenDebugLog()) { + return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string())); + } + } if (!fLogTimestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); @@ -1240,6 +1237,15 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + GetMainSignals().RegisterWithMempoolSignals(mempool); + + /* Register RPC commands regardless of -server setting so they will be + * available in the GUI RPC console even if external calls are disabled. + */ + RegisterAllCoreRPCCommands(tableRPC); +#ifdef ENABLE_WALLET + RegisterWalletRPC(tableRPC); +#endif /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections @@ -1406,12 +1412,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) do { try { UnloadBlockIndex(); - delete pcoinsTip; - delete pcoinsdbview; - delete pcoinscatcher; - delete pblocktree; - - pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReset); + pcoinsTip.reset(); + pcoinsdbview.reset(); + pcoinscatcher.reset(); + pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); if (fReset) { pblocktree->WriteReindexing(true); @@ -1462,8 +1466,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // At this point we're either in reindex or we've loaded a useful // block tree into mapBlockIndex! - pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState); - pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); + pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState)); + pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get())); // If necessary, upgrade from older database format. // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate @@ -1473,13 +1477,13 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate - if (!ReplayBlocks(chainparams, pcoinsdbview)) { + if (!ReplayBlocks(chainparams, pcoinsdbview.get())) { strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate."); break; } // The on-disk coinsdb is now in a good state, create the cache - pcoinsTip = new CCoinsViewCache(pcoinscatcher); + pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get())); bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull(); if (!is_coinsview_empty) { @@ -1521,7 +1525,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), + if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview.get(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { strLoadError = _("Corrupted block database detected"); break; @@ -1722,5 +1726,5 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) StartWallets(scheduler); #endif - return !fRequestShutdown; + return true; } diff --git a/src/key.cpp b/src/key.cpp index 315a3978c8..9d4c4498d8 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -2,13 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "key.h" +#include <key.h> -#include "arith_uint256.h" -#include "crypto/common.h" -#include "crypto/hmac_sha512.h" -#include "pubkey.h" -#include "random.h" +#include <arith_uint256.h> +#include <crypto/common.h> +#include <crypto/hmac_sha512.h> +#include <random.h> #include <secp256k1.h> #include <secp256k1_recovery.h> @@ -6,10 +6,10 @@ #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H -#include "pubkey.h" -#include "serialize.h" -#include "support/allocators/secure.h" -#include "uint256.h" +#include <pubkey.h> +#include <serialize.h> +#include <support/allocators/secure.h> +#include <uint256.h> #include <stdexcept> #include <vector> diff --git a/src/keystore.cpp b/src/keystore.cpp index 8454175ca8..4ab089e032 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -3,11 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "keystore.h" +#include <keystore.h> -#include "key.h" -#include "pubkey.h" -#include "util.h" +#include <util.h> bool CKeyStore::AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); @@ -36,6 +34,33 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) return true; } +bool CBasicKeyStore::HaveKey(const CKeyID &address) const +{ + LOCK(cs_KeyStore); + return mapKeys.count(address) > 0; +} + +std::set<CKeyID> CBasicKeyStore::GetKeys() const +{ + LOCK(cs_KeyStore); + std::set<CKeyID> set_address; + for (const auto& mi : mapKeys) { + set_address.insert(mi.first); + } + return set_address; +} + +bool CBasicKeyStore::GetKey(const CKeyID &address, CKey &keyOut) const +{ + LOCK(cs_KeyStore); + KeyMap::const_iterator mi = mapKeys.find(address); + if (mi != mapKeys.end()) { + keyOut = mi->second; + return true; + } + return false; +} + bool CBasicKeyStore::AddCScript(const CScript& redeemScript) { if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) diff --git a/src/keystore.h b/src/keystore.h index 9b85ddb0ec..4e6d8e8a27 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -6,11 +6,11 @@ #ifndef BITCOIN_KEYSTORE_H #define BITCOIN_KEYSTORE_H -#include "key.h" -#include "pubkey.h" -#include "script/script.h" -#include "script/standard.h" -#include "sync.h" +#include <key.h> +#include <pubkey.h> +#include <script/script.h> +#include <script/standard.h> +#include <sync.h> #include <boost/signals2/signal.hpp> @@ -62,37 +62,9 @@ protected: public: bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override; - bool HaveKey(const CKeyID &address) const override - { - bool result; - { - LOCK(cs_KeyStore); - result = (mapKeys.count(address) > 0); - } - return result; - } - std::set<CKeyID> GetKeys() const override - { - LOCK(cs_KeyStore); - std::set<CKeyID> set_address; - for (const auto& mi : mapKeys) { - set_address.insert(mi.first); - } - return set_address; - } - bool GetKey(const CKeyID &address, CKey &keyOut) const override - { - { - LOCK(cs_KeyStore); - KeyMap::const_iterator mi = mapKeys.find(address); - if (mi != mapKeys.end()) - { - keyOut = mi->second; - return true; - } - } - return false; - } + bool HaveKey(const CKeyID &address) const override; + std::set<CKeyID> GetKeys() const override; + bool GetKey(const CKeyID &address, CKey &keyOut) const override; bool AddCScript(const CScript& redeemScript) override; bool HaveCScript(const CScriptID &hash) const override; bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override; diff --git a/src/memusage.h b/src/memusage.h index 93fd6a0eb5..d931171d35 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_MEMUSAGE_H #define BITCOIN_MEMUSAGE_H -#include "indirectmap.h" +#include <indirectmap.h> #include <stdlib.h> diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 3f07b4dac4..f4db9dd57e 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "merkleblock.h" +#include <merkleblock.h> -#include "hash.h" -#include "consensus/consensus.h" -#include "utilstrencodings.h" +#include <hash.h> +#include <consensus/consensus.h> +#include <utilstrencodings.h> CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids) diff --git a/src/merkleblock.h b/src/merkleblock.h index 6c05f2c1f8..b64c34370e 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -6,10 +6,10 @@ #ifndef BITCOIN_MERKLEBLOCK_H #define BITCOIN_MERKLEBLOCK_H -#include "serialize.h" -#include "uint256.h" -#include "primitives/block.h" -#include "bloom.h" +#include <serialize.h> +#include <uint256.h> +#include <primitives/block.h> +#include <bloom.h> #include <vector> diff --git a/src/miner.cpp b/src/miner.cpp index a9989f4b17..0fb9b774d3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -3,29 +3,28 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "miner.h" - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "coins.h" -#include "consensus/consensus.h" -#include "consensus/tx_verify.h" -#include "consensus/merkle.h" -#include "consensus/validation.h" -#include "hash.h" -#include "validation.h" -#include "net.h" -#include "policy/feerate.h" -#include "policy/policy.h" -#include "pow.h" -#include "primitives/transaction.h" -#include "script/standard.h" -#include "timedata.h" -#include "txmempool.h" -#include "util.h" -#include "utilmoneystr.h" -#include "validationinterface.h" +#include <miner.h> + +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <coins.h> +#include <consensus/consensus.h> +#include <consensus/tx_verify.h> +#include <consensus/merkle.h> +#include <consensus/validation.h> +#include <hash.h> +#include <validation.h> +#include <net.h> +#include <policy/feerate.h> +#include <policy/policy.h> +#include <pow.h> +#include <primitives/transaction.h> +#include <script/standard.h> +#include <timedata.h> +#include <util.h> +#include <utilmoneystr.h> +#include <validationinterface.h> #include <algorithm> #include <queue> diff --git a/src/miner.h b/src/miner.h index db165e71c6..d81ec6421c 100644 --- a/src/miner.h +++ b/src/miner.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_MINER_H #define BITCOIN_MINER_H -#include "primitives/block.h" -#include "txmempool.h" +#include <primitives/block.h> +#include <txmempool.h> #include <stdint.h> #include <memory> @@ -71,7 +71,7 @@ struct modifiedentry_iter { // except operating on CTxMemPoolModifiedEntry. // TODO: refactor to avoid duplication of this logic. struct CompareModifiedEntry { - bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) + bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) const { double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors; double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors; @@ -86,7 +86,7 @@ struct CompareModifiedEntry { // This is sufficient to sort an ancestor package in an order that is valid // to appear in a block. struct CompareTxIterByAncestorCount { - bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) + bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) const { if (a->GetCountWithAncestors() != b->GetCountWithAncestors()) return a->GetCountWithAncestors() < b->GetCountWithAncestors(); diff --git a/src/net.cpp b/src/net.cpp index d5bd4c162b..23bf640472 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -4,23 +4,21 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "net.h" - -#include "addrman.h" -#include "chainparams.h" -#include "clientversion.h" -#include "consensus/consensus.h" -#include "crypto/common.h" -#include "crypto/sha256.h" -#include "hash.h" -#include "primitives/transaction.h" -#include "netbase.h" -#include "scheduler.h" -#include "ui_interface.h" -#include "utilstrencodings.h" +#include <net.h> + +#include <chainparams.h> +#include <clientversion.h> +#include <consensus/consensus.h> +#include <crypto/common.h> +#include <crypto/sha256.h> +#include <primitives/transaction.h> +#include <netbase.h> +#include <scheduler.h> +#include <ui_interface.h> +#include <utilstrencodings.h> #ifdef WIN32 #include <string.h> @@ -110,13 +108,13 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer) int nBestReachability = -1; { LOCK(cs_mapLocalHost); - for (std::map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) + for (const auto& entry : mapLocalHost) { - int nScore = (*it).second.nScore; - int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); + int nScore = entry.second.nScore; + int nReachability = entry.first.GetReachabilityFrom(paddrPeer); if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) { - addr = CService((*it).first, (*it).second.nPort); + addr = CService(entry.first, entry.second.nPort); nBestReachability = nReachability; nBestScore = nScore; } @@ -417,39 +415,48 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (addrConnect.IsValid()) { bool proxyConnectionFailed = false; - if (GetProxy(addrConnect.GetNetwork(), proxy)) + if (GetProxy(addrConnect.GetNetwork(), proxy)) { + hSocket = CreateSocket(proxy.proxy); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed); - else // no proxy needed (none set for target network) + } else { + // no proxy needed (none set for target network) + hSocket = CreateSocket(addrConnect); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); + } if (!proxyConnectionFailed) { // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to // the proxy, mark this as an attempt. addrman.Attempt(addrConnect, fCountFailure); } } else if (pszDest && GetNameProxy(proxy)) { + hSocket = CreateSocket(proxy.proxy); + if (hSocket == INVALID_SOCKET) { + return nullptr; + } std::string host; int port = default_port; SplitHostPort(std::string(pszDest), port, host); connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, nullptr); } - if (connected) { - if (!IsSelectableSocket(hSocket)) { - LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); - CloseSocket(hSocket); - return nullptr; - } - - // Add node - NodeId id = GetNewNodeId(); - uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); - CAddress addr_bind = GetBindAddress(hSocket); - CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false); - pnode->AddRef(); - - return pnode; + if (!connected) { + CloseSocket(hSocket); + return nullptr; } - return nullptr; + // Add node + NodeId id = GetNewNodeId(); + uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); + CAddress addr_bind = GetBindAddress(hSocket); + CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false); + pnode->AddRef(); + + return pnode; } void CConnman::DumpBanlist() @@ -1102,7 +1109,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { if (IsBanned(addr) && !whitelisted) { - LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); + LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString()); CloseSocket(hSocket); return; } @@ -1534,22 +1541,20 @@ void ThreadMapPort() void MapPort(bool fUseUPnP) { - static boost::thread* upnp_thread = nullptr; + static std::unique_ptr<boost::thread> upnp_thread; if (fUseUPnP) { if (upnp_thread) { upnp_thread->interrupt(); upnp_thread->join(); - delete upnp_thread; } - upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort)); + upnp_thread.reset(new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort))); } else if (upnp_thread) { upnp_thread->interrupt(); upnp_thread->join(); - delete upnp_thread; - upnp_thread = nullptr; + upnp_thread.reset(); } } @@ -2060,44 +2065,21 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b return false; } - SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); + SOCKET hListenSocket = CreateSocket(addrBind); if (hListenSocket == INVALID_SOCKET) { strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } - if (!IsSelectableSocket(hListenSocket)) - { - strError = "Error: Couldn't create a listenable socket for incoming connections"; - LogPrintf("%s\n", strError); - return false; - } - - #ifndef WIN32 -#ifdef SO_NOSIGPIPE - // Different way of disabling SIGPIPE on BSD - setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); -#endif // Allow binding if the port is still in TIME_WAIT state after // the program was closed and restarted. setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); - // Disable Nagle's algorithm - setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&nOne, sizeof(int)); #else setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int)); - setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nOne, sizeof(int)); #endif - // Set to non-blocking, incoming connections will also inherit this - if (!SetSocketNonBlocking(hListenSocket, true)) { - CloseSocket(hListenSocket); - strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); - return false; - } - // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option // and enable it by default or not. Try to enable it, if possible. if (addrBind.IsIPv6()) { @@ -2224,8 +2206,6 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe nLastNodeId = 0; nSendBufferMaxSize = 0; nReceiveFloodSize = 0; - semOutbound = nullptr; - semAddnode = nullptr; flagInterruptMsgProc = false; SetTryNewOutboundPeer(false); @@ -2273,10 +2253,16 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { Init(connOptions); - nTotalBytesRecv = 0; - nTotalBytesSent = 0; - nMaxOutboundTotalBytesSentInCycle = 0; - nMaxOutboundCycleStartTime = 0; + { + LOCK(cs_totalBytesRecv); + nTotalBytesRecv = 0; + } + { + LOCK(cs_totalBytesSent); + nTotalBytesSent = 0; + nMaxOutboundTotalBytesSentInCycle = 0; + nMaxOutboundCycleStartTime = 0; + } if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { if (clientInterface) { @@ -2331,11 +2317,11 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) if (semOutbound == nullptr) { // initialize semaphore - semOutbound = new CSemaphore(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections)); + semOutbound = MakeUnique<CSemaphore>(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections)); } if (semAddnode == nullptr) { // initialize semaphore - semAddnode = new CSemaphore(nMaxAddnode); + semAddnode = MakeUnique<CSemaphore>(nMaxAddnode); } // @@ -2458,10 +2444,8 @@ void CConnman::Stop() vNodes.clear(); vNodesDisconnected.clear(); vhListenSocket.clear(); - delete semOutbound; - semOutbound = nullptr; - delete semAddnode; - semAddnode = nullptr; + semOutbound.reset(); + semAddnode.reset(); } void CConnman::DeleteNode(CNode* pnode) @@ -2747,7 +2731,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn nNextInvSend = 0; fRelayTxes = false; fSentAddr = false; - pfilter = new CBloomFilter(); + pfilter = MakeUnique<CBloomFilter>(); timeLastMempoolReq = 0; nLastBlockTime = 0; nLastTXTime = 0; @@ -2777,8 +2761,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn CNode::~CNode() { CloseSocket(hSocket); - - delete pfilter; } void CNode::AskFor(const CInv& inv) @@ -6,21 +6,21 @@ #ifndef BITCOIN_NET_H #define BITCOIN_NET_H -#include "addrdb.h" -#include "addrman.h" -#include "amount.h" -#include "bloom.h" -#include "compat.h" -#include "hash.h" -#include "limitedmap.h" -#include "netaddress.h" -#include "policy/feerate.h" -#include "protocol.h" -#include "random.h" -#include "streams.h" -#include "sync.h" -#include "uint256.h" -#include "threadinterrupt.h" +#include <addrdb.h> +#include <addrman.h> +#include <amount.h> +#include <bloom.h> +#include <compat.h> +#include <hash.h> +#include <limitedmap.h> +#include <netaddress.h> +#include <policy/feerate.h> +#include <protocol.h> +#include <random.h> +#include <streams.h> +#include <sync.h> +#include <uint256.h> +#include <threadinterrupt.h> #include <atomic> #include <deque> @@ -158,10 +158,16 @@ public: m_msgproc = connOptions.m_msgproc; nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nReceiveFloodSize; - nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; - nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + { + LOCK(cs_totalBytesSent); + nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; + nMaxOutboundLimit = connOptions.nMaxOutboundLimit; + } vWhitelistedRange = connOptions.vWhitelistedRange; - vAddedNodes = connOptions.m_added_nodes; + { + LOCK(cs_vAddedNodes); + vAddedNodes = connOptions.m_added_nodes; + } } CConnman(uint64_t seed0, uint64_t seed1); @@ -364,14 +370,14 @@ private: // Network usage totals CCriticalSection cs_totalBytesRecv; CCriticalSection cs_totalBytesSent; - uint64_t nTotalBytesRecv; - uint64_t nTotalBytesSent; + uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv); + uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent); // outbound limit & stats - uint64_t nMaxOutboundTotalBytesSentInCycle; - uint64_t nMaxOutboundCycleStartTime; - uint64_t nMaxOutboundLimit; - uint64_t nMaxOutboundTimeframe; + uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent); + uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent); // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). @@ -389,7 +395,7 @@ private: CAddrMan addrman; std::deque<std::string> vOneShots; CCriticalSection cs_vOneShots; - std::vector<std::string> vAddedNodes; + std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes); CCriticalSection cs_vAddedNodes; std::vector<CNode*> vNodes; std::list<CNode*> vNodesDisconnected; @@ -399,8 +405,8 @@ private: /** Services this instance offers */ ServiceFlags nLocalServices; - CSemaphore *semOutbound; - CSemaphore *semAddnode; + std::unique_ptr<CSemaphore> semOutbound; + std::unique_ptr<CSemaphore> semAddnode; int nMaxConnections; int nMaxOutbound; int nMaxAddnode; @@ -648,7 +654,7 @@ public: bool fSentAddr; CSemaphoreGrant grantOutbound; CCriticalSection cs_filter; - CBloomFilter* pfilter; + std::unique_ptr<CBloomFilter> pfilter; std::atomic<int> nRefCount; const uint64_t nKeyedNetGroup; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 82b09f5f14..20426eaceb 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3,34 +3,32 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "net_processing.h" - -#include "addrman.h" -#include "arith_uint256.h" -#include "blockencodings.h" -#include "chainparams.h" -#include "consensus/validation.h" -#include "hash.h" -#include "init.h" -#include "validation.h" -#include "merkleblock.h" -#include "net.h" -#include "netmessagemaker.h" -#include "netbase.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "random.h" -#include "reverse_iterator.h" -#include "scheduler.h" -#include "tinyformat.h" -#include "txmempool.h" -#include "ui_interface.h" -#include "util.h" -#include "utilmoneystr.h" -#include "utilstrencodings.h" -#include "validationinterface.h" +#include <net_processing.h> + +#include <addrman.h> +#include <arith_uint256.h> +#include <blockencodings.h> +#include <chainparams.h> +#include <consensus/validation.h> +#include <hash.h> +#include <init.h> +#include <validation.h> +#include <merkleblock.h> +#include <netmessagemaker.h> +#include <netbase.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <primitives/block.h> +#include <primitives/transaction.h> +#include <random.h> +#include <reverse_iterator.h> +#include <scheduler.h> +#include <tinyformat.h> +#include <txmempool.h> +#include <ui_interface.h> +#include <util.h> +#include <utilmoneystr.h> +#include <utilstrencodings.h> #if defined(NDEBUG) # error "Bitcoin cannot be compiled without assertions." @@ -1078,7 +1076,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } send = BlockRequestAllowed(mi->second, consensusParams); if (!send) { - LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); + LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); } } // disconnect node in case we have reached the outbound limit for serving historical blocks @@ -1091,6 +1089,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pfrom->fDisconnect = true; send = false; } + // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold + if (send && !pfrom->fWhitelisted && ( + (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (chainActive.Tip()->nHeight - mi->second->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) ) + )) { + LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom->GetId()); + + //disconnect node and prevent it from stalling (would otherwise wait for the missing block) + pfrom->fDisconnect = true; + send = false; + } // Pruned nodes may have deleted the block, so check whether // it's available before trying to send. if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) @@ -1559,7 +1567,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version - LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); + LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION))); pfrom->fDisconnect = true; @@ -1659,7 +1667,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (fLogIPs) remoteAddr = ", peeraddr=" + pfrom->addr.ToString(); - LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n", + LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n", cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(), remoteAddr); @@ -1702,6 +1710,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Mark this node as currently connected, so we update its timestamp later. LOCK(cs_main); State(pfrom->GetId())->fCurrentlyConnected = true; + LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s\n", + pfrom->nVersion.load(), pfrom->nStartingHeight, pfrom->GetId(), + (fLogIPs ? strprintf(", peeraddr=%s", pfrom->addr.ToString()) : "")); } if (pfrom->nVersion >= SENDHEADERS_VERSION) { @@ -1980,7 +1991,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr BlockMap::iterator it = mapBlockIndex.find(req.blockhash); if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { - LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); return true; } @@ -2032,7 +2043,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pindex = (*mi).second; if (!BlockRequestAllowed(pindex, chainparams.GetConsensus())) { - LogPrintf("%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId()); + LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId()); return true; } } @@ -2102,7 +2113,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, ptx, &fMissingInputs, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) { - mempool.check(pcoinsTip); + mempool.check(pcoinsTip.get()); RelayTransaction(tx, connman); for (unsigned int i = 0; i < tx.vout.size(); i++) { vWorkQueue.emplace_back(inv.hash, i); @@ -2169,7 +2180,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr recentRejects->insert(orphanHash); } } - mempool.check(pcoinsTip); + mempool.check(pcoinsTip.get()); } } @@ -2286,10 +2297,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr int nDoS; if (state.IsInvalid(nDoS)) { if (nDoS > 0) { + LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); + } else { + LogPrint(BCLog::NET, "Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); } - LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); return true; } } @@ -2751,8 +2764,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr else { LOCK(pfrom->cs_filter); - delete pfrom->pfilter; - pfrom->pfilter = new CBloomFilter(filter); + pfrom->pfilter.reset(new CBloomFilter(filter)); pfrom->pfilter->UpdateEmptyFull(); pfrom->fRelayTxes = true; } @@ -2788,8 +2800,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr { LOCK(pfrom->cs_filter); if (pfrom->GetLocalServices() & NODE_BLOOM) { - delete pfrom->pfilter; - pfrom->pfilter = new CBloomFilter(); + pfrom->pfilter.reset(new CBloomFilter()); } pfrom->fRelayTxes = true; } @@ -2893,7 +2904,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter msg.SetVersion(pfrom->GetRecvVersion()); // Scan for message start if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { - LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); + LogPrint(BCLog::NET, "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); pfrom->fDisconnect = true; return false; } @@ -2902,7 +2913,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter CMessageHeader& hdr = msg.hdr; if (!hdr.IsValid(chainparams.MessageStart())) { - LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); + LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); return fMoreWork; } std::string strCommand = hdr.GetCommand(); @@ -2915,7 +2926,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter const uint256& hash = msg.GetMessageHash(); if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) { - LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, + LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, SanitizeString(strCommand), nMessageSize, HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); @@ -2938,17 +2949,17 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter if (strstr(e.what(), "end of data")) { // Allow exceptions from under-length message on vRecv - LogPrintf("%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else if (strstr(e.what(), "size too large")) { // Allow exceptions from over-long size - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else if (strstr(e.what(), "non-canonical ReadCompactSize()")) { // Allow exceptions from non-canonical encoding - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } else { @@ -2962,7 +2973,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter } if (!fRet) { - LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId()); + LogPrint(BCLog::NET, "%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId()); } LOCK(cs_main); @@ -3008,6 +3019,7 @@ void PeerLogicValidation::ConsiderEviction(CNode *pto, int64_t time_in_seconds) LogPrintf("Disconnecting outbound peer %d for old chain, best known block = %s\n", pto->GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>"); pto->fDisconnect = true; } else { + assert(state.m_chain_sync.m_work_header); LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto->GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString()); connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(state.m_chain_sync.m_work_header->pprev), uint256())); state.m_chain_sync.m_sent_getheaders = true; diff --git a/src/net_processing.h b/src/net_processing.h index 0a49972eed..3fc1e05835 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_NET_PROCESSING_H #define BITCOIN_NET_PROCESSING_H -#include "net.h" -#include "validationinterface.h" -#include "consensus/params.h" +#include <net.h> +#include <validationinterface.h> +#include <consensus/params.h> /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; diff --git a/src/netaddress.cpp b/src/netaddress.cpp index b8a261c921..fa1c191559 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -3,14 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifdef HAVE_CONFIG_H -#include "config/bitcoin-config.h" -#endif - -#include "netaddress.h" -#include "hash.h" -#include "utilstrencodings.h" -#include "tinyformat.h" +#include <netaddress.h> +#include <hash.h> +#include <utilstrencodings.h> +#include <tinyformat.h> static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; diff --git a/src/netaddress.h b/src/netaddress.h index 6ca99b36b5..3b542b4748 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -6,11 +6,11 @@ #define BITCOIN_NETADDRESS_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "compat.h" -#include "serialize.h" +#include <compat.h> +#include <serialize.h> #include <stdint.h> #include <string> diff --git a/src/netbase.cpp b/src/netbase.cpp index 82040605c5..f4232fc42a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -3,18 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifdef HAVE_CONFIG_H -#include "config/bitcoin-config.h" -#endif - -#include "netbase.h" +#include <netbase.h> -#include "hash.h" -#include "sync.h" -#include "uint256.h" -#include "random.h" -#include "util.h" -#include "utilstrencodings.h" +#include <hash.h> +#include <sync.h> +#include <uint256.h> +#include <random.h> +#include <util.h> +#include <utilstrencodings.h> #include <atomic> @@ -317,12 +313,11 @@ std::string Socks5ErrorString(uint8_t err) } /** Connect using SOCKS5 (as described in RFC1928) */ -static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) +static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket) { IntrRecvError recvr; LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest); if (strDest.size() > 255) { - CloseSocket(hSocket); return error("Hostname too long"); } // Accepted authentication methods @@ -338,17 +333,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vSocks5Init.size()) { - CloseSocket(hSocket); return error("Error sending to proxy"); } uint8_t pchRet1[2]; if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); return false; } if (pchRet1[0] != SOCKSVersion::SOCKS5) { - CloseSocket(hSocket); return error("Proxy failed to initialize"); } if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { @@ -363,23 +355,19 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end()); ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vAuth.size()) { - CloseSocket(hSocket); return error("Error sending authentication to proxy"); } LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); uint8_t pchRetA[2]; if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading proxy authentication response"); } if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { - CloseSocket(hSocket); return error("Proxy authentication unsuccessful"); } } else if (pchRet1[1] == SOCKS5Method::NOAUTH) { // Perform no authentication } else { - CloseSocket(hSocket); return error("Proxy requested wrong authentication method %02x", pchRet1[1]); } std::vector<uint8_t> vSocks5; @@ -393,12 +381,10 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials vSocks5.push_back((port >> 0) & 0xFF); ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vSocks5.size()) { - CloseSocket(hSocket); return error("Error sending to proxy"); } uint8_t pchRet2[4]; if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); if (recvr == IntrRecvError::Timeout) { /* If a timeout happens here, this effectively means we timed out while connecting * to the remote node. This is very common for Tor, so do not print an @@ -409,17 +395,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } } if (pchRet2[0] != SOCKSVersion::SOCKS5) { - CloseSocket(hSocket); return error("Proxy failed to accept request"); } if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { // Failures to connect to a peer that are not proxy errors - CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1])); return false; } if (pchRet2[2] != 0x00) { // Reserved field must be 0 - CloseSocket(hSocket); return error("Error: malformed proxy response"); } uint8_t pchRet3[256]; @@ -431,41 +414,42 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials { recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); if (recvr != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } int nRecv = pchRet3[0]; recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); break; } - default: CloseSocket(hSocket); return error("Error: malformed proxy response"); + default: return error("Error: malformed proxy response"); } if (recvr != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { - CloseSocket(hSocket); return error("Error reading from proxy"); } LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); return true; } -bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) +SOCKET CreateSocket(const CService &addrConnect) { - hSocketRet = INVALID_SOCKET; - struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { - LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); - return false; + LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString()); + return INVALID_SOCKET; } SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); if (hSocket == INVALID_SOCKET) - return false; + return INVALID_SOCKET; + + if (!IsSelectableSocket(hSocket)) { + CloseSocket(hSocket); + LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); + return INVALID_SOCKET; + } #ifdef SO_NOSIGPIPE int set = 1; @@ -479,9 +463,23 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int // Set to non-blocking if (!SetSocketNonBlocking(hSocket, true)) { CloseSocket(hSocket); - return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); + LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); } + return hSocket; +} +bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout) +{ + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + if (hSocket == INVALID_SOCKET) { + LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString()); + return false; + } + if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { + LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); + return false; + } if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { int nErr = WSAGetLastError(); @@ -496,13 +494,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int if (nRet == 0) { LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString()); - CloseSocket(hSocket); return false; } if (nRet == SOCKET_ERROR) { LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } socklen_t nRetSize = sizeof(nRet); @@ -513,13 +509,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int #endif { LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } if (nRet != 0) { LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet)); - CloseSocket(hSocket); return false; } } @@ -530,12 +524,9 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int #endif { LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); - CloseSocket(hSocket); return false; } } - - hSocketRet = hSocket; return true; } @@ -587,9 +578,8 @@ bool IsProxy(const CNetAddr &addr) { return false; } -bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) +bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed) { - SOCKET hSocket = INVALID_SOCKET; // first connect to proxy server if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { if (outProxyConnectionFailed) @@ -601,14 +591,14 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int ProxyCredentials random_auth; static std::atomic_int counter(0); random_auth.username = random_auth.password = strprintf("%i", counter++); - if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) + if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) { return false; + } } else { - if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) + if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) { return false; + } } - - hSocketRet = hSocket; return true; } bool LookupSubNet(const char* pszName, CSubNet& ret) diff --git a/src/netbase.h b/src/netbase.h index e7d7bcb375..c89bd5b88f 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -6,12 +6,12 @@ #define BITCOIN_NETBASE_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "compat.h" -#include "netaddress.h" -#include "serialize.h" +#include <compat.h> +#include <netaddress.h> +#include <serialize.h> #include <stdint.h> #include <string> @@ -51,8 +51,9 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); CService LookupNumeric(const char *pszName, int portDefault = 0); bool LookupSubNet(const char *pszName, CSubNet& subnet); -bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout); -bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed); +SOCKET CreateSocket(const CService &addrConnect); +bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocketRet, int nTimeout); +bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed); /** Return readable error string for a network error code */ std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ diff --git a/src/netmessagemaker.h b/src/netmessagemaker.h index 79b2501c5d..ea7fccacb2 100644 --- a/src/netmessagemaker.h +++ b/src/netmessagemaker.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_NETMESSAGEMAKER_H #define BITCOIN_NETMESSAGEMAKER_H -#include "net.h" -#include "serialize.h" +#include <net.h> +#include <serialize.h> class CNetMsgMaker { diff --git a/src/noui.cpp b/src/noui.cpp index 4bfb75fa29..feb3464a56 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "noui.h" +#include <noui.h> -#include "ui_interface.h" -#include "util.h" +#include <ui_interface.h> +#include <util.h> #include <cstdio> #include <stdint.h> diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp index a089c02284..26c44ee0cf 100644 --- a/src/policy/feerate.cpp +++ b/src/policy/feerate.cpp @@ -3,9 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "feerate.h" +#include <policy/feerate.h> -#include "tinyformat.h" +#include <tinyformat.h> const std::string CURRENCY_UNIT = "BTC"; diff --git a/src/policy/feerate.h b/src/policy/feerate.h index 3449cdd699..35b1b23786 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_POLICY_FEERATE_H #define BITCOIN_POLICY_FEERATE_H -#include "amount.h" -#include "serialize.h" +#include <amount.h> +#include <serialize.h> #include <string> diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index c7e57671c0..dc88c4f91a 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -3,16 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "policy/fees.h" -#include "policy/policy.h" +#include <policy/fees.h> +#include <policy/policy.h> -#include "amount.h" -#include "clientversion.h" -#include "primitives/transaction.h" -#include "random.h" -#include "streams.h" -#include "txmempool.h" -#include "util.h" +#include <clientversion.h> +#include <primitives/transaction.h> +#include <streams.h> +#include <txmempool.h> +#include <util.h> static constexpr double INF_FEERATE = 1e99; @@ -548,16 +546,13 @@ CBlockPolicyEstimator::CBlockPolicyEstimator() bucketMap[INF_FEERATE] = bucketIndex; assert(bucketMap.size() == buckets.size()); - feeStats = new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE); - shortStats = new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE); - longStats = new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE); + feeStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE)); + shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE)); + longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE)); } CBlockPolicyEstimator::~CBlockPolicyEstimator() { - delete feeStats; - delete shortStats; - delete longStats; } void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate) @@ -690,16 +685,16 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr double sufficientTxs = SUFFICIENT_FEETXS; switch (horizon) { case FeeEstimateHorizon::SHORT_HALFLIFE: { - stats = shortStats; + stats = shortStats.get(); sufficientTxs = SUFFICIENT_TXS_SHORT; break; } case FeeEstimateHorizon::MED_HALFLIFE: { - stats = feeStats; + stats = feeStats.get(); break; } case FeeEstimateHorizon::LONG_HALFLIFE: { - stats = longStats; + stats = longStats.get(); break; } default: { @@ -1002,12 +997,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein) } // Destroy old TxConfirmStats and point to new ones that already reference buckets and bucketMap - delete feeStats; - delete shortStats; - delete longStats; - feeStats = fileFeeStats.release(); - shortStats = fileShortStats.release(); - longStats = fileLongStats.release(); + feeStats = std::move(fileFeeStats); + shortStats = std::move(fileShortStats); + longStats = std::move(fileLongStats); nBestSeenHeight = nFileBestSeenHeight; historicalFirst = nFileHistoricalFirst; diff --git a/src/policy/fees.h b/src/policy/fees.h index 6edaf28714..6528560f52 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -5,11 +5,11 @@ #ifndef BITCOIN_POLICYESTIMATOR_H #define BITCOIN_POLICYESTIMATOR_H -#include "amount.h" -#include "feerate.h" -#include "uint256.h" -#include "random.h" -#include "sync.h" +#include <amount.h> +#include <policy/feerate.h> +#include <uint256.h> +#include <random.h> +#include <sync.h> #include <map> #include <string> @@ -245,9 +245,9 @@ private: std::map<uint256, TxStatsInfo> mapMemPoolTxs; /** Classes to track historical data on transaction confirmations */ - TxConfirmStats* feeStats; - TxConfirmStats* shortStats; - TxConfirmStats* longStats; + std::unique_ptr<TxConfirmStats> feeStats; + std::unique_ptr<TxConfirmStats> shortStats; + std::unique_ptr<TxConfirmStats> longStats; unsigned int trackedTxs; unsigned int untrackedTxs; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index b2fb284508..b69bed5d6f 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -5,14 +5,14 @@ // NOTE: This file is intended to be customised by the end user, and includes only local node policy logic -#include "policy/policy.h" - -#include "consensus/validation.h" -#include "validation.h" -#include "coins.h" -#include "tinyformat.h" -#include "util.h" -#include "utilstrencodings.h" +#include <policy/policy.h> + +#include <consensus/validation.h> +#include <validation.h> +#include <coins.h> +#include <tinyformat.h> +#include <util.h> +#include <utilstrencodings.h> CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) diff --git a/src/policy/policy.h b/src/policy/policy.h index ef71dd73bc..f3f8ebbbb4 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -6,10 +6,10 @@ #ifndef BITCOIN_POLICY_POLICY_H #define BITCOIN_POLICY_POLICY_H -#include "consensus/consensus.h" -#include "feerate.h" -#include "script/interpreter.h" -#include "script/standard.h" +#include <consensus/consensus.h> +#include <policy/feerate.h> +#include <script/interpreter.h> +#include <script/standard.h> #include <string> diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index 755ef83c9a..e9692d4b48 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "policy/rbf.h" +#include <policy/rbf.h> bool SignalsOptInRBF(const CTransaction &tx) { diff --git a/src/policy/rbf.h b/src/policy/rbf.h index 22c73f3319..1a5218e120 100644 --- a/src/policy/rbf.h +++ b/src/policy/rbf.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_POLICY_RBF_H #define BITCOIN_POLICY_RBF_H -#include "txmempool.h" +#include <txmempool.h> static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd; diff --git a/src/pow.cpp b/src/pow.cpp index 7d87c6bbb7..cecb54ca7b 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "pow.h" +#include <pow.h> -#include "arith_uint256.h" -#include "chain.h" -#include "primitives/block.h" -#include "uint256.h" +#include <arith_uint256.h> +#include <chain.h> +#include <primitives/block.h> +#include <uint256.h> unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { @@ -6,7 +6,7 @@ #ifndef BITCOIN_POW_H #define BITCOIN_POW_H -#include "consensus/params.h" +#include <consensus/params.h> #include <stdint.h> diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 3774ac3e4b..9e20565511 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "primitives/block.h" +#include <primitives/block.h> -#include "hash.h" -#include "tinyformat.h" -#include "utilstrencodings.h" -#include "crypto/common.h" +#include <hash.h> +#include <tinyformat.h> +#include <utilstrencodings.h> +#include <crypto/common.h> uint256 CBlockHeader::GetHash() const { diff --git a/src/primitives/block.h b/src/primitives/block.h index 292df40896..4957958c6a 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_PRIMITIVES_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H -#include "primitives/transaction.h" -#include "serialize.h" -#include "uint256.h" +#include <primitives/transaction.h> +#include <serialize.h> +#include <uint256.h> /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index e0a106adb9..d8230d1423 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "primitives/transaction.h" +#include <primitives/transaction.h> -#include "hash.h" -#include "tinyformat.h" -#include "utilstrencodings.h" +#include <hash.h> +#include <tinyformat.h> +#include <utilstrencodings.h> std::string COutPoint::ToString() const { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 18d524e23d..32f45e5748 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,10 +7,10 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include <stdint.h> -#include "amount.h" -#include "script/script.h" -#include "serialize.h" -#include "uint256.h" +#include <amount.h> +#include <script/script.h> +#include <serialize.h> +#include <uint256.h> static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; diff --git a/src/protocol.cpp b/src/protocol.cpp index da87e40091..8c34c4196e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "protocol.h" +#include <protocol.h> -#include "util.h" -#include "utilstrencodings.h" +#include <util.h> +#include <utilstrencodings.h> #ifndef WIN32 # include <arpa/inet.h> diff --git a/src/protocol.h b/src/protocol.h index 56b59aed3f..cf1d40db77 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -10,10 +10,10 @@ #ifndef BITCOIN_PROTOCOL_H #define BITCOIN_PROTOCOL_H -#include "netaddress.h" -#include "serialize.h" -#include "uint256.h" -#include "version.h" +#include <netaddress.h> +#include <serialize.h> +#include <uint256.h> +#include <version.h> #include <stdint.h> #include <string> @@ -27,16 +27,13 @@ class CMessageHeader { public: - enum { - MESSAGE_START_SIZE = 4, - COMMAND_SIZE = 12, - MESSAGE_SIZE_SIZE = 4, - CHECKSUM_SIZE = 4, - - MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE, - CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE, - HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE - }; + static constexpr size_t MESSAGE_START_SIZE = 4; + static constexpr size_t COMMAND_SIZE = 12; + static constexpr size_t MESSAGE_SIZE_SIZE = 4; + static constexpr size_t CHECKSUM_SIZE = 4; + static constexpr size_t MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE; + static constexpr size_t CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE; + static constexpr size_t HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; explicit CMessageHeader(const MessageStartChars& pchMessageStartIn); @@ -249,9 +246,8 @@ const std::vector<std::string> &getAllNetMessageTypes(); enum ServiceFlags : uint64_t { // Nothing NODE_NONE = 0, - // NODE_NETWORK means that the node is capable of serving the block chain. It is currently - // set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want - // network services but don't provide them. + // NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently + // set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light clients. NODE_NETWORK = (1 << 0), // NODE_GETUTXO means the node is capable of responding to the getutxo protocol request. // Bitcoin Core does not support this but a patch set called Bitcoin XT does. @@ -267,6 +263,10 @@ enum ServiceFlags : uint64_t { // NODE_XTHIN means the node supports Xtreme Thinblocks // If this is turned off then the node will not service nor make xthin requests NODE_XTHIN = (1 << 4), + // NODE_NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only + // serving the last 288 (2 day) blocks + // See BIP159 for details on how this is implemented. + NODE_NETWORK_LIMITED = (1 << 10), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 2dd0a87fc9..7f5ec1e8de 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "pubkey.h" +#include <pubkey.h> #include <secp256k1.h> #include <secp256k1_recovery.h> diff --git a/src/pubkey.h b/src/pubkey.h index 65738d8fe2..c9f3c18eb3 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_PUBKEY_H #define BITCOIN_PUBKEY_H -#include "hash.h" -#include "serialize.h" -#include "uint256.h" +#include <hash.h> +#include <serialize.h> +#include <uint256.h> #include <stdexcept> #include <vector> diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index f295bd4689..dda8dce391 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -3,18 +3,18 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "addressbookpage.h" -#include "ui_addressbookpage.h" +#include <qt/addressbookpage.h> +#include <qt/forms/ui_addressbookpage.h> -#include "addresstablemodel.h" -#include "bitcoingui.h" -#include "csvmodelwriter.h" -#include "editaddressdialog.h" -#include "guiutil.h" -#include "platformstyle.h" +#include <qt/addresstablemodel.h> +#include <qt/bitcoingui.h> +#include <qt/csvmodelwriter.h> +#include <qt/editaddressdialog.h> +#include <qt/guiutil.h> +#include <qt/platformstyle.h> #include <QIcon> #include <QMenu> diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 0eb7ec4306..1d16940acb 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "addresstablemodel.h" +#include <qt/addresstablemodel.h> -#include "guiutil.h" -#include "walletmodel.h" +#include <qt/guiutil.h> +#include <qt/walletmodel.h> -#include "base58.h" -#include "wallet/wallet.h" +#include <base58.h> +#include <wallet/wallet.h> #include <QFont> diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index d6cce09e8d..a720ac956b 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -3,16 +3,16 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "askpassphrasedialog.h" -#include "ui_askpassphrasedialog.h" +#include <qt/askpassphrasedialog.h> +#include <qt/forms/ui_askpassphrasedialog.h> -#include "guiconstants.h" -#include "walletmodel.h" +#include <qt/guiconstants.h> +#include <qt/walletmodel.h> -#include "support/allocators/secure.h" +#include <support/allocators/secure.h> #include <QKeyEvent> #include <QMessageBox> diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index f8a99506c1..c96bdfd5d7 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bantablemodel.h" +#include <qt/bantablemodel.h> -#include "clientmodel.h" -#include "guiconstants.h" -#include "guiutil.h" +#include <qt/clientmodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> -#include "sync.h" -#include "utiltime.h" +#include <sync.h> +#include <utiltime.h> #include <QDebug> #include <QList> @@ -55,11 +55,11 @@ public: #if QT_VERSION >= 0x040700 cachedBanlist.reserve(banMap.size()); #endif - for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) + for (const auto& entry : banMap) { CCombinedBan banEntry; - banEntry.subnet = (*it).first; - banEntry.banEntry = (*it).second; + banEntry.subnet = entry.first; + banEntry.banEntry = entry.second; cachedBanlist.append(banEntry); } diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index 062cfdc931..dc69dee20a 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_BANTABLEMODEL_H #define BITCOIN_QT_BANTABLEMODEL_H -#include "net.h" +#include <net.h> #include <QAbstractTableModel> #include <QStringList> diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 3fd58a2f9a..557d7efcec 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -3,38 +3,38 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "bitcoingui.h" - -#include "chainparams.h" -#include "clientmodel.h" -#include "fs.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "intro.h" -#include "networkstyle.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "splashscreen.h" -#include "utilitydialog.h" -#include "winshutdownmonitor.h" +#include <qt/bitcoingui.h> + +#include <chainparams.h> +#include <qt/clientmodel.h> +#include <fs.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/intro.h> +#include <qt/networkstyle.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/splashscreen.h> +#include <qt/utilitydialog.h> +#include <qt/winshutdownmonitor.h> #ifdef ENABLE_WALLET -#include "paymentserver.h" -#include "walletmodel.h" +#include <qt/paymentserver.h> +#include <qt/walletmodel.h> #endif -#include "init.h" -#include "rpc/server.h" -#include "scheduler.h" -#include "ui_interface.h" -#include "util.h" -#include "warnings.h" +#include <init.h> +#include <rpc/server.h> +#include <scheduler.h> +#include <ui_interface.h> +#include <util.h> +#include <warnings.h> #ifdef ENABLE_WALLET -#include "wallet/wallet.h" +#include <wallet/wallet.h> #endif #include <stdint.h> @@ -261,7 +261,7 @@ private: void startThread(); }; -#include "bitcoin.moc" +#include <qt/bitcoin.moc> BitcoinCore::BitcoinCore(): QObject() diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp index 362a71f04d..e8d174bf29 100644 --- a/src/qt/bitcoinaddressvalidator.cpp +++ b/src/qt/bitcoinaddressvalidator.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bitcoinaddressvalidator.h" +#include <qt/bitcoinaddressvalidator.h> -#include "base58.h" +#include <base58.h> /* Base58 characters are: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 73eb35a54e..0b21349c54 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bitcoinamountfield.h" +#include <qt/bitcoinamountfield.h> -#include "bitcoinunits.h" -#include "guiconstants.h" -#include "qvaluecombobox.h" +#include <qt/bitcoinunits.h> +#include <qt/guiconstants.h> +#include <qt/qvaluecombobox.h> #include <QApplication> #include <QAbstractSpinBox> @@ -188,7 +188,7 @@ Q_SIGNALS: void valueChanged(); }; -#include "bitcoinamountfield.moc" +#include <qt/bitcoinamountfield.moc> BitcoinAmountField::BitcoinAmountField(QWidget *parent) : QWidget(parent), diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 2f03a3d171..659ecb416b 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_BITCOINAMOUNTFIELD_H #define BITCOIN_QT_BITCOINAMOUNTFIELD_H -#include "amount.h" +#include <amount.h> #include <QWidget> diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index dc55141900..f925ec5359 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -2,39 +2,35 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" -#endif - -#include "bitcoingui.h" - -#include "bitcoinunits.h" -#include "clientmodel.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "modaloverlay.h" -#include "networkstyle.h" -#include "notificator.h" -#include "openuridialog.h" -#include "optionsdialog.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "rpcconsole.h" -#include "utilitydialog.h" +#include <qt/bitcoingui.h> + +#include <qt/bitcoinunits.h> +#include <qt/clientmodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/modaloverlay.h> +#include <qt/networkstyle.h> +#include <qt/notificator.h> +#include <qt/openuridialog.h> +#include <qt/optionsdialog.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/rpcconsole.h> +#include <qt/utilitydialog.h> #ifdef ENABLE_WALLET -#include "walletframe.h" -#include "walletmodel.h" +#include <qt/walletframe.h> +#include <qt/walletmodel.h> #endif // ENABLE_WALLET #ifdef Q_OS_MAC -#include "macdockiconhandler.h" +#include <qt/macdockiconhandler.h> #endif -#include "chainparams.h" -#include "init.h" -#include "ui_interface.h" -#include "util.h" +#include <chainparams.h> +#include <init.h> +#include <ui_interface.h> +#include <util.h> #include <iostream> diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index aa45ea1f0a..1647975fec 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -6,10 +6,10 @@ #define BITCOIN_QT_BITCOINGUI_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "amount.h" +#include <amount.h> #include <QLabel> #include <QMainWindow> diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 4da414a4e3..c8614fdfe0 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bitcoinunits.h" +#include <qt/bitcoinunits.h> -#include "primitives/transaction.h" +#include <primitives/transaction.h> #include <QStringList> diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index 6ef37de380..3f5a7fd32d 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_BITCOINUNITS_H #define BITCOIN_QT_BITCOINUNITS_H -#include "amount.h" +#include <amount.h> #include <QAbstractListModel> #include <QString> diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 52ce11cefd..78174b90a1 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -2,23 +2,23 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "clientmodel.h" - -#include "bantablemodel.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "peertablemodel.h" - -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "clientversion.h" -#include "validation.h" -#include "net.h" -#include "txmempool.h" -#include "ui_interface.h" -#include "util.h" -#include "warnings.h" +#include <qt/clientmodel.h> + +#include <qt/bantablemodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/peertablemodel.h> + +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#include <clientversion.h> +#include <validation.h> +#include <net.h> +#include <txmempool.h> +#include <ui_interface.h> +#include <util.h> +#include <warnings.h> #include <stdint.h> diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 207e441b6b..49f4e74a9f 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -2,24 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "coincontroldialog.h" -#include "ui_coincontroldialog.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "txmempool.h" -#include "walletmodel.h" - -#include "wallet/coincontrol.h" -#include "init.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "validation.h" // For mempool -#include "wallet/fees.h" -#include "wallet/wallet.h" +#include <qt/coincontroldialog.h> +#include <qt/forms/ui_coincontroldialog.h> + +#include <qt/addresstablemodel.h> +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <txmempool.h> +#include <qt/walletmodel.h> + +#include <wallet/coincontrol.h> +#include <init.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <validation.h> // For mempool +#include <wallet/fees.h> +#include <wallet/wallet.h> #include <QApplication> #include <QCheckBox> @@ -28,9 +28,7 @@ #include <QFlags> #include <QIcon> #include <QSettings> -#include <QString> #include <QTreeWidget> -#include <QTreeWidgetItem> QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 4949c91771..51b0a42907 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_COINCONTROLDIALOG_H #define BITCOIN_QT_COINCONTROLDIALOG_H -#include "amount.h" +#include <amount.h> #include <QAbstractButton> #include <QAction> diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp index 88510b6168..b628824793 100644 --- a/src/qt/coincontroltreewidget.cpp +++ b/src/qt/coincontroltreewidget.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "coincontroltreewidget.h" -#include "coincontroldialog.h" +#include <qt/coincontroltreewidget.h> +#include <qt/coincontroldialog.h> CoinControlTreeWidget::CoinControlTreeWidget(QWidget *parent) : QTreeWidget(parent) diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp index df59927782..702757147b 100644 --- a/src/qt/csvmodelwriter.cpp +++ b/src/qt/csvmodelwriter.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "csvmodelwriter.h" +#include <qt/csvmodelwriter.h> #include <QAbstractItemModel> #include <QFile> diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index bb03c12f2d..0437f81a7e 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "editaddressdialog.h" -#include "ui_editaddressdialog.h" +#include <qt/editaddressdialog.h> +#include <qt/forms/ui_editaddressdialog.h> -#include "addresstablemodel.h" -#include "guiutil.h" +#include <qt/addresstablemodel.h> +#include <qt/guiutil.h> #include <QDataWidgetMapper> #include <QMessageBox> diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui index 1ea00eb5c3..d1237ad283 100644 --- a/src/qt/forms/coincontroldialog.ui +++ b/src/qt/forms/coincontroldialog.ui @@ -487,7 +487,7 @@ <customwidget> <class>CoinControlTreeWidget</class> <extends>QTreeWidget</extends> - <header>coincontroltreewidget.h</header> + <header>qt/coincontroltreewidget.h</header> </customwidget> </customwidgets> <resources/> diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 093e644bdc..bba822882e 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -1424,7 +1424,7 @@ <customwidget> <class>TrafficGraphWidget</class> <extends>QWidget</extends> - <header>trafficgraphwidget.h</header> + <header>qt/trafficgraphwidget.h</header> <container>1</container> <slots> <slot>clear()</slot> diff --git a/src/qt/forms/editaddressdialog.ui b/src/qt/forms/editaddressdialog.ui index c1aea36338..e968271107 100644 --- a/src/qt/forms/editaddressdialog.ui +++ b/src/qt/forms/editaddressdialog.ui @@ -71,7 +71,7 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> </customwidgets> <resources/> diff --git a/src/qt/forms/modaloverlay.ui b/src/qt/forms/modaloverlay.ui index 65a7a6c77e..fdc52dc455 100644 --- a/src/qt/forms/modaloverlay.ui +++ b/src/qt/forms/modaloverlay.ui @@ -367,7 +367,7 @@ QLabel { color: rgb(40,40,40); }</string> <customwidget> <class>ModalOverlay</class> <extends>QWidget</extends> - <header>modaloverlay.h</header> + <header>qt/modaloverlay.h</header> <container>1</container> </customwidget> </customwidgets> diff --git a/src/qt/forms/openuridialog.ui b/src/qt/forms/openuridialog.ui index 7fce858bd2..0e1048bc07 100644 --- a/src/qt/forms/openuridialog.ui +++ b/src/qt/forms/openuridialog.ui @@ -77,7 +77,7 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> </customwidgets> <resources/> diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index e31bfee05e..a3721991ee 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -824,12 +824,12 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> <customwidget> <class>QValueComboBox</class> <extends>QComboBox</extends> - <header>qvaluecombobox.h</header> + <header>qt/qvaluecombobox.h</header> </customwidget> </customwidgets> <resources/> diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 03fcb2fb50..58f030ebf0 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -28,23 +28,6 @@ <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <layout class="QGridLayout" name="gridLayout"> - <item row="7" column="2"> - <widget class="QCheckBox" name="reuseAddress"> - <property name="toolTip"> - <string>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</string> - </property> - <property name="text"> - <string>R&euse an existing receiving address (not recommended)</string> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string/> - </property> - </widget> - </item> <item row="6" column="0"> <widget class="QLabel" name="label_3"> <property name="toolTip"> @@ -127,7 +110,7 @@ </property> </widget> </item> - <item row="8" column="2"> + <item row="7" column="2"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QPushButton" name="receiveButton"> @@ -184,7 +167,7 @@ </item> </layout> </item> - <item row="8" column="0"> + <item row="7" column="0"> <widget class="QLabel" name="label_7"> <property name="text"> <string/> @@ -316,7 +299,7 @@ <customwidget> <class>BitcoinAmountField</class> <extends>QLineEdit</extends> - <header>bitcoinamountfield.h</header> + <header>qt/bitcoinamountfield.h</header> <container>1</container> </customwidget> </customwidgets> @@ -324,7 +307,6 @@ <tabstop>reqLabel</tabstop> <tabstop>reqAmount</tabstop> <tabstop>reqMessage</tabstop> - <tabstop>reuseAddress</tabstop> <tabstop>receiveButton</tabstop> <tabstop>clearButton</tabstop> <tabstop>recentRequestsView</tabstop> diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui index 4163f4189c..dbe966b241 100644 --- a/src/qt/forms/receiverequestdialog.ui +++ b/src/qt/forms/receiverequestdialog.ui @@ -127,7 +127,7 @@ <customwidget> <class>QRImageWidget</class> <extends>QLabel</extends> - <header>receiverequestdialog.h</header> + <header>qt/receiverequestdialog.h</header> </customwidget> </customwidgets> <resources/> diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index a0e48334c1..c6fd708cdf 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1108,10 +1108,10 @@ <item> <widget class="QCheckBox" name="optInRBF"> <property name="text"> - <string>Request Replace-By-Fee</string> + <string>Allow increasing fee</string> </property> <property name="toolTip"> - <string>Indicates that the sender may wish to replace this transaction with a new one paying higher fees (prior to being confirmed).</string> + <string>This allows you to increase the fee later if the transaction takes a long time to confirm. This will also cause the recommended fee to be lower. ("Replace-By-Fee", BIP 125)</string> </property> </widget> </item> @@ -1264,12 +1264,12 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> <customwidget> <class>BitcoinAmountField</class> <extends>QLineEdit</extends> - <header>bitcoinamountfield.h</header> + <header>qt/bitcoinamountfield.h</header> <container>1</container> </customwidget> </customwidgets> diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index df06f36833..3c699abc6a 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -163,7 +163,7 @@ </widget> </item> <item row="2" column="1"> - <layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1"> + <layout class="QHBoxLayout" name="horizontalLayoutAmount" stretch="0,1,0"> <item> <widget class="BitcoinAmountField" name="payAmount"/> </item> @@ -177,6 +177,13 @@ </property> </widget> </item> + <item> + <widget class="QPushButton" name="useAvailableBalanceButton"> + <property name="text"> + <string>Use available balance</string> + </property> + </widget> + </item> </layout> </item> <item row="3" column="0"> @@ -1248,12 +1255,12 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> <customwidget> <class>BitcoinAmountField</class> <extends>QLineEdit</extends> - <header>bitcoinamountfield.h</header> + <header>qt/bitcoinamountfield.h</header> </customwidget> </customwidgets> <tabstops> diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui index 92f6430c51..c9ddd757c1 100644 --- a/src/qt/forms/signverifymessagedialog.ui +++ b/src/qt/forms/signverifymessagedialog.ui @@ -380,7 +380,7 @@ <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> - <header>qvalidatedlineedit.h</header> + <header>qt/qvalidatedlineedit.h</header> </customwidget> </customwidgets> <resources> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 4bd63f4649..eb5d3304af 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -2,21 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "guiutil.h" - -#include "bitcoinaddressvalidator.h" -#include "bitcoinunits.h" -#include "qvalidatedlineedit.h" -#include "walletmodel.h" - -#include "fs.h" -#include "primitives/transaction.h" -#include "init.h" -#include "policy/policy.h" -#include "protocol.h" -#include "script/script.h" -#include "script/standard.h" -#include "util.h" +#include <qt/guiutil.h> + +#include <qt/bitcoinaddressvalidator.h> +#include <qt/bitcoinunits.h> +#include <qt/qvalidatedlineedit.h> +#include <qt/walletmodel.h> + +#include <primitives/transaction.h> +#include <init.h> +#include <policy/policy.h> +#include <protocol.h> +#include <script/script.h> +#include <script/standard.h> +#include <util.h> #ifdef WIN32 #ifdef _WIN32_WINNT @@ -31,9 +30,9 @@ #ifndef NOMINMAX #define NOMINMAX #endif -#include "shellapi.h" -#include "shlobj.h" -#include "shlwapi.h" +#include <shellapi.h> +#include <shlobj.h> +#include <shlwapi.h> #endif #include <boost/scoped_array.hpp> diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 7622816f7f..d0ab491952 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -5,8 +5,8 @@ #ifndef BITCOIN_QT_GUIUTIL_H #define BITCOIN_QT_GUIUTIL_H -#include "amount.h" -#include "fs.h" +#include <amount.h> +#include <fs.h> #include <QEvent> #include <QHeaderView> diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 0ff95d8502..7f8a8394e6 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -3,16 +3,16 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "fs.h" -#include "intro.h" -#include "ui_intro.h" +#include <fs.h> +#include <qt/intro.h> +#include <qt/forms/ui_intro.h> -#include "guiutil.h" +#include <qt/guiutil.h> -#include "util.h" +#include <util.h> #include <QFileDialog> #include <QSettings> @@ -60,7 +60,7 @@ private: Intro *intro; }; -#include "intro.moc" +#include <qt/intro.moc> FreespaceChecker::FreespaceChecker(Intro *_intro) { @@ -214,7 +214,10 @@ bool Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir)); + if (TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir))) { + // If a new data directory has been created, make wallets subdirectory too + TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) / "wallets"); + } break; } catch (const fs::filesystem_error&) { QMessageBox::critical(0, tr(PACKAGE_NAME), diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index e32a0bdda8..b707b0dda9 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "modaloverlay.h" -#include "ui_modaloverlay.h" +#include <qt/modaloverlay.h> +#include <qt/forms/ui_modaloverlay.h> -#include "guiutil.h" +#include <qt/guiutil.h> -#include "chainparams.h" +#include <chainparams.h> #include <QResizeEvent> #include <QPropertyAnimation> diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index 4b81c54d36..42ae3ae566 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "networkstyle.h" +#include <qt/networkstyle.h> -#include "guiconstants.h" +#include <qt/guiconstants.h> #include <QApplication> diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 937928315b..f4383bf679 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -2,11 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "notificator.h" +#include <qt/notificator.h> #include <QApplication> #include <QByteArray> -#include <QIcon> #include <QImageWriter> #include <QMessageBox> #include <QMetaType> @@ -24,7 +23,7 @@ // #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 #ifdef Q_OS_MAC #include <ApplicationServices/ApplicationServices.h> -#include "macnotificationhandler.h" +#include <qt/macnotificationhandler.h> #endif diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 67f2b1df69..ef6f5c7ec5 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -6,7 +6,7 @@ #define BITCOIN_QT_NOTIFICATOR_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <QIcon> diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp index 3ee656d470..40671922f4 100644 --- a/src/qt/openuridialog.cpp +++ b/src/qt/openuridialog.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "openuridialog.h" -#include "ui_openuridialog.h" +#include <qt/openuridialog.h> +#include <qt/forms/ui_openuridialog.h> -#include "guiutil.h" -#include "walletmodel.h" +#include <qt/guiutil.h> +#include <qt/walletmodel.h> #include <QUrl> diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 53e2e5053c..a0f78d5ead 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -3,19 +3,19 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "optionsdialog.h" -#include "ui_optionsdialog.h" +#include <qt/optionsdialog.h> +#include <qt/forms/ui_optionsdialog.h> -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> -#include "validation.h" // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS -#include "netbase.h" -#include "txdb.h" // for -dbcache defaults +#include <validation.h> // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS +#include <netbase.h> +#include <txdb.h> // for -dbcache defaults #include <QDataWidgetMapper> #include <QDir> @@ -338,7 +338,7 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons { Q_UNUSED(pos); // Validate the proxy - CService serv(LookupNumeric(input.toStdString().c_str(), 9050)); + CService serv(LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT)); proxyType addrProxy = proxyType(serv, true); if (addrProxy.IsValid()) return QValidator::Acceptable; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index fb8c60d100..c9e4f517c7 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -3,31 +3,32 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "optionsmodel.h" +#include <qt/optionsmodel.h> -#include "bitcoinunits.h" -#include "guiutil.h" +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> -#include "amount.h" -#include "init.h" -#include "validation.h" // For DEFAULT_SCRIPTCHECK_THREADS -#include "net.h" -#include "netbase.h" -#include "txdb.h" // for -dbcache defaults -#include "intro.h" +#include <init.h> +#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS +#include <net.h> +#include <netbase.h> +#include <txdb.h> // for -dbcache defaults +#include <qt/intro.h> #ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#include "wallet/walletdb.h" +#include <wallet/wallet.h> +#include <wallet/walletdb.h> #endif #include <QNetworkProxy> #include <QSettings> #include <QStringList> +const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1"; + OptionsModel::OptionsModel(QObject *parent, bool resetSettings) : QAbstractListModel(parent) { @@ -124,8 +125,8 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("fUseProxy")) settings.setValue("fUseProxy", false); - if (!settings.contains("addrProxy") || !settings.value("addrProxy").toString().contains(':')) - settings.setValue("addrProxy", "127.0.0.1:9050"); + if (!settings.contains("addrProxy")) + settings.setValue("addrProxy", QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST, DEFAULT_GUI_PROXY_PORT)); // Only try to set -proxy, if user has enabled fUseProxy if (settings.value("fUseProxy").toBool() && !gArgs.SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) addOverriddenOption("-proxy"); @@ -134,8 +135,8 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("fUseSeparateProxyTor")) settings.setValue("fUseSeparateProxyTor", false); - if (!settings.contains("addrSeparateProxyTor") || !settings.value("addrSeparateProxyTor").toString().contains(':')) - settings.setValue("addrSeparateProxyTor", "127.0.0.1:9050"); + if (!settings.contains("addrSeparateProxyTor")) + settings.setValue("addrSeparateProxyTor", QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST, DEFAULT_GUI_PROXY_PORT)); // Only try to set -onion, if user has enabled fUseSeparateProxyTor if (settings.value("fUseSeparateProxyTor").toBool() && !gArgs.SoftSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString())) addOverriddenOption("-onion"); @@ -200,6 +201,33 @@ int OptionsModel::rowCount(const QModelIndex & parent) const return OptionIDRowCount; } +struct ProxySetting { + bool is_set; + QString ip; + QString port; +}; + +static ProxySetting GetProxySetting(QSettings &settings, const QString &name) +{ + static const ProxySetting default_val = {false, DEFAULT_GUI_PROXY_HOST, QString("%1").arg(DEFAULT_GUI_PROXY_PORT)}; + // Handle the case that the setting is not set at all + if (!settings.contains(name)) { + return default_val; + } + // contains IP at index 0 and port at index 1 + QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts); + if (ip_port.size() == 2) { + return {true, ip_port.at(0), ip_port.at(1)}; + } else { // Invalid: return default + return default_val; + } +} + +static void SetProxySetting(QSettings &settings, const QString &name, const ProxySetting &ip_port) +{ + settings.setValue(name, ip_port.ip + ":" + ip_port.port); +} + // read QSettings values and return them QVariant OptionsModel::data(const QModelIndex & index, int role) const { @@ -226,30 +254,18 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const // default proxy case ProxyUse: return settings.value("fUseProxy", false); - case ProxyIP: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(0); - } - case ProxyPort: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(1); - } + case ProxyIP: + return GetProxySetting(settings, "addrProxy").ip; + case ProxyPort: + return GetProxySetting(settings, "addrProxy").port; // separate Tor proxy case ProxyUseTor: return settings.value("fUseSeparateProxyTor", false); - case ProxyIPTor: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(0); - } - case ProxyPortTor: { - // contains IP at index 0 and port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - return strlIpPort.at(1); - } + case ProxyIPTor: + return GetProxySetting(settings, "addrSeparateProxyTor").ip; + case ProxyPortTor: + return GetProxySetting(settings, "addrSeparateProxyTor").port; #ifdef ENABLE_WALLET case SpendZeroConfChange: @@ -314,25 +330,19 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; case ProxyIP: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed IP - if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) { - // construct new value from new IP and current port - QString strNewValue = value.toString() + ":" + strlIpPort.at(1); - settings.setValue("addrProxy", strNewValue); + auto ip_port = GetProxySetting(settings, "addrProxy"); + if (!ip_port.is_set || ip_port.ip != value.toString()) { + ip_port.ip = value.toString(); + SetProxySetting(settings, "addrProxy", ip_port); setRestartRequired(true); } } break; case ProxyPort: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed port - if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) { - // construct new value from current IP and new port - QString strNewValue = strlIpPort.at(0) + ":" + value.toString(); - settings.setValue("addrProxy", strNewValue); + auto ip_port = GetProxySetting(settings, "addrProxy"); + if (!ip_port.is_set || ip_port.port != value.toString()) { + ip_port.port = value.toString(); + SetProxySetting(settings, "addrProxy", ip_port); setRestartRequired(true); } } @@ -346,25 +356,19 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; case ProxyIPTor: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed IP - if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(0) != value.toString()) { - // construct new value from new IP and current port - QString strNewValue = value.toString() + ":" + strlIpPort.at(1); - settings.setValue("addrSeparateProxyTor", strNewValue); + auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor"); + if (!ip_port.is_set || ip_port.ip != value.toString()) { + ip_port.ip = value.toString(); + SetProxySetting(settings, "addrSeparateProxyTor", ip_port); setRestartRequired(true); } } break; case ProxyPortTor: { - // contains current IP at index 0 and current port at index 1 - QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts); - // if that key doesn't exist or has a changed port - if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(1) != value.toString()) { - // construct new value from current IP and new port - QString strNewValue = strlIpPort.at(0) + ":" + value.toString(); - settings.setValue("addrSeparateProxyTor", strNewValue); + auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor"); + if (!ip_port.is_set || ip_port.port != value.toString()) { + ip_port.port = value.toString(); + SetProxySetting(settings, "addrSeparateProxyTor", ip_port); setRestartRequired(true); } } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 0ac82a4148..f8782dd204 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_OPTIONSMODEL_H #define BITCOIN_QT_OPTIONSMODEL_H -#include "amount.h" +#include <amount.h> #include <QAbstractListModel> @@ -13,6 +13,9 @@ QT_BEGIN_NAMESPACE class QNetworkProxy; QT_END_NAMESPACE +extern const char *DEFAULT_GUI_PROXY_HOST; +static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050; + /** Interface from Qt to configuration data structure for Bitcoin client. To Qt, the options are presented as a list with the different options laid out vertically. diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index ba1839e7b4..7818607d30 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "overviewpage.h" -#include "ui_overviewpage.h" - -#include "bitcoinunits.h" -#include "clientmodel.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "transactionfilterproxy.h" -#include "transactiontablemodel.h" -#include "walletmodel.h" +#include <qt/overviewpage.h> +#include <qt/forms/ui_overviewpage.h> + +#include <qt/bitcoinunits.h> +#include <qt/clientmodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/transactionfilterproxy.h> +#include <qt/transactiontablemodel.h> +#include <qt/walletmodel.h> #include <QAbstractItemDelegate> #include <QPainter> @@ -106,7 +106,7 @@ public: const PlatformStyle *platformStyle; }; -#include "overviewpage.moc" +#include <qt/overviewpage.moc> OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) : QWidget(parent), diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index d76b651ce6..1e09d907b0 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_OVERVIEWPAGE_H #define BITCOIN_QT_OVERVIEWPAGE_H -#include "amount.h" +#include <amount.h> #include <QWidget> #include <memory> diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index c7f92a0921..4503728882 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -7,9 +7,9 @@ // with some extra methods // -#include "paymentrequestplus.h" +#include <qt/paymentrequestplus.h> -#include "util.h" +#include <util.h> #include <stdexcept> diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index a2fea3fdc6..e1388f2b5d 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -7,10 +7,10 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#include "paymentrequest.pb.h" +#include <qt/paymentrequest.pb.h> #pragma GCC diagnostic pop -#include "base58.h" +#include <base58.h> #include <openssl/x509.h> diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 506e49af0d..510a3783ae 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "paymentserver.h" - -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" - -#include "base58.h" -#include "chainparams.h" -#include "policy/policy.h" -#include "ui_interface.h" -#include "util.h" -#include "wallet/wallet.h" +#include <qt/paymentserver.h> + +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> + +#include <base58.h> +#include <chainparams.h> +#include <policy/policy.h> +#include <ui_interface.h> +#include <util.h> +#include <wallet/wallet.h> #include <cstdlib> diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 98b2364b92..9adef9743d 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -32,8 +32,8 @@ // sends them to the server. // -#include "paymentrequestplus.h" -#include "walletmodel.h" +#include <qt/paymentrequestplus.h> +#include <qt/walletmodel.h> #include <QObject> #include <QString> diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 8b2a7e7047..cfafab2c8a 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "peertablemodel.h" +#include <qt/peertablemodel.h> -#include "clientmodel.h" -#include "guiconstants.h" -#include "guiutil.h" +#include <qt/clientmodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> -#include "validation.h" // for cs_main -#include "sync.h" +#include <validation.h> // for cs_main +#include <sync.h> #include <QDebug> #include <QList> diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index ec91d07127..e41fe4bb03 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -5,8 +5,8 @@ #ifndef BITCOIN_QT_PEERTABLEMODEL_H #define BITCOIN_QT_PEERTABLEMODEL_H -#include "net_processing.h" // For CNodeStateStats -#include "net.h" +#include <net_processing.h> // For CNodeStateStats +#include <net.h> #include <QAbstractTableModel> #include <QStringList> diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 1f4e1a442f..0e1bd59ada 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -2,16 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "platformstyle.h" +#include <qt/platformstyle.h> -#include "guiconstants.h" +#include <qt/guiconstants.h> #include <QApplication> #include <QColor> -#include <QIcon> #include <QImage> #include <QPalette> -#include <QPixmap> static const struct { const char *platformId; diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index 179ecdc8b3..4d6d5891c9 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "qvalidatedlineedit.h" +#include <qt/qvalidatedlineedit.h> -#include "bitcoinaddressvalidator.h" -#include "guiconstants.h" +#include <qt/bitcoinaddressvalidator.h> +#include <qt/guiconstants.h> QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : QLineEdit(parent), diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index a3b9b994ec..af5f6f8fd0 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "qvaluecombobox.h" +#include <qt/qvaluecombobox.h> QValueComboBox::QValueComboBox(QWidget *parent) : QComboBox(parent), role(Qt::UserRole) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 84f43266e1..e9dcbc0a72 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -2,22 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "receivecoinsdialog.h" -#include "ui_receivecoinsdialog.h" - -#include "addressbookpage.h" -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "receiverequestdialog.h" -#include "recentrequeststablemodel.h" -#include "walletmodel.h" +#include <qt/receivecoinsdialog.h> +#include <qt/forms/ui_receivecoinsdialog.h> + +#include <qt/addressbookpage.h> +#include <qt/addresstablemodel.h> +#include <qt/bitcoinunits.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/receiverequestdialog.h> +#include <qt/recentrequeststablemodel.h> +#include <qt/walletmodel.h> #include <QAction> #include <QCursor> -#include <QItemSelection> #include <QMessageBox> #include <QScrollBar> #include <QTextDocument> @@ -106,7 +104,6 @@ void ReceiveCoinsDialog::clear() ui->reqAmount->clear(); ui->reqLabel->setText(""); ui->reqMessage->setText(""); - ui->reuseAddress->setChecked(false); updateDisplayUnit(); } @@ -135,25 +132,8 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString address; QString label = ui->reqLabel->text(); - if(ui->reuseAddress->isChecked()) - { - /* Choose existing receiving address */ - AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this); - dlg.setModel(model->getAddressTableModel()); - if(dlg.exec()) - { - address = dlg.getReturnValue(); - if(label.isEmpty()) /* If no label provided, use the previously used label */ - { - label = model->getAddressTableModel()->labelForAddress(address); - } - } else { - return; - } - } else { - /* Generate new receiving address */ - address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, ""); - } + /* Generate new receiving address */ + address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, ""); SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text()); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 385f98565c..3687cca87b 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_RECEIVECOINSDIALOG_H #define BITCOIN_QT_RECEIVECOINSDIALOG_H -#include "guiutil.h" +#include <qt/guiutil.h> #include <QDialog> #include <QHeaderView> diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 4aa6375d8a..d30e9b2dca 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -2,14 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "receiverequestdialog.h" -#include "ui_receiverequestdialog.h" +#include <qt/receiverequestdialog.h> +#include <qt/forms/ui_receiverequestdialog.h> -#include "bitcoinunits.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "walletmodel.h" +#include <qt/bitcoinunits.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> #include <QClipboard> #include <QDrag> @@ -22,7 +21,7 @@ #endif #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" /* for USE_QRCODE */ +#include <config/bitcoin-config.h> /* for USE_QRCODE */ #endif #ifdef USE_QRCODE diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 1a9b165237..23b81135e2 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_RECEIVEREQUESTDIALOG_H #define BITCOIN_QT_RECEIVEREQUESTDIALOG_H -#include "walletmodel.h" +#include <qt/walletmodel.h> #include <QDialog> #include <QImage> diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 1c4f7aca86..4d6e401d0d 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "recentrequeststablemodel.h" +#include <qt/recentrequeststablemodel.h> -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> -#include "clientversion.h" -#include "streams.h" +#include <clientversion.h> +#include <streams.h> RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel *parent) : diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 0c02968f92..c88b8c4426 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H #define BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H -#include "walletmodel.h" +#include <qt/walletmodel.h> #include <QAbstractTableModel> #include <QStringList> diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 068c40e1e6..0b90205270 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -3,21 +3,20 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "rpcconsole.h" -#include "ui_debugwindow.h" +#include <qt/rpcconsole.h> +#include <qt/forms/ui_debugwindow.h> -#include "bantablemodel.h" -#include "clientmodel.h" -#include "guiutil.h" -#include "platformstyle.h" -#include "chainparams.h" -#include "netbase.h" -#include "rpc/server.h" -#include "rpc/client.h" -#include "util.h" +#include <qt/bantablemodel.h> +#include <qt/clientmodel.h> +#include <qt/platformstyle.h> +#include <chainparams.h> +#include <netbase.h> +#include <rpc/server.h> +#include <rpc/client.h> +#include <util.h> #include <openssl/crypto.h> @@ -35,7 +34,6 @@ #include <QScrollBar> #include <QSettings> #include <QSignalMapper> -#include <QThread> #include <QTime> #include <QTimer> #include <QStringList> @@ -125,7 +123,7 @@ public: }; -#include "rpcconsole.moc" +#include <qt/rpcconsole.moc> /** * Split shell command line into a list of arguments and optionally execute the command(s). @@ -392,11 +390,37 @@ void RPCExecutor::request(const QString &command) { std::string result; std::string executableCommand = command.toStdString() + "\n"; + + // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply. + if(executableCommand == "help-console\n") + { + Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n" + "This console accepts RPC commands using the standard syntax.\n" + " example: getblockhash 0\n\n" + + "This console can also accept RPC commands using parenthesized syntax.\n" + " example: getblockhash(0)\n\n" + + "Commands may be nested when specified with the parenthesized syntax.\n" + " example: getblock(getblockhash(0) 1)\n\n" + + "A space or a comma can be used to delimit arguments for either syntax.\n" + " example: getblockhash 0\n" + " getblockhash,0\n\n" + + "Named results can be queried with a non-quoted key string in brackets.\n" + " example: getblock(getblockhash(0) true)[tx]\n\n" + + "Results without keys can be queried using an integer in brackets.\n" + " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); + return; + } if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result)); } catch (UniValue& objError) @@ -645,6 +669,7 @@ void RPCConsole::setClientModel(ClientModel *model) wordList << ("help " + commandList[i]).c_str(); } + wordList << "help-console"; wordList.sort(); autoCompleter = new QCompleter(wordList, this); autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); @@ -750,10 +775,11 @@ void RPCConsole::clear(bool clearHistory) message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "<br>" + tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg("<b>"+clsKey+"</b>") + "<br>" + - tr("Type <b>help</b> for an overview of available commands.")) + - "<br><span class=\"secwarning\">" + + tr("Type %1 for an overview of available commands.").arg("<b>help</b>") + "<br>" + + tr("For more information on using this console type %1.").arg("<b>help-console</b>") + + "<br><span class=\"secwarning\"><br>" + tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") + - "</span>", + "</span>"), true); } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index ad6e84a44a..5960410cdd 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -5,10 +5,10 @@ #ifndef BITCOIN_QT_RPCCONSOLE_H #define BITCOIN_QT_RPCCONSOLE_H -#include "guiutil.h" -#include "peertablemodel.h" +#include <qt/guiutil.h> +#include <qt/peertablemodel.h> -#include "net.h" +#include <net.h> #include <QWidget> #include <QCompleter> diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 6309070fef..2a46cdab8c 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -2,34 +2,31 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sendcoinsdialog.h" -#include "ui_sendcoinsdialog.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "clientmodel.h" -#include "coincontroldialog.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "sendcoinsentry.h" -#include "walletmodel.h" - -#include "base58.h" -#include "chainparams.h" -#include "wallet/coincontrol.h" -#include "validation.h" // mempool and minRelayTxFee -#include "ui_interface.h" -#include "txmempool.h" -#include "policy/fees.h" -#include "wallet/fees.h" +#include <qt/sendcoinsdialog.h> +#include <qt/forms/ui_sendcoinsdialog.h> + +#include <qt/addresstablemodel.h> +#include <qt/bitcoinunits.h> +#include <qt/clientmodel.h> +#include <qt/coincontroldialog.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/sendcoinsentry.h> + +#include <base58.h> +#include <chainparams.h> +#include <wallet/coincontrol.h> +#include <validation.h> // mempool and minRelayTxFee +#include <ui_interface.h> +#include <txmempool.h> +#include <policy/fees.h> +#include <wallet/fees.h> #include <QFontMetrics> -#include <QMessageBox> #include <QScrollBar> #include <QSettings> #include <QTextDocument> -#include <QTimer> static const std::array<int, 9> confTargets = { {2, 4, 6, 12, 24, 48, 144, 504, 1008} }; int getConfTargetForIndex(int index) { @@ -345,7 +342,7 @@ void SendCoinsDialog::on_sendButton_clicked() if (ui->optInRBF->isChecked()) { questionString.append("<hr /><span>"); - questionString.append(tr("This transaction signals replaceability (optin-RBF).")); + questionString.append(tr("You can increase the fee later (signals Replace-By-Fee).")); questionString.append("</span>"); } @@ -402,6 +399,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry() entry->setModel(model); ui->entries->addWidget(entry); connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*))); + connect(entry, SIGNAL(useAvailableBalance(SendCoinsEntry*)), this, SLOT(useAvailableBalance(SendCoinsEntry*))); connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels())); connect(entry, SIGNAL(subtractFeeFromAmountChanged()), this, SLOT(coinControlUpdateLabels())); @@ -599,6 +597,31 @@ void SendCoinsDialog::on_buttonMinimizeFee_clicked() minimizeFeeSection(true); } +void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry) +{ + // Get CCoinControl instance if CoinControl is enabled or create a new one. + CCoinControl coin_control; + if (model->getOptionsModel()->getCoinControlFeatures()) { + coin_control = *CoinControlDialog::coinControl; + } + + // Calculate available amount to send. + CAmount amount = model->getBalance(&coin_control); + for (int i = 0; i < ui->entries->count(); ++i) { + SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget()); + if (e && !e->isHidden() && e != entry) { + amount -= e->getValue().amount; + } + } + + if (amount > 0) { + entry->checkSubtractFeeFromAmount(); + entry->setAmount(amount); + } else { + entry->setAmount(0); + } +} + void SendCoinsDialog::setMinimumFee() { ui->customFee->setValue(GetRequiredFee(1000)); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 70b4aa5a03..300116fd9f 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_SENDCOINSDIALOG_H #define BITCOIN_QT_SENDCOINSDIALOG_H -#include "walletmodel.h" +#include <qt/walletmodel.h> #include <QDialog> #include <QMessageBox> @@ -76,6 +76,7 @@ private Q_SLOTS: void on_buttonChooseFee_clicked(); void on_buttonMinimizeFee_clicked(); void removeEntry(SendCoinsEntry* entry); + void useAvailableBalance(SendCoinsEntry* entry); void updateDisplayUnit(); void coinControlFeatureChanged(bool); void coinControlButtonClicked(); diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index bb0f47b21c..4cf4bb9ef7 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -2,15 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sendcoinsentry.h" -#include "ui_sendcoinsentry.h" +#include <qt/sendcoinsentry.h> +#include <qt/forms/ui_sendcoinsentry.h> -#include "addressbookpage.h" -#include "addresstablemodel.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "walletmodel.h" +#include <qt/addressbookpage.h> +#include <qt/addresstablemodel.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> #include <QApplication> #include <QClipboard> @@ -48,6 +47,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked())); connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked())); connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked())); + connect(ui->useAvailableBalanceButton, SIGNAL(clicked()), this, SLOT(useAvailableBalanceClicked())); } SendCoinsEntry::~SendCoinsEntry() @@ -112,11 +112,21 @@ void SendCoinsEntry::clear() updateDisplayUnit(); } +void SendCoinsEntry::checkSubtractFeeFromAmount() +{ + ui->checkboxSubtractFeeFromAmount->setChecked(true); +} + void SendCoinsEntry::deleteClicked() { Q_EMIT removeEntry(this); } +void SendCoinsEntry::useAvailableBalanceClicked() +{ + Q_EMIT useAvailableBalance(this); +} + bool SendCoinsEntry::validate() { if (!model) @@ -228,6 +238,11 @@ void SendCoinsEntry::setAddress(const QString &address) ui->payAmount->setFocus(); } +void SendCoinsEntry::setAmount(const CAmount &amount) +{ + ui->payAmount->setValue(amount); +} + bool SendCoinsEntry::isClear() { return ui->payTo->text().isEmpty() && ui->payTo_is->text().isEmpty() && ui->payTo_s->text().isEmpty(); diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index a8be670c2a..b470a0d72e 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_SENDCOINSENTRY_H #define BITCOIN_QT_SENDCOINSENTRY_H -#include "walletmodel.h" +#include <qt/walletmodel.h> #include <QStackedWidget> @@ -38,6 +38,7 @@ public: void setValue(const SendCoinsRecipient &value); void setAddress(const QString &address); + void setAmount(const CAmount &amount); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases * (issue https://bugreports.qt-project.org/browse/QTBUG-10907). @@ -48,14 +49,17 @@ public: public Q_SLOTS: void clear(); + void checkSubtractFeeFromAmount(); Q_SIGNALS: void removeEntry(SendCoinsEntry *entry); + void useAvailableBalance(SendCoinsEntry* entry); void payAmountChanged(); void subtractFeeFromAmountChanged(); private Q_SLOTS: void deleteClicked(); + void useAvailableBalanceClicked(); void on_payTo_textChanged(const QString &address); void on_addressBookButton_clicked(); void on_pasteButton_clicked(); diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index cba9d4da38..4cd0c76b16 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "signverifymessagedialog.h" -#include "ui_signverifymessagedialog.h" - -#include "addressbookpage.h" -#include "guiutil.h" -#include "platformstyle.h" -#include "walletmodel.h" - -#include "base58.h" -#include "init.h" -#include "validation.h" // For strMessageMagic -#include "wallet/wallet.h" +#include <qt/signverifymessagedialog.h> +#include <qt/forms/ui_signverifymessagedialog.h> + +#include <qt/addressbookpage.h> +#include <qt/guiutil.h> +#include <qt/platformstyle.h> +#include <qt/walletmodel.h> + +#include <base58.h> +#include <init.h> +#include <validation.h> // For strMessageMagic +#include <wallet/wallet.h> #include <string> #include <vector> diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index a1fbba963c..5aa1de5553 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -3,21 +3,21 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "splashscreen.h" +#include <qt/splashscreen.h> -#include "networkstyle.h" +#include <qt/networkstyle.h> -#include "clientversion.h" -#include "init.h" -#include "util.h" -#include "ui_interface.h" -#include "version.h" +#include <clientversion.h> +#include <init.h> +#include <util.h> +#include <ui_interface.h> +#include <version.h> #ifdef ENABLE_WALLET -#include "wallet/wallet.h" +#include <wallet/wallet.h> #endif #include <QApplication> diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp index 2a7284b5b2..7a4388e940 100644 --- a/src/qt/test/compattests.cpp +++ b/src/qt/test/compattests.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "paymentrequestplus.h" // this includes protobuf's port.h which defines its own bswap macos +#include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos -#include "compattests.h" +#include <qt/test/compattests.h> -#include "compat/byteswap.h" +#include <compat/byteswap.h> void CompatTests::bswapTests() { diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 273bd10487..1864604372 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -2,17 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "paymentservertests.h" +#include <qt/test/paymentservertests.h> -#include "optionsmodel.h" -#include "paymentrequestdata.h" +#include <qt/optionsmodel.h> +#include <qt/test/paymentrequestdata.h> -#include "amount.h" -#include "random.h" -#include "script/script.h" -#include "script/standard.h" -#include "util.h" -#include "utilstrencodings.h" +#include <amount.h> +#include <random.h> +#include <script/script.h> +#include <script/standard.h> +#include <util.h> +#include <utilstrencodings.h> #include <openssl/x509.h> #include <openssl/x509_vfy.h> diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h index faf167f2c6..6d84c38287 100644 --- a/src/qt/test/paymentservertests.h +++ b/src/qt/test/paymentservertests.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H #define BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H -#include "../paymentserver.h" +#include <qt/paymentserver.h> #include <QObject> #include <QTest> diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 70fdd4bf58..0596ccf90e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpcnestedtests.h" - -#include "chainparams.h" -#include "consensus/validation.h" -#include "fs.h" -#include "validation.h" -#include "rpc/register.h" -#include "rpc/server.h" -#include "rpcconsole.h" -#include "test/test_bitcoin.h" -#include "univalue.h" -#include "util.h" +#include <qt/test/rpcnestedtests.h> + +#include <chainparams.h> +#include <consensus/validation.h> +#include <fs.h> +#include <validation.h> +#include <rpc/register.h> +#include <rpc/server.h> +#include <qt/rpcconsole.h> +#include <test/test_bitcoin.h> +#include <univalue.h> +#include <util.h> #include <QDir> #include <QtGlobal> diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h index 9ad409019f..04a9d124aa 100644 --- a/src/qt/test/rpcnestedtests.h +++ b/src/qt/test/rpcnestedtests.h @@ -8,8 +8,8 @@ #include <QObject> #include <QTest> -#include "txdb.h" -#include "txmempool.h" +#include <txdb.h> +#include <txmempool.h> class RPCNestedTests : public QObject { @@ -17,9 +17,6 @@ class RPCNestedTests : public QObject private Q_SLOTS: void rpcNestedTests(); - -private: - CCoinsViewDB *pcoinsdbview; }; #endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 4c04e67ccc..2e11b4f4d6 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -3,18 +3,18 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "chainparams.h" -#include "rpcnestedtests.h" -#include "util.h" -#include "uritests.h" -#include "compattests.h" +#include <chainparams.h> +#include <qt/test/rpcnestedtests.h> +#include <util.h> +#include <qt/test/uritests.h> +#include <qt/test/compattests.h> #ifdef ENABLE_WALLET -#include "paymentservertests.h" -#include "wallettests.h" +#include <qt/test/paymentservertests.h> +#include <qt/test/wallettests.h> #endif #include <QApplication> diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 8b53c0d5c7..e47aa8b546 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "uritests.h" +#include <qt/test/uritests.h> -#include "guiutil.h" -#include "walletmodel.h" +#include <qt/guiutil.h> +#include <qt/walletmodel.h> #include <QUrl> diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 12755d43e4..4b7c3bd726 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -1,22 +1,22 @@ -#include "wallettests.h" +#include <qt/test/wallettests.h> -#include "qt/bitcoinamountfield.h" -#include "qt/callback.h" -#include "qt/optionsmodel.h" -#include "qt/platformstyle.h" -#include "qt/qvalidatedlineedit.h" -#include "qt/sendcoinsdialog.h" -#include "qt/sendcoinsentry.h" -#include "qt/transactiontablemodel.h" -#include "qt/transactionview.h" -#include "qt/walletmodel.h" -#include "test/test_bitcoin.h" -#include "validation.h" -#include "wallet/wallet.h" -#include "qt/overviewpage.h" -#include "qt/receivecoinsdialog.h" -#include "qt/recentrequeststablemodel.h" -#include "qt/receiverequestdialog.h" +#include <qt/bitcoinamountfield.h> +#include <qt/callback.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/qvalidatedlineedit.h> +#include <qt/sendcoinsdialog.h> +#include <qt/sendcoinsentry.h> +#include <qt/transactiontablemodel.h> +#include <qt/transactionview.h> +#include <qt/walletmodel.h> +#include <test/test_bitcoin.h> +#include <validation.h> +#include <wallet/wallet.h> +#include <qt/overviewpage.h> +#include <qt/receivecoinsdialog.h> +#include <qt/recentrequeststablemodel.h> +#include <qt/receiverequestdialog.h> #include <QAbstractButton> #include <QAction> @@ -164,7 +164,10 @@ void TestGUI() wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive"); wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); } - wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, true); + { + LOCK(cs_main); + wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, true); + } wallet.SetBroadcastTransactions(true); // Create widgets for sending coins and listing transactions. diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 5bb863451f..b5e4ccb406 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "trafficgraphwidget.h" -#include "clientmodel.h" +#include <qt/trafficgraphwidget.h> +#include <qt/clientmodel.h> #include <QPainter> #include <QColor> diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 41ee89de09..3f245e6c33 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -2,21 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactiondesc.h" - -#include "bitcoinunits.h" -#include "guiutil.h" -#include "paymentserver.h" -#include "transactionrecord.h" - -#include "base58.h" -#include "consensus/consensus.h" -#include "validation.h" -#include "script/script.h" -#include "timedata.h" -#include "util.h" -#include "wallet/db.h" -#include "wallet/wallet.h" +#include <qt/transactiondesc.h> + +#include <qt/bitcoinunits.h> +#include <qt/guiutil.h> +#include <qt/paymentserver.h> +#include <qt/transactionrecord.h> + +#include <base58.h> +#include <consensus/consensus.h> +#include <validation.h> +#include <script/script.h> +#include <timedata.h> +#include <util.h> +#include <wallet/db.h> +#include <wallet/wallet.h> #include <stdint.h> #include <string> diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp index 65f163deb2..74d7a8f525 100644 --- a/src/qt/transactiondescdialog.cpp +++ b/src/qt/transactiondescdialog.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactiondescdialog.h" -#include "ui_transactiondescdialog.h" +#include <qt/transactiondescdialog.h> +#include <qt/forms/ui_transactiondescdialog.h> -#include "transactiontablemodel.h" +#include <qt/transactiontablemodel.h> #include <QModelIndex> diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 44e4ef8238..47890fc7e2 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -2,15 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactionfilterproxy.h" +#include <qt/transactionfilterproxy.h> -#include "transactiontablemodel.h" -#include "transactionrecord.h" +#include <qt/transactiontablemodel.h> +#include <qt/transactionrecord.h> #include <cstdlib> -#include <QDateTime> - // Earliest date that can be represented (far in the past) const QDateTime TransactionFilterProxy::MIN_DATE = QDateTime::fromTime_t(0); // Last date that can be represented (far in the future) @@ -20,7 +18,7 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) : QSortFilterProxyModel(parent), dateFrom(MIN_DATE), dateTo(MAX_DATE), - addrPrefix(), + m_search_string(), typeFilter(ALL_TYPES), watchOnlyFilter(WatchOnlyFilter_All), minAmount(0), @@ -38,6 +36,7 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & bool involvesWatchAddress = index.data(TransactionTableModel::WatchonlyRole).toBool(); QString address = index.data(TransactionTableModel::AddressRole).toString(); QString label = index.data(TransactionTableModel::LabelRole).toString(); + QString txid = index.data(TransactionTableModel::TxIDRole).toString(); qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); int status = index.data(TransactionTableModel::StatusRole).toInt(); @@ -51,8 +50,11 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & return false; if(datetime < dateFrom || datetime > dateTo) return false; - if (!address.contains(addrPrefix, Qt::CaseInsensitive) && !label.contains(addrPrefix, Qt::CaseInsensitive)) + if (!address.contains(m_search_string, Qt::CaseInsensitive) && + ! label.contains(m_search_string, Qt::CaseInsensitive) && + ! txid.contains(m_search_string, Qt::CaseInsensitive)) { return false; + } if(amount < minAmount) return false; @@ -66,9 +68,10 @@ void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime invalidateFilter(); } -void TransactionFilterProxy::setAddressPrefix(const QString &_addrPrefix) +void TransactionFilterProxy::setSearchString(const QString &search_string) { - this->addrPrefix = _addrPrefix; + if (m_search_string == search_string) return; + m_search_string = search_string; invalidateFilter(); } diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index 7db02cd61f..fea7502b26 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_TRANSACTIONFILTERPROXY_H #define BITCOIN_QT_TRANSACTIONFILTERPROXY_H -#include "amount.h" +#include <amount.h> #include <QDateTime> #include <QSortFilterProxyModel> @@ -35,7 +35,7 @@ public: }; void setDateRange(const QDateTime &from, const QDateTime &to); - void setAddressPrefix(const QString &addrPrefix); + void setSearchString(const QString &); /** @note Type filter takes a bit field created with TYPE() or ALL_TYPES */ @@ -57,7 +57,7 @@ protected: private: QDateTime dateFrom; QDateTime dateTo; - QString addrPrefix; + QString m_search_string; quint32 typeFilter; WatchOnlyFilter watchOnlyFilter; CAmount minAmount; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 8ac00ac4cf..e3e8377cb9 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactionrecord.h" +#include <qt/transactionrecord.h> -#include "base58.h" -#include "consensus/consensus.h" -#include "validation.h" -#include "timedata.h" -#include "wallet/wallet.h" +#include <base58.h> +#include <consensus/consensus.h> +#include <validation.h> +#include <timedata.h> +#include <wallet/wallet.h> #include <stdint.h> diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index a26e676142..ee85acf4ac 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -5,8 +5,8 @@ #ifndef BITCOIN_QT_TRANSACTIONRECORD_H #define BITCOIN_QT_TRANSACTIONRECORD_H -#include "amount.h" -#include "uint256.h" +#include <amount.h> +#include <uint256.h> #include <QList> #include <QString> diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index e83d824a6a..67580f11ae 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -2,23 +2,23 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactiontablemodel.h" - -#include "addresstablemodel.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "transactiondesc.h" -#include "transactionrecord.h" -#include "walletmodel.h" - -#include "core_io.h" -#include "validation.h" -#include "sync.h" -#include "uint256.h" -#include "util.h" -#include "wallet/wallet.h" +#include <qt/transactiontablemodel.h> + +#include <qt/addresstablemodel.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/transactiondesc.h> +#include <qt/transactionrecord.h> +#include <qt/walletmodel.h> + +#include <core_io.h> +#include <validation.h> +#include <sync.h> +#include <uint256.h> +#include <util.h> +#include <wallet/wallet.h> #include <QColor> #include <QDateTime> @@ -80,10 +80,10 @@ public: cachedWallet.clear(); { LOCK2(cs_main, wallet->cs_wallet); - for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) + for (const auto& entry : wallet->mapWallet) { - if(TransactionRecord::showTransaction(it->second)) - cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second)); + if (TransactionRecord::showTransaction(entry.second)) + cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, entry.second)); } } } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index b1f81498b2..a769707163 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_TRANSACTIONTABLEMODEL_H #define BITCOIN_QT_TRANSACTIONTABLEMODEL_H -#include "bitcoinunits.h" +#include <qt/bitcoinunits.h> #include <QAbstractTableModel> #include <QStringList> diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 39dfdb587c..b7e39e05ec 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -2,23 +2,22 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "transactionview.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "csvmodelwriter.h" -#include "editaddressdialog.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "sendcoinsdialog.h" -#include "transactiondescdialog.h" -#include "transactionfilterproxy.h" -#include "transactionrecord.h" -#include "transactiontablemodel.h" -#include "walletmodel.h" - -#include "ui_interface.h" +#include <qt/transactionview.h> + +#include <qt/addresstablemodel.h> +#include <qt/bitcoinunits.h> +#include <qt/csvmodelwriter.h> +#include <qt/editaddressdialog.h> +#include <qt/optionsmodel.h> +#include <qt/platformstyle.h> +#include <qt/sendcoinsdialog.h> +#include <qt/transactiondescdialog.h> +#include <qt/transactionfilterproxy.h> +#include <qt/transactionrecord.h> +#include <qt/transactiontablemodel.h> +#include <qt/walletmodel.h> + +#include <ui_interface.h> #include <QComboBox> #include <QDateTimeEdit> @@ -95,11 +94,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa hlayout->addWidget(typeWidget); - addressWidget = new QLineEdit(this); + search_widget = new QLineEdit(this); #if QT_VERSION >= 0x040700 - addressWidget->setPlaceholderText(tr("Enter address or label to search")); + search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search")); #endif - hlayout->addWidget(addressWidget); + hlayout->addWidget(search_widget); amountWidget = new QLineEdit(this); #if QT_VERSION >= 0x040700 @@ -187,8 +186,8 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(watchOnlyWidget, SIGNAL(activated(int)), this, SLOT(chooseWatchonly(int))); connect(amountWidget, SIGNAL(textChanged(QString)), amount_typing_delay, SLOT(start())); connect(amount_typing_delay, SIGNAL(timeout()), this, SLOT(changedAmount())); - connect(addressWidget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start())); - connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedPrefix())); + connect(search_widget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start())); + connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedSearch())); connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); @@ -326,11 +325,11 @@ void TransactionView::chooseWatchonly(int idx) (TransactionFilterProxy::WatchOnlyFilter)watchOnlyWidget->itemData(idx).toInt()); } -void TransactionView::changedPrefix() +void TransactionView::changedSearch() { if(!transactionProxyModel) return; - transactionProxyModel->setAddressPrefix(addressWidget->text()); + transactionProxyModel->setSearchString(search_widget->text()); } void TransactionView::changedAmount() diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 5b4cfd4a88..f72a828b00 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_TRANSACTIONVIEW_H #define BITCOIN_QT_TRANSACTIONVIEW_H -#include "guiutil.h" +#include <qt/guiutil.h> #include <QWidget> #include <QKeyEvent> @@ -66,7 +66,7 @@ private: QComboBox *dateWidget; QComboBox *typeWidget; QComboBox *watchOnlyWidget; - QLineEdit *addressWidget; + QLineEdit *search_widget; QLineEdit *amountWidget; QMenu *contextMenu; @@ -113,7 +113,7 @@ public Q_SLOTS: void chooseType(int idx); void chooseWatchonly(int idx); void changedAmount(); - void changedPrefix(); + void changedSearch(); void exportClicked(); void focusTransaction(const QModelIndex&); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 5d8c23d13c..6d5a2f3101 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -3,23 +3,23 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "utilitydialog.h" +#include <qt/utilitydialog.h> -#include "ui_helpmessagedialog.h" +#include <qt/forms/ui_helpmessagedialog.h> -#include "bitcoingui.h" -#include "clientmodel.h" -#include "guiconstants.h" -#include "intro.h" -#include "paymentrequestplus.h" -#include "guiutil.h" +#include <qt/bitcoingui.h> +#include <qt/clientmodel.h> +#include <qt/guiconstants.h> +#include <qt/intro.h> +#include <qt/paymentrequestplus.h> +#include <qt/guiutil.h> -#include "clientversion.h" -#include "init.h" -#include "util.h" +#include <clientversion.h> +#include <init.h> +#include <util.h> #include <stdio.h> diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 714a594318..573b3f1412 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "walletframe.h" +#include <qt/walletframe.h> -#include "bitcoingui.h" -#include "walletview.h" +#include <qt/bitcoingui.h> +#include <qt/walletview.h> #include <cassert> #include <cstdio> diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e1d0660627..a38e233608 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -2,32 +2,32 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "walletmodel.h" - -#include "addresstablemodel.h" -#include "consensus/validation.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "paymentserver.h" -#include "recentrequeststablemodel.h" -#include "sendcoinsdialog.h" -#include "transactiontablemodel.h" - -#include "base58.h" -#include "chain.h" -#include "keystore.h" -#include "validation.h" -#include "net.h" // for g_connman -#include "policy/fees.h" -#include "policy/rbf.h" -#include "sync.h" -#include "ui_interface.h" -#include "util.h" // for GetBoolArg -#include "wallet/coincontrol.h" -#include "wallet/feebumper.h" -#include "wallet/wallet.h" -#include "wallet/walletdb.h" // for BackupWallet +#include <qt/walletmodel.h> + +#include <qt/addresstablemodel.h> +#include <consensus/validation.h> +#include <qt/guiconstants.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/paymentserver.h> +#include <qt/recentrequeststablemodel.h> +#include <qt/sendcoinsdialog.h> +#include <qt/transactiontablemodel.h> + +#include <base58.h> +#include <chain.h> +#include <keystore.h> +#include <validation.h> +#include <net.h> // for g_connman +#include <policy/fees.h> +#include <policy/rbf.h> +#include <sync.h> +#include <ui_interface.h> +#include <util.h> // for GetBoolArg +#include <wallet/coincontrol.h> +#include <wallet/feebumper.h> +#include <wallet/wallet.h> +#include <wallet/walletdb.h> // for BackupWallet #include <stdint.h> @@ -659,45 +659,39 @@ bool WalletModel::abandonTransaction(uint256 hash) const bool WalletModel::transactionCanBeBumped(uint256 hash) const { - LOCK2(cs_main, wallet->cs_wallet); - const CWalletTx *wtx = wallet->GetWalletTx(hash); - return wtx && SignalsOptInRBF(*(wtx->tx)) && !wtx->mapValue.count("replaced_by_txid"); + return feebumper::TransactionCanBeBumped(wallet, hash); } bool WalletModel::bumpFee(uint256 hash) { - std::unique_ptr<CFeeBumper> feeBump; - { - CCoinControl coin_control; - coin_control.signalRbf = true; - LOCK2(cs_main, wallet->cs_wallet); - feeBump.reset(new CFeeBumper(wallet, hash, coin_control, 0)); - } - if (feeBump->getResult() != BumpFeeResult::OK) - { + CCoinControl coin_control; + coin_control.signalRbf = true; + std::vector<std::string> errors; + CAmount old_fee; + CAmount new_fee; + CMutableTransaction mtx; + if (feebumper::CreateTransaction(wallet, hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx) != feebumper::Result::OK) { QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" + - (feeBump->getErrors().size() ? QString::fromStdString(feeBump->getErrors()[0]) : "") +")"); + (errors.size() ? QString::fromStdString(errors[0]) : "") +")"); return false; } // allow a user based fee verification QString questionString = tr("Do you want to increase the fee?"); questionString.append("<br />"); - CAmount oldFee = feeBump->getOldFee(); - CAmount newFee = feeBump->getNewFee(); questionString.append("<table style=\"text-align: left;\">"); questionString.append("<tr><td>"); questionString.append(tr("Current fee:")); questionString.append("</td><td>"); - questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), oldFee)); + questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), old_fee)); questionString.append("</td></tr><tr><td>"); questionString.append(tr("Increase:")); questionString.append("</td><td>"); - questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee - oldFee)); + questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), new_fee - old_fee)); questionString.append("</td></tr><tr><td>"); questionString.append(tr("New fee:")); questionString.append("</td><td>"); - questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee)); + questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), new_fee)); questionString.append("</td></tr></table>"); SendConfirmationDialog confirmationDialog(tr("Confirm fee bump"), questionString); confirmationDialog.exec(); @@ -715,23 +709,15 @@ bool WalletModel::bumpFee(uint256 hash) } // sign bumped transaction - bool res = false; - { - LOCK2(cs_main, wallet->cs_wallet); - res = feeBump->signTransaction(wallet); - } - if (!res) { + if (!feebumper::SignTransaction(wallet, mtx)) { QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction.")); return false; } // commit the bumped transaction - { - LOCK2(cs_main, wallet->cs_wallet); - res = feeBump->commit(wallet); - } - if(!res) { + uint256 txid; + if (feebumper::CommitTransaction(wallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" + - QString::fromStdString(feeBump->getErrors()[0])+")"); + QString::fromStdString(errors[0])+")"); return false; } return true; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 05733f8272..028146c187 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -5,10 +5,10 @@ #ifndef BITCOIN_QT_WALLETMODEL_H #define BITCOIN_QT_WALLETMODEL_H -#include "paymentrequestplus.h" -#include "walletmodeltransaction.h" +#include <qt/paymentrequestplus.h> +#include <qt/walletmodeltransaction.h> -#include "support/allocators/secure.h" +#include <support/allocators/secure.h> #include <map> #include <vector> diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index a2290535c7..2188b39b92 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -2,15 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "walletmodeltransaction.h" +#include <qt/walletmodeltransaction.h> -#include "policy/policy.h" -#include "wallet/wallet.h" +#include <policy/policy.h> +#include <wallet/wallet.h> WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) : recipients(_recipients), walletTransaction(0), - keyChange(0), fee(0) { walletTransaction = new CWalletTx(); @@ -18,7 +17,6 @@ WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> & WalletModelTransaction::~WalletModelTransaction() { - delete keyChange; delete walletTransaction; } @@ -91,10 +89,10 @@ CAmount WalletModelTransaction::getTotalTransactionAmount() const void WalletModelTransaction::newPossibleKeyChange(CWallet *wallet) { - keyChange = new CReserveKey(wallet); + keyChange.reset(new CReserveKey(wallet)); } CReserveKey *WalletModelTransaction::getPossibleKeyChange() { - return keyChange; + return keyChange.get(); } diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index d7ecd7aa8c..519cf9df99 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_WALLETMODELTRANSACTION_H #define BITCOIN_QT_WALLETMODELTRANSACTION_H -#include "walletmodel.h" +#include <qt/walletmodel.h> #include <QObject> @@ -40,7 +40,7 @@ public: private: QList<SendCoinsRecipient> recipients; CWalletTx *walletTransaction; - CReserveKey *keyChange; + std::unique_ptr<CReserveKey> keyChange; CAmount fee; }; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index a56a40037f..a589fad9bd 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -2,24 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "walletview.h" - -#include "addressbookpage.h" -#include "askpassphrasedialog.h" -#include "bitcoingui.h" -#include "clientmodel.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "overviewpage.h" -#include "platformstyle.h" -#include "receivecoinsdialog.h" -#include "sendcoinsdialog.h" -#include "signverifymessagedialog.h" -#include "transactiontablemodel.h" -#include "transactionview.h" -#include "walletmodel.h" - -#include "ui_interface.h" +#include <qt/walletview.h> + +#include <qt/addressbookpage.h> +#include <qt/askpassphrasedialog.h> +#include <qt/bitcoingui.h> +#include <qt/clientmodel.h> +#include <qt/guiutil.h> +#include <qt/optionsmodel.h> +#include <qt/overviewpage.h> +#include <qt/platformstyle.h> +#include <qt/receivecoinsdialog.h> +#include <qt/sendcoinsdialog.h> +#include <qt/signverifymessagedialog.h> +#include <qt/transactiontablemodel.h> +#include <qt/transactionview.h> +#include <qt/walletmodel.h> + +#include <ui_interface.h> #include <QAction> #include <QActionGroup> diff --git a/src/qt/walletview.h b/src/qt/walletview.h index c1f8422f0c..4c90874135 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_QT_WALLETVIEW_H #define BITCOIN_QT_WALLETVIEW_H -#include "amount.h" +#include <amount.h> #include <QStackedWidget> diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index d78d9a2358..aa6c273431 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "winshutdownmonitor.h" +#include <qt/winshutdownmonitor.h> #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 -#include "init.h" -#include "util.h" +#include <init.h> +#include <util.h> #include <windows.h> diff --git a/src/random.cpp b/src/random.cpp index 7e0e94439e..3075a77182 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -3,16 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "random.h" +#include <random.h> -#include "crypto/sha512.h" -#include "support/cleanse.h" +#include <crypto/sha512.h> +#include <support/cleanse.h> #ifdef WIN32 -#include "compat.h" // for Windows API +#include <compat.h> // for Windows API #include <wincrypt.h> #endif -#include "util.h" // for LogPrint() -#include "utilstrencodings.h" // for GetTime() +#include <util.h> // for LogPrint() +#include <utilstrencodings.h> // for GetTime() #include <stdlib.h> #include <limits> diff --git a/src/random.h b/src/random.h index 413adbd464..a984545467 100644 --- a/src/random.h +++ b/src/random.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H -#include "crypto/chacha20.h" -#include "crypto/common.h" -#include "uint256.h" +#include <crypto/chacha20.h> +#include <crypto/common.h> +#include <uint256.h> #include <stdint.h> diff --git a/src/rest.cpp b/src/rest.cpp index b1fc96bdf5..86ee7804a3 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,20 +3,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" -#include "chainparams.h" -#include "core_io.h" -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "validation.h" -#include "httpserver.h" -#include "rpc/blockchain.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "txmempool.h" -#include "utilstrencodings.h" -#include "version.h" +#include <chain.h> +#include <chainparams.h> +#include <core_io.h> +#include <primitives/block.h> +#include <primitives/transaction.h> +#include <validation.h> +#include <httpserver.h> +#include <rpc/blockchain.h> +#include <rpc/server.h> +#include <streams.h> +#include <sync.h> +#include <txmempool.h> +#include <utilstrencodings.h> +#include <version.h> #include <boost/algorithm/string.hpp> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8d01d8ba9c..b7895b86f7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -3,28 +3,28 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/blockchain.h" - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "coins.h" -#include "consensus/validation.h" -#include "validation.h" -#include "core_io.h" -#include "policy/feerate.h" -#include "policy/policy.h" -#include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "txdb.h" -#include "txmempool.h" -#include "util.h" -#include "utilstrencodings.h" -#include "hash.h" -#include "warnings.h" +#include <rpc/blockchain.h> + +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#include <coins.h> +#include <consensus/validation.h> +#include <validation.h> +#include <core_io.h> +#include <policy/feerate.h> +#include <policy/policy.h> +#include <primitives/transaction.h> +#include <rpc/server.h> +#include <streams.h> +#include <sync.h> +#include <txdb.h> +#include <txmempool.h> +#include <util.h> +#include <utilstrencodings.h> +#include <hash.h> +#include <warnings.h> #include <stdint.h> @@ -928,7 +928,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) CCoinsStats stats; FlushStateToDisk(); - if (GetUTXOStats(pcoinsdbview, stats)) { + if (GetUTXOStats(pcoinsdbview.get(), stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); @@ -996,7 +996,7 @@ UniValue gettxout(const JSONRPCRequest& request) Coin coin; if (fMempool) { LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); + CCoinsViewMemPool view(pcoinsTip.get(), mempool); if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { return NullUniValue; } @@ -1048,7 +1048,7 @@ UniValue verifychain(const JSONRPCRequest& request) if (!request.params[1].isNull()) nCheckDepth = request.params[1].get_int(); - return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(Params(), pcoinsTip.get(), nCheckLevel, nCheckDepth); } /** Implementation of IsSuperMajority with better feedback */ @@ -1113,13 +1113,13 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } -void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { // Deployments with timeout value of 0 are hidden. // A timeout value of 0 guarantees a softfork will never be activated. // This is used when softfork codes are merged without specifying the deployment schedule. if (consensusParams.vDeployments[id].nTimeout > 0) - bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); + bip9_softforks.push_back(Pair(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id))); } UniValue getblockchaininfo(const JSONRPCRequest& request) @@ -1130,45 +1130,46 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) "Returns an object containing various state info regarding blockchain processing.\n" "\nResult:\n" "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" + " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" - " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" + " \"initialblockdownload\": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.\n" + " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" + " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" " \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n" - " \"softforks\": [ (array) status of softforks in progress\n" + " \"softforks\": [ (array) status of softforks in progress\n" " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" " },\n" " }, ...\n" " ],\n" - " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\": xx, (numeric) height of the first block to which the status applies\n" - " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" - " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" - " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" - " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" - " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" - " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" + " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" + " \"xxxx\" : { (string) name of the softfork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" + " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " \"since\": xx, (numeric) height of the first block to which the status applies\n" + " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" + " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" + " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" + " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" + " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" + " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" " }\n" " }\n" " }\n" - " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" + " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -1185,6 +1186,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast())); obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()))); + obj.push_back(Pair("initialblockdownload", IsInitialBlockDownload())); obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); obj.push_back(Pair("pruned", fPruneMode)); @@ -1212,8 +1214,9 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); - BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); + for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) { + BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos)); + } obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 721f363aef..f2fa114313 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -3,15 +3,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/client.h" -#include "rpc/protocol.h" -#include "util.h" +#include <rpc/client.h> +#include <rpc/protocol.h> +#include <util.h> #include <set> #include <stdint.h> -#include <univalue.h> - class CRPCConvertParam { public: diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 0ba0e968a7..d003be4954 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -3,34 +3,32 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "consensus/consensus.h" -#include "consensus/params.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "init.h" -#include "validation.h" -#include "miner.h" -#include "net.h" -#include "policy/fees.h" -#include "pow.h" -#include "rpc/blockchain.h" -#include "rpc/mining.h" -#include "rpc/server.h" -#include "txmempool.h" -#include "util.h" -#include "utilstrencodings.h" -#include "validationinterface.h" -#include "warnings.h" +#include <base58.h> +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <consensus/consensus.h> +#include <consensus/params.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <init.h> +#include <validation.h> +#include <miner.h> +#include <net.h> +#include <policy/fees.h> +#include <pow.h> +#include <rpc/blockchain.h> +#include <rpc/mining.h> +#include <rpc/server.h> +#include <txmempool.h> +#include <util.h> +#include <utilstrencodings.h> +#include <validationinterface.h> +#include <warnings.h> #include <memory> #include <stdint.h> -#include <univalue.h> - unsigned int ParseConfirmTarget(const UniValue& value) { int target = value.get_int(); diff --git a/src/rpc/mining.h b/src/rpc/mining.h index 868d7002b5..8d46273159 100644 --- a/src/rpc/mining.h +++ b/src/rpc/mining.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_RPC_MINING_H #define BITCOIN_RPC_MINING_H -#include "script/script.h" +#include <script/script.h> #include <univalue.h> diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index d042fa31d5..327af2e237 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -3,27 +3,27 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "chain.h" -#include "clientversion.h" -#include "core_io.h" -#include "crypto/ripemd160.h" -#include "init.h" -#include "validation.h" -#include "httpserver.h" -#include "net.h" -#include "netbase.h" -#include "rpc/blockchain.h" -#include "rpc/server.h" -#include "timedata.h" -#include "util.h" -#include "utilstrencodings.h" +#include <base58.h> +#include <chain.h> +#include <clientversion.h> +#include <core_io.h> +#include <crypto/ripemd160.h> +#include <init.h> +#include <validation.h> +#include <httpserver.h> +#include <net.h> +#include <netbase.h> +#include <rpc/blockchain.h> +#include <rpc/server.h> +#include <timedata.h> +#include <util.h> +#include <utilstrencodings.h> #ifdef ENABLE_WALLET -#include "wallet/rpcwallet.h" -#include "wallet/wallet.h" -#include "wallet/walletdb.h" +#include <wallet/rpcwallet.h> +#include <wallet/wallet.h> +#include <wallet/walletdb.h> #endif -#include "warnings.h" +#include <warnings.h> #include <stdint.h> #ifdef HAVE_MALLOC_INFO @@ -187,17 +187,24 @@ UniValue validateaddress(const JSONRPCRequest& request) ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { - const auto& meta = pwallet->mapKeyMetadata; - const CKeyID *keyID = boost::get<CKeyID>(&dest); - auto it = keyID ? meta.find(*keyID) : meta.end(); - if (it == meta.end()) { - it = meta.find(CScriptID(scriptPubKey)); + const CKeyMetadata* meta = nullptr; + if (const CKeyID* key_id = boost::get<CKeyID>(&dest)) { + auto it = pwallet->mapKeyMetadata.find(*key_id); + if (it != pwallet->mapKeyMetadata.end()) { + meta = &it->second; + } + } + if (!meta) { + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != pwallet->m_script_metadata.end()) { + meta = &it->second; + } } - if (it != meta.end()) { - ret.push_back(Pair("timestamp", it->second.nCreateTime)); - if (!it->second.hdKeypath.empty()) { - ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); - ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); + if (meta) { + ret.push_back(Pair("timestamp", meta->nCreateTime)); + if (!meta->hdKeypath.empty()) { + ret.push_back(Pair("hdkeypath", meta->hdKeypath)); + ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex())); } } } @@ -533,6 +540,9 @@ uint32_t getCategoryMask(UniValue cats) { if (!GetLogCategory(&flag, &cat)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); } + if (flag == BCLog::NONE) { + return 0; + } mask |= flag; } return mask; @@ -542,16 +552,32 @@ UniValue logging(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) { throw std::runtime_error( - "logging [include,...] <exclude>\n" + "logging ( <include> <exclude> )\n" "Gets and sets the logging configuration.\n" - "When called without an argument, returns the list of categories that are currently being debug logged.\n" - "When called with arguments, adds or removes categories from debug logging.\n" + "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" + "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" + "The arguments are evaluated in order \"include\", \"exclude\".\n" + "If an item is both included and excluded, it will thus end up being excluded.\n" "The valid logging categories are: " + ListLogCategories() + "\n" - "libevent logging is configured on startup and cannot be modified by this RPC during runtime." - "Arguments:\n" - "1. \"include\" (array of strings) add debug logging for these categories.\n" - "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" - "\nResult: <categories> (string): a list of the logging categories that are active.\n" + "In addition, the following are available as category names with special meanings:\n" + " - \"all\", \"1\" : represent all logging categories.\n" + " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" + "\nArguments:\n" + "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "\nResult:\n" + "{ (json object where keys are the logging categories, and values indicates its status\n" + " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n" + " ...\n" + "}\n" "\nExamples:\n" + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 8fb8328c5e..9de249855c 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -2,24 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/server.h" - -#include "chainparams.h" -#include "clientversion.h" -#include "core_io.h" -#include "validation.h" -#include "net.h" -#include "net_processing.h" -#include "netbase.h" -#include "policy/policy.h" -#include "protocol.h" -#include "sync.h" -#include "timedata.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" -#include "version.h" -#include "warnings.h" +#include <rpc/server.h> + +#include <chainparams.h> +#include <clientversion.h> +#include <core_io.h> +#include <validation.h> +#include <net.h> +#include <net_processing.h> +#include <netbase.h> +#include <policy/policy.h> +#include <rpc/protocol.h> +#include <sync.h> +#include <timedata.h> +#include <ui_interface.h> +#include <util.h> +#include <utilstrencodings.h> +#include <version.h> +#include <warnings.h> #include <univalue.h> @@ -571,11 +571,11 @@ UniValue listbanned(const JSONRPCRequest& request) g_connman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); - for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) + for (const auto& entry : banMap) { - CBanEntry banEntry = (*it).second; + const CBanEntry& banEntry = entry.second; UniValue rec(UniValue::VOBJ); - rec.push_back(Pair("address", (*it).first.ToString())); + rec.push_back(Pair("address", entry.first.ToString())); rec.push_back(Pair("banned_until", banEntry.nBanUntil)); rec.push_back(Pair("ban_created", banEntry.nCreateTime)); rec.push_back(Pair("ban_reason", banEntry.banReasonToString())); diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 1f4ae75b18..d999a08d74 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -3,16 +3,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/protocol.h" +#include <rpc/protocol.h> -#include "random.h" -#include "tinyformat.h" -#include "util.h" -#include "utilstrencodings.h" -#include "utiltime.h" -#include "version.h" +#include <random.h> +#include <tinyformat.h> +#include <util.h> +#include <utilstrencodings.h> +#include <utiltime.h> +#include <version.h> -#include <stdint.h> #include <fstream> /** diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index cb668f3db9..4b9bd41994 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H -#include "fs.h" +#include <fs.h> #include <list> #include <map> diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d860dbc244..018c255325 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -3,33 +3,35 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "chain.h" -#include "coins.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "init.h" -#include "keystore.h" -#include "validation.h" -#include "merkleblock.h" -#include "net.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "primitives/transaction.h" -#include "rpc/safemode.h" -#include "rpc/server.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" -#include "txmempool.h" -#include "uint256.h" -#include "utilstrencodings.h" +#include <base58.h> +#include <chain.h> +#include <coins.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <init.h> +#include <keystore.h> +#include <validation.h> +#include <validationinterface.h> +#include <merkleblock.h> +#include <net.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <primitives/transaction.h> +#include <rpc/safemode.h> +#include <rpc/server.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/sign.h> +#include <script/standard.h> +#include <txmempool.h> +#include <uint256.h> +#include <utilstrencodings.h> #ifdef ENABLE_WALLET -#include "wallet/rpcwallet.h" -#include "wallet/wallet.h" +#include <wallet/rpcwallet.h> +#include <wallet/wallet.h> #endif +#include <future> #include <stdint.h> #include <univalue.h> @@ -62,12 +64,15 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue getrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( - "getrawtransaction \"txid\" ( verbose )\n" + "getrawtransaction \"txid\" ( verbose \"blockhash\" )\n" "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n" - "enabled, it also works for blockchain transactions.\n" + "enabled, it also works for blockchain transactions. If the block which contains the transaction\n" + "is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n" + "provided, only that block will be searched and if the transaction is in the mempool or other\n" + "blocks, or if this node does not have the given block available, the transaction will not be found.\n" "DEPRECATED: for now, it also works for transactions with unspent outputs.\n" "\nReturn the raw transaction data.\n" @@ -76,13 +81,15 @@ UniValue getrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" - "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "3. \"blockhash\" (string, optional) The block in which to look for the transaction\n" "\nResult (if verbose is not set or set to false):\n" "\"data\" (string) The serialized, hex-encoded data for 'txid'\n" "\nResult (if verbose is set to true):\n" "{\n" + " \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n" " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" @@ -130,42 +137,56 @@ UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true") + HelpExampleRpc("getrawtransaction", "\"mytxid\", true") + + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") ); LOCK(cs_main); + bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); + CBlockIndex* blockindex = nullptr; // Accept either a bool (true) or a num (>=1) to indicate verbose output. bool fVerbose = false; if (!request.params[1].isNull()) { - if (request.params[1].isNum()) { - if (request.params[1].get_int() != 0) { - fVerbose = true; - } - } - else if(request.params[1].isBool()) { - if(request.params[1].isTrue()) { - fVerbose = true; - } - } - else { - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean."); + fVerbose = request.params[1].isNum() ? (request.params[1].get_int() != 0) : request.params[1].get_bool(); + } + + if (!request.params[2].isNull()) { + uint256 blockhash = ParseHashV(request.params[2], "parameter 3"); + BlockMap::iterator it = mapBlockIndex.find(blockhash); + if (it == mapBlockIndex.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found"); } + blockindex = it->second; + in_active_chain = chainActive.Contains(blockindex); } CTransactionRef tx; - uint256 hashBlock; - if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string(fTxIndex ? "No such mempool or blockchain transaction" - : "No such mempool transaction. Use -txindex to enable blockchain transaction queries") + - ". Use gettransaction for wallet transactions."); + uint256 hash_block; + if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) { + std::string errmsg; + if (blockindex) { + if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) { + throw JSONRPCError(RPC_MISC_ERROR, "Block not available"); + } + errmsg = "No such transaction found in the provided block"; + } else { + errmsg = fTxIndex + ? "No such mempool or blockchain transaction" + : "No such mempool transaction. Use -txindex to enable blockchain transaction queries"; + } + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions."); + } - if (!fVerbose) + if (!fVerbose) { return EncodeHexTx(*tx, RPCSerializationFlags()); + } UniValue result(UniValue::VOBJ); - TxToJSON(*tx, hashBlock, result); + if (blockindex) result.push_back(Pair("in_active_chain", in_active_chain)); + TxToJSON(*tx, hash_block, result); return result; } @@ -917,7 +938,9 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) ); ObserveSafeMode(); - LOCK(cs_main); + + std::promise<void> promise; + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); // parse hex string from parameter @@ -931,6 +954,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) if (!request.params[1].isNull() && request.params[1].get_bool()) nMaxRawTxFee = 0; + { // cs_main scope + LOCK(cs_main); CCoinsViewCache &view = *pcoinsTip; bool fHaveChain = false; for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) { @@ -952,10 +977,28 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) } throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason()); } + } else { + // If wallet is enabled, ensure that the wallet has been made aware + // of the new transaction prior to returning. This prevents a race + // where a user might call sendrawtransaction with a transaction + // to/from their wallet, immediately call some wallet RPC, and get + // a stale result because callbacks have not yet been processed. + CallFunctionInValidationInterfaceQueue([&promise] { + promise.set_value(); + }); } } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); + } else { + // Make sure we don't block forever if re-sending + // a transaction already in mempool. + promise.set_value(); } + + } // cs_main + + promise.get_future().wait(); + if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -964,13 +1007,14 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) { pnode->PushInventory(inv); }); + return hashTx.GetHex(); } static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- - { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose"} }, + { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} }, { "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} }, { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} }, { "rawtransactions", "decodescript", &decodescript, {"hexstring"} }, diff --git a/src/rpc/safemode.cpp b/src/rpc/safemode.cpp index 24770ad47f..9f3a9d30b8 100644 --- a/src/rpc/safemode.cpp +++ b/src/rpc/safemode.cpp @@ -1,8 +1,8 @@ -#include "safemode.h" +#include <rpc/safemode.h> -#include "rpc/protocol.h" -#include "util.h" -#include "warnings.h" +#include <rpc/protocol.h> +#include <util.h> +#include <warnings.h> void ObserveSafeMode() { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 39bcfc6903..2e7e0ba474 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -3,18 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/server.h" +#include <rpc/server.h> -#include "base58.h" -#include "fs.h" -#include "init.h" -#include "random.h" -#include "sync.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" - -#include <univalue.h> +#include <base58.h> +#include <fs.h> +#include <init.h> +#include <random.h> +#include <sync.h> +#include <ui_interface.h> +#include <util.h> +#include <utilstrencodings.h> #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> @@ -160,8 +158,8 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& std::set<rpcfn_type> setDone; std::vector<std::pair<std::string, const CRPCCommand*> > vCommands; - for (std::map<std::string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) - vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second)); + for (const auto& entry : mapCommands) + vCommands.push_back(make_pair(entry.second->category + entry.first, entry.second)); sort(vCommands.begin(), vCommands.end()); JSONRPCRequest jreq(helpreq); diff --git a/src/rpc/server.h b/src/rpc/server.h index 74c4a9e801..cd201bf316 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_RPCSERVER_H #define BITCOIN_RPCSERVER_H -#include "amount.h" -#include "rpc/protocol.h" -#include "uint256.h" +#include <amount.h> +#include <rpc/protocol.h> +#include <uint256.h> #include <list> #include <map> diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 4edb2c6d9b..260f6fa60e 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "scheduler.h" +#include <scheduler.h> -#include "random.h" -#include "reverselock.h" +#include <random.h> +#include <reverselock.h> #include <assert.h> #include <boost/bind.hpp> diff --git a/src/scheduler.h b/src/scheduler.h index db93bcb21e..b99f165343 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -14,7 +14,7 @@ #include <boost/thread.hpp> #include <map> -#include "sync.h" +#include <sync.h> // // Simple class for background tasks that should be run diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 03128917fd..77edc85b8c 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bitcoinconsensus.h" +#include <script/bitcoinconsensus.h> -#include "primitives/transaction.h" -#include "pubkey.h" -#include "script/interpreter.h" -#include "version.h" +#include <primitives/transaction.h> +#include <pubkey.h> +#include <script/interpreter.h> +#include <version.h> namespace { diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h index 33bf80e5a7..f09cd59b92 100644 --- a/src/script/bitcoinconsensus.h +++ b/src/script/bitcoinconsensus.h @@ -9,7 +9,7 @@ #include <stdint.h> #if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #if defined(_WIN32) #if defined(DLL_EXPORT) #if defined(HAVE_FUNC_ATTRIBUTE_DLLEXPORT) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 2f7b8e3a03..3c3f92fe46 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -3,15 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "interpreter.h" +#include <script/interpreter.h> -#include "primitives/transaction.h" -#include "crypto/ripemd160.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "pubkey.h" -#include "script/script.h" -#include "uint256.h" +#include <crypto/ripemd160.h> +#include <crypto/sha1.h> +#include <crypto/sha256.h> +#include <pubkey.h> +#include <script/script.h> +#include <uint256.h> typedef std::vector<unsigned char> valtype; @@ -349,9 +348,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& { if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { // not enabled; treat as a NOP2 - if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { - return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); - } break; } @@ -391,9 +387,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& { if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { // not enabled; treat as a NOP3 - if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { - return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); - } break; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 1cb9cc7899..83a96739b1 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_SCRIPT_INTERPRETER_H #define BITCOIN_SCRIPT_INTERPRETER_H -#include "script_error.h" -#include "primitives/transaction.h" +#include <script/script_error.h> +#include <primitives/transaction.h> #include <vector> #include <stdint.h> @@ -27,37 +27,40 @@ enum SIGHASH_ANYONECANPAY = 0x80, }; -/** Script verification flags */ +/** Script verification flags. + * + * All flags are intended to be soft forks: the set of acceptable scripts under + * flags (A | B) is a subset of the acceptable scripts under flag (A). + */ enum { SCRIPT_VERIFY_NONE = 0, - // Evaluate P2SH subscripts (softfork safe, BIP16). + // Evaluate P2SH subscripts (BIP16). SCRIPT_VERIFY_P2SH = (1U << 0), // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. - // (softfork safe, but not used or intended as a consensus rule). + // (not used or intended as a consensus rule). SCRIPT_VERIFY_STRICTENC = (1U << 1), - // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1) + // Passing a non-strict-DER signature to a checksig operation causes script failure (BIP62 rule 1) SCRIPT_VERIFY_DERSIG = (1U << 2), // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure - // (softfork safe, BIP62 rule 5). + // (BIP62 rule 5). SCRIPT_VERIFY_LOW_S = (1U << 3), - // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7). + // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (BIP62 rule 7). SCRIPT_VERIFY_NULLDUMMY = (1U << 4), - // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2). + // Using a non-push operator in the scriptSig causes script failure (BIP62 rule 2). SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5), // Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct // pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating // any other push causes the script to fail (BIP62 rule 3). // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4). - // (softfork safe) SCRIPT_VERIFY_MINIMALDATA = (1U << 6), // Discourage use of NOPs reserved for upgrades (NOP1-10) @@ -68,12 +71,14 @@ enum // discouraged NOPs fails the script. This verification flag will never be // a mandatory flag applied to scripts in a block. NOPs that are not // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected. + // NOPs that have associated forks to give them new meaning (CLTV, CSV) + // are not subject to this rule. SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7), // Require that only a single stack element remains after evaluation. This changes the success criterion from // "At least one stack element must remain, and when interpreted as a boolean, it must be true" to // "Exactly one stack element must remain, and when interpreted as a boolean, it must be true". - // (softfork safe, BIP62 rule 6) + // (BIP62 rule 6) // Note: CLEANSTACK should never be used without P2SH or WITNESS. SCRIPT_VERIFY_CLEANSTACK = (1U << 8), diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 6b68f0679e..5849f55651 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -3,13 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "ismine.h" +#include <script/ismine.h> -#include "key.h" -#include "keystore.h" -#include "script/script.h" -#include "script/standard.h" -#include "script/sign.h" +#include <key.h> +#include <keystore.h> +#include <script/script.h> +#include <script/sign.h> typedef std::vector<unsigned char> valtype; diff --git a/src/script/ismine.h b/src/script/ismine.h index 1aa5937b34..77ffa82432 100644 --- a/src/script/ismine.h +++ b/src/script/ismine.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_SCRIPT_ISMINE_H #define BITCOIN_SCRIPT_ISMINE_H -#include "script/standard.h" +#include <script/standard.h> #include <stdint.h> diff --git a/src/script/script.cpp b/src/script/script.cpp index a10b619f7d..a7bfb170eb 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "script.h" +#include <script/script.h> -#include "tinyformat.h" -#include "utilstrencodings.h" +#include <tinyformat.h> +#include <utilstrencodings.h> const char* GetOpName(opcodetype opcode) { diff --git a/src/script/script.h b/src/script/script.h index 2a92060543..263db62edf 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H -#include "crypto/common.h" -#include "prevector.h" -#include "serialize.h" +#include <crypto/common.h> +#include <prevector.h> +#include <serialize.h> #include <assert.h> #include <climits> diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 6c590f53e3..32aa639ac4 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "script_error.h" +#include <script/script_error.h> const char* ScriptErrorString(const ScriptError serror) { diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 4cc7afa2f5..88d1d67559 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -3,15 +3,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sigcache.h" +#include <script/sigcache.h> -#include "memusage.h" -#include "pubkey.h" -#include "random.h" -#include "uint256.h" -#include "util.h" +#include <memusage.h> +#include <pubkey.h> +#include <random.h> +#include <uint256.h> +#include <util.h> -#include "cuckoocache.h" +#include <cuckoocache.h> #include <boost/thread.hpp> namespace { diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 5832b264b3..1019061fbb 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_SCRIPT_SIGCACHE_H #define BITCOIN_SCRIPT_SIGCACHE_H -#include "script/interpreter.h" +#include <script/interpreter.h> #include <vector> diff --git a/src/script/sign.cpp b/src/script/sign.cpp index ac58b690a2..117a4d8a52 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -3,14 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "script/sign.h" - -#include "key.h" -#include "keystore.h" -#include "policy/policy.h" -#include "primitives/transaction.h" -#include "script/standard.h" -#include "uint256.h" +#include <script/sign.h> + +#include <key.h> +#include <keystore.h> +#include <policy/policy.h> +#include <primitives/transaction.h> +#include <script/standard.h> +#include <uint256.h> typedef std::vector<unsigned char> valtype; diff --git a/src/script/sign.h b/src/script/sign.h index a0d8ee4ff9..400c0c0865 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_SCRIPT_SIGN_H #define BITCOIN_SCRIPT_SIGN_H -#include "script/interpreter.h" +#include <script/interpreter.h> class CKeyID; class CKeyStore; diff --git a/src/script/standard.cpp b/src/script/standard.cpp index f57f1f61b4..b7b33fade6 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "script/standard.h" +#include <script/standard.h> -#include "pubkey.h" -#include "script/script.h" -#include "util.h" -#include "utilstrencodings.h" +#include <pubkey.h> +#include <script/script.h> +#include <util.h> +#include <utilstrencodings.h> typedef std::vector<unsigned char> valtype; diff --git a/src/script/standard.h b/src/script/standard.h index fa07ea88c1..3eeeabdc15 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_SCRIPT_STANDARD_H #define BITCOIN_SCRIPT_STANDARD_H -#include "script/interpreter.h" -#include "uint256.h" +#include <script/interpreter.h> +#include <uint256.h> #include <boost/variant.hpp> diff --git a/src/serialize.h b/src/serialize.h index eeb05fa76c..02d3e4f7c6 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_SERIALIZE_H #define BITCOIN_SERIALIZE_H -#include "compat/endian.h" +#include <compat/endian.h> #include <algorithm> #include <assert.h> @@ -21,7 +21,7 @@ #include <utility> #include <vector> -#include "prevector.h" +#include <prevector.h> static const unsigned int MAX_SIZE = 0x02000000; @@ -732,8 +732,8 @@ template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m) { WriteCompactSize(os, m.size()); - for (typename std::map<K, T, Pred, A>::const_iterator mi = m.begin(); mi != m.end(); ++mi) - Serialize(os, (*mi)); + for (const auto& entry : m) + Serialize(os, entry); } template<typename Stream, typename K, typename T, typename Pred, typename A> diff --git a/src/streams.h b/src/streams.h index 5dbeaac9a5..a212691f6d 100644 --- a/src/streams.h +++ b/src/streams.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_STREAMS_H #define BITCOIN_STREAMS_H -#include "support/allocators/zeroafterfree.h" -#include "serialize.h" +#include <support/allocators/zeroafterfree.h> +#include <serialize.h> #include <algorithm> #include <assert.h> diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index 39347c73bb..7cd031bfe8 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -6,8 +6,8 @@ #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H -#include "support/lockedpool.h" -#include "support/cleanse.h" +#include <support/lockedpool.h> +#include <support/cleanse.h> #include <string> diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h index 618874ceee..23ef96c13f 100644 --- a/src/support/allocators/zeroafterfree.h +++ b/src/support/allocators/zeroafterfree.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_SUPPORT_ALLOCATORS_ZEROAFTERFREE_H #define BITCOIN_SUPPORT_ALLOCATORS_ZEROAFTERFREE_H -#include "support/cleanse.h" +#include <support/cleanse.h> #include <memory> #include <vector> diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp index eb6e0a73a2..8d3c7369b4 100644 --- a/src/support/cleanse.cpp +++ b/src/support/cleanse.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "cleanse.h" +#include <support/cleanse.h> #include <cstring> diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index 2ead72185f..98e8694181 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "support/lockedpool.h" -#include "support/cleanse.h" +#include <support/lockedpool.h> +#include <support/cleanse.h> #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #ifdef WIN32 diff --git a/src/sync.cpp b/src/sync.cpp index 87024ccdf2..3f51383ea2 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -2,16 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sync.h" +#include <sync.h> -#include "util.h" -#include "utilstrencodings.h" +#include <set> +#include <util.h> +#include <utilstrencodings.h> #include <stdio.h> -#include <boost/thread.hpp> - #ifdef DEBUG_LOCKCONTENTION +#if !defined(HAVE_THREAD_LOCAL) +static_assert(false, "thread_local is not supported"); +#endif void PrintLockContention(const char* pszName, const char* pszFile, int nLine) { LogPrintf("LOCKCONTENTION: %s\n", pszName); @@ -45,8 +47,8 @@ struct CLockLocation { return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : ""); } - bool fTry; private: + bool fTry; std::string mutexName; std::string sourceFile; int sourceLine; @@ -67,10 +69,10 @@ struct LockData { LockOrders lockorders; InvLockOrders invlockorders; - boost::mutex dd_mutex; + std::mutex dd_mutex; } static lockdata; -boost::thread_specific_ptr<LockStack> lockstack; +static thread_local std::unique_ptr<LockStack> lockstack; static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2) { @@ -100,12 +102,12 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, static void push_lock(void* c, const CLockLocation& locklocation) { - if (lockstack.get() == nullptr) + if (!lockstack) lockstack.reset(new LockStack); - boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex); + std::lock_guard<std::mutex> lock(lockdata.dd_mutex); - (*lockstack).push_back(std::make_pair(c, locklocation)); + lockstack->push_back(std::make_pair(c, locklocation)); for (const std::pair<void*, CLockLocation> & i : (*lockstack)) { if (i.first == c) @@ -155,13 +157,23 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, abort(); } +void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) +{ + for (const std::pair<void*, CLockLocation>& i : *lockstack) { + if (i.first == cs) { + fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); + abort(); + } + } +} + void DeleteLock(void* cs) { if (!lockdata.available) { // We're already shutting down. return; } - boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex); + std::lock_guard<std::mutex> lock(lockdata.dd_mutex); std::pair<void*, void*> item = std::make_pair(cs, nullptr); LockOrders::iterator it = lockdata.lockorders.lower_bound(item); while (it != lockdata.lockorders.end() && it->first.first == cs) { diff --git a/src/sync.h b/src/sync.h index 20556af890..3af27c65d0 100644 --- a/src/sync.h +++ b/src/sync.h @@ -6,10 +6,8 @@ #ifndef BITCOIN_SYNC_H #define BITCOIN_SYNC_H -#include "threadsafety.h" +#include <threadsafety.h> -#include <boost/thread/condition_variable.hpp> -#include <boost/thread/mutex.hpp> #include <condition_variable> #include <thread> #include <mutex> @@ -77,14 +75,17 @@ void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs void LeaveCritical(); std::string LocksHeld(); void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); +void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); void DeleteLock(void* cs); #else void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} void static inline LeaveCritical() {} void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} +void static inline AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} void static inline DeleteLock(void* cs) {} #endif #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) +#define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs) /** * Wrapped mutex: supports recursive locking, but no waiting @@ -193,8 +194,8 @@ public: class CSemaphore { private: - boost::condition_variable condition; - boost::mutex mutex; + std::condition_variable condition; + std::mutex mutex; int value; public: @@ -202,16 +203,14 @@ public: void wait() { - boost::unique_lock<boost::mutex> lock(mutex); - while (value < 1) { - condition.wait(lock); - } + std::unique_lock<std::mutex> lock(mutex); + condition.wait(lock, [&]() { return value >= 1; }); value--; } bool try_wait() { - boost::unique_lock<boost::mutex> lock(mutex); + std::lock_guard<std::mutex> lock(mutex); if (value < 1) return false; value--; @@ -221,7 +220,7 @@ public: void post() { { - boost::unique_lock<boost::mutex> lock(mutex); + std::lock_guard<std::mutex> lock(mutex); value++; } condition.notify_one(); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index d1f9e63ecf..6be176a1ad 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -4,17 +4,17 @@ // Unit tests for denial-of-service detection/prevention code -#include "chainparams.h" -#include "keystore.h" -#include "net.h" -#include "net_processing.h" -#include "pow.h" -#include "script/sign.h" -#include "serialize.h" -#include "util.h" -#include "validation.h" - -#include "test/test_bitcoin.h" +#include <chainparams.h> +#include <keystore.h> +#include <net.h> +#include <net_processing.h> +#include <pow.h> +#include <script/sign.h> +#include <serialize.h> +#include <util.h> +#include <validation.h> + +#include <test/test_bitcoin.h> #include <stdint.h> @@ -66,11 +66,14 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) dummyNode1.fSuccessfullyConnected = true; // This test requires that we have a chain with non-zero work. + LOCK(cs_main); BOOST_CHECK(chainActive.Tip() != nullptr); BOOST_CHECK(chainActive.Tip()->nChainWork > 0); // Test starts here + LOCK(dummyNode1.cs_sendProcessing); peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders + LOCK(dummyNode1.cs_vSend); BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); dummyNode1.vSendMsg.clear(); @@ -183,7 +186,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning) peerLogic->InitializeNode(&dummyNode1); dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; - Misbehaving(dummyNode1.GetId(), 100); // Should get banned + { + LOCK(cs_main); + Misbehaving(dummyNode1.GetId(), 100); // Should get banned + } + LOCK(dummyNode1.cs_sendProcessing); peerLogic->SendMessages(&dummyNode1, interruptDummy); BOOST_CHECK(connman->IsBanned(addr1)); BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned @@ -194,11 +201,18 @@ BOOST_AUTO_TEST_CASE(DoS_banning) peerLogic->InitializeNode(&dummyNode2); dummyNode2.nVersion = 1; dummyNode2.fSuccessfullyConnected = true; - Misbehaving(dummyNode2.GetId(), 50); + { + LOCK(cs_main); + Misbehaving(dummyNode2.GetId(), 50); + } + LOCK(dummyNode2.cs_sendProcessing); peerLogic->SendMessages(&dummyNode2, interruptDummy); BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet... BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be - Misbehaving(dummyNode2.GetId(), 50); + { + LOCK(cs_main); + Misbehaving(dummyNode2.GetId(), 50); + } peerLogic->SendMessages(&dummyNode2, interruptDummy); BOOST_CHECK(connman->IsBanned(addr2)); @@ -219,13 +233,23 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) peerLogic->InitializeNode(&dummyNode1); dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; - Misbehaving(dummyNode1.GetId(), 100); + { + LOCK(cs_main); + Misbehaving(dummyNode1.GetId(), 100); + } + LOCK(dummyNode1.cs_sendProcessing); peerLogic->SendMessages(&dummyNode1, interruptDummy); BOOST_CHECK(!connman->IsBanned(addr1)); - Misbehaving(dummyNode1.GetId(), 10); + { + LOCK(cs_main); + Misbehaving(dummyNode1.GetId(), 10); + } peerLogic->SendMessages(&dummyNode1, interruptDummy); BOOST_CHECK(!connman->IsBanned(addr1)); - Misbehaving(dummyNode1.GetId(), 1); + { + LOCK(cs_main); + Misbehaving(dummyNode1.GetId(), 1); + } peerLogic->SendMessages(&dummyNode1, interruptDummy); BOOST_CHECK(connman->IsBanned(addr1)); gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); @@ -249,7 +273,11 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) dummyNode.nVersion = 1; dummyNode.fSuccessfullyConnected = true; - Misbehaving(dummyNode.GetId(), 100); + { + LOCK(cs_main); + Misbehaving(dummyNode.GetId(), 100); + } + LOCK(dummyNode.cs_sendProcessing); peerLogic->SendMessages(&dummyNode, interruptDummy); BOOST_CHECK(connman->IsBanned(addr)); @@ -266,6 +294,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) CTransactionRef RandomOrphan() { std::map<uint256, COrphanTx>::iterator it; + LOCK(cs_main); it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); @@ -335,6 +364,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i)); } + LOCK(cs_main); // Test EraseOrphansFor: for (NodeId i = 0; i < 3; i++) { diff --git a/src/test/README.md b/src/test/README.md index dbaa9c27f3..01da32109b 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -52,4 +52,4 @@ examine `uint256_tests.cpp`. For further reading, I found the following website to be helpful in explaining how the boost unit test framework works: -[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/). +[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://archive.is/dRBGf). diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 7be29c6d6b..609b1a05d3 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -1,14 +1,14 @@ // Copyright (c) 2012-2016 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 "addrman.h" -#include "test/test_bitcoin.h" +#include <addrman.h> +#include <test/test_bitcoin.h> #include <string> #include <boost/test/unit_test.hpp> -#include "hash.h" -#include "netbase.h" -#include "random.h" +#include <hash.h> +#include <netbase.h> +#include <random.h> class CAddrManTest : public CAddrMan { diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 4a533b5bf2..83fa3b76be 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" +#include <util.h> -#include "support/allocators/secure.h" -#include "test/test_bitcoin.h" +#include <support/allocators/secure.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 952cf901f0..7ebbd22c5d 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "amount.h" -#include "policy/feerate.h" -#include "test/test_bitcoin.h" +#include <amount.h> +#include <policy/feerate.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 2c98fbcfd6..eb3148a1de 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -8,11 +8,11 @@ #include <iomanip> #include <limits> #include <cmath> -#include "uint256.h" -#include "arith_uint256.h" +#include <uint256.h> +#include <arith_uint256.h> #include <string> -#include "version.h" -#include "test/test_bitcoin.h" +#include <version.h> +#include <test/test_bitcoin.h> BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 6422b3a88f..abf236b953 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 6bc6dd5187..3156cc53d0 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" - -#include "data/base58_encode_decode.json.h" -#include "data/base58_keys_invalid.json.h" -#include "data/base58_keys_valid.json.h" - -#include "key.h" -#include "script/script.h" -#include "test/test_bitcoin.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" +#include <base58.h> + +#include <test/data/base58_encode_decode.json.h> +#include <test/data/base58_keys_invalid.json.h> +#include <test/data/base58_keys_valid.json.h> + +#include <key.h> +#include <script/script.h> +#include <test/test_bitcoin.h> +#include <uint256.h> +#include <util.h> +#include <utilstrencodings.h> #include <univalue.h> diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index ccad94d946..46b3a04f35 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index ce4cddd64b..495290c8d9 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bech32.h" -#include "test/test_bitcoin.h" +#include <bech32.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index e123c26ad0..e3e727439b 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -4,12 +4,12 @@ #include <boost/test/unit_test.hpp> -#include "base58.h" -#include "key.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <base58.h> +#include <key.h> +#include <uint256.h> +#include <util.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <string> #include <vector> diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index f2d5b385d0..718b5bdfb9 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "blockencodings.h" -#include "consensus/merkle.h" -#include "chainparams.h" -#include "random.h" +#include <blockencodings.h> +#include <consensus/merkle.h> +#include <chainparams.h> +#include <random.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> @@ -62,6 +62,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2])); + LOCK(pool.cs); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); // Do a simple ShortTxIDs RT @@ -161,6 +162,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2])); + LOCK(pool.cs); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; @@ -227,6 +229,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest) CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(*block.vtx[1])); + LOCK(pool.cs); BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index eac2c102a6..fdd30be0b1 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -2,20 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bloom.h" - -#include "base58.h" -#include "clientversion.h" -#include "key.h" -#include "merkleblock.h" -#include "primitives/block.h" -#include "random.h" -#include "serialize.h" -#include "streams.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <bloom.h> + +#include <base58.h> +#include <clientversion.h> +#include <key.h> +#include <merkleblock.h> +#include <primitives/block.h> +#include <random.h> +#include <serialize.h> +#include <streams.h> +#include <uint256.h> +#include <util.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp index 7b3134d327..ab4f08b999 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "compat/byteswap.h" -#include "test/test_bitcoin.h" +#include <compat/byteswap.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 162c597c30..42f9dd0600 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" -#include "utiltime.h" -#include "validation.h" +#include <util.h> +#include <utiltime.h> +#include <validation.h> -#include "test/test_bitcoin.h" -#include "checkqueue.h" +#include <test/test_bitcoin.h> +#include <checkqueue.h> #include <boost/test/unit_test.hpp> #include <boost/thread.hpp> #include <atomic> @@ -18,7 +18,7 @@ #include <unordered_set> #include <memory> -#include "random.h" +#include <random.h> // BasicTestingSetup not sufficient because nScriptCheckThreads is not set // otherwise. diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index dc358bff95..ed556c07f4 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "coins.h" -#include "script/standard.h" -#include "uint256.h" -#include "undo.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" -#include "validation.h" -#include "consensus/validation.h" +#include <coins.h> +#include <script/standard.h> +#include <uint256.h> +#include <undo.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> +#include <validation.h> +#include <consensus/validation.h> #include <vector> #include <map> @@ -81,8 +81,8 @@ public: // Manually recompute the dynamic usage of the whole data, and compare it. size_t ret = memusage::DynamicUsage(cacheCoins); size_t count = 0; - for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { - ret += it->second.coin.DynamicMemoryUsage(); + for (const auto& entry : cacheCoins) { + ret += entry.second.coin.DynamicMemoryUsage(); ++count; } BOOST_CHECK_EQUAL(GetCacheSize(), count); @@ -189,15 +189,15 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // Once every 1000 iterations and at the end, verify the full cache. if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { - for (auto it = result.begin(); it != result.end(); it++) { - bool have = stack.back()->HaveCoin(it->first); - const Coin& coin = stack.back()->AccessCoin(it->first); + for (const auto& entry : result) { + bool have = stack.back()->HaveCoin(entry.first); + const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == it->second); + BOOST_CHECK(coin == entry.second); if (coin.IsSpent()) { missed_an_entry = true; } else { - BOOST_CHECK(stack.back()->HaveCoinInCache(it->first)); + BOOST_CHECK(stack.back()->HaveCoinInCache(entry.first)); found_an_entry = true; } } @@ -420,11 +420,11 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) // Once every 1000 iterations and at the end, verify the full cache. if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { - for (auto it = result.begin(); it != result.end(); it++) { - bool have = stack.back()->HaveCoin(it->first); - const Coin& coin = stack.back()->AccessCoin(it->first); + for (const auto& entry : result) { + bool have = stack.back()->HaveCoin(entry.first); + const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == it->second); + BOOST_CHECK(coin == entry.second); } } diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 35e4458bba..87e75d8020 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "compressor.h" -#include "util.h" -#include "test/test_bitcoin.h" +#include <compressor.h> +#include <util.h> +#include <test/test_bitcoin.h> #include <stdint.h> diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index c748b2448c..125b68e76d 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -2,17 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/aes.h" -#include "crypto/chacha20.h" -#include "crypto/ripemd160.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/sha512.h" -#include "crypto/hmac_sha256.h" -#include "crypto/hmac_sha512.h" -#include "random.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <crypto/aes.h> +#include <crypto/chacha20.h> +#include <crypto/ripemd160.h> +#include <crypto/sha1.h> +#include <crypto/sha256.h> +#include <crypto/sha512.h> +#include <crypto/hmac_sha256.h> +#include <crypto/hmac_sha512.h> +#include <random.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <vector> @@ -340,6 +340,22 @@ BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) { "647320746f20626520686173686564206265666f7265206265696e6720757365" "642062792074686520484d414320616c676f726974686d2e", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); + // Test case with key length 63 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "9de4b546756c83516720a4ad7fe7bdbeac4298c6fdd82b15f895a6d10b0769a6"); + // Test case with key length 64 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "528c609a4c9254c274585334946b7c2661bad8f1fc406b20f6892478d19163dd"); + // Test case with key length 65 bytes. + TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "d06af337f359a2330deffb8e3cbe4b5b7aa8ca1f208528cdbd245d5dc63c4483"); } BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { @@ -383,6 +399,31 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { "642062792074686520484d414320616c676f726974686d2e", "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); + // Test case with key length 127 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "267424dfb8eeb999f3e5ec39a4fe9fd14c923e6187e0897063e5c9e02b2e624a" + "c04413e762977df71a9fb5d562b37f89dfdfb930fce2ed1fa783bbc2a203d80e"); + // Test case with key length 128 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "43aaac07bb1dd97c82c04df921f83b16a68d76815cd1a30d3455ad43a3d80484" + "2bb35462be42cc2e4b5902de4d204c1c66d93b47d1383e3e13a3788687d61258"); + // Test case with key length 129 bytes. + TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665" + "4a", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "0b273325191cfc1b4b71d5075c8fcad67696309d292b1dad2cd23983a35feb8e" + "fb29795e79f2ef27f68cb1e16d76178c307a67beaad9456fac5fdffeadb16e2c"); } BOOST_AUTO_TEST_CASE(aes_testvectors) { diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 1004482224..32d46da984 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <boost/test/unit_test.hpp> -#include "cuckoocache.h" -#include "script/sigcache.h" -#include "test/test_bitcoin.h" -#include "random.h" +#include <cuckoocache.h> +#include <script/sigcache.h> +#include <test/test_bitcoin.h> +#include <random.h> #include <thread> /** Test Suite for CuckooCache diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 698e898231..63f43c0fc6 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -862,8 +862,6 @@ ["Ensure 100% coverage of discouraged NOPS"], ["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], -["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], ["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"], diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index efddafe17e..2e1e4da72f 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "dbwrapper.h" -#include "uint256.h" -#include "random.h" -#include "test/test_bitcoin.h" +#include <dbwrapper.h> +#include <uint256.h> +#include <random.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> @@ -125,7 +125,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. - CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); + std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false); char key = 'k'; uint256 in = InsecureRand256(); uint256 res; @@ -135,8 +135,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK_EQUAL(res.ToString(), in.ToString()); // Call the destructor to free leveldb LOCK - delete dbw; - dbw = nullptr; + dbw.reset(); // Now, set up another wrapper that wants to obfuscate the same directory CDBWrapper odbw(ph, (1 << 10), false, false, true); @@ -167,7 +166,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. - CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); + std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false); char key = 'k'; uint256 in = InsecureRand256(); uint256 res; @@ -177,8 +176,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK_EQUAL(res.ToString(), in.ToString()); // Call the destructor to free leveldb LOCK - delete dbw; - dbw = nullptr; + dbw.reset(); // Simulate a -reindex by wiping the existing data store CDBWrapper odbw(ph, (1 << 10), false, true, true); diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 40f0ecd5f1..3c39258693 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" -#include "test/test_bitcoin.h" +#include <util.h> +#include <test/test_bitcoin.h> #include <string> #include <vector> diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 05b6b3b1e6..68f445d142 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "hash.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <hash.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 91c0175412..7b9d7a6398 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "key.h" - -#include "base58.h" -#include "script/script.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" +#include <key.h> + +#include <base58.h> +#include <script/script.h> +#include <uint256.h> +#include <util.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> #include <string> #include <vector> diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp index b071ab117b..90730cd7b5 100644 --- a/src/test/limitedmap_tests.cpp +++ b/src/test/limitedmap_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "limitedmap.h" +#include <limitedmap.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 656aec606b..4be32f7628 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chainparams.h" -#include "validation.h" -#include "net.h" +#include <chainparams.h> +#include <validation.h> +#include <net.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/signals2/signal.hpp> #include <boost/test/unit_test.hpp> diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 116210a297..a694b870fe 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "policy/policy.h" -#include "txmempool.h" -#include "util.h" +#include <policy/policy.h> +#include <txmempool.h> +#include <util.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> #include <list> @@ -165,6 +165,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest) sortedOrder[2] = tx1.GetHash().ToString(); // 10000 sortedOrder[3] = tx4.GetHash().ToString(); // 15000 sortedOrder[4] = tx2.GetHash().ToString(); // 20000 + LOCK(pool.cs); CheckSort<descendant_score>(pool, sortedOrder); /* low fee but with high fee child */ @@ -375,6 +376,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest) } sortedOrder[4] = tx3.GetHash().ToString(); // 0 + LOCK(pool.cs); CheckSort<ancestor_score>(pool, sortedOrder); /* low fee parent with high fee child */ diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 1a1cf4399c..ee48d96ad9 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/merkle.h" -#include "test/test_bitcoin.h" +#include <consensus/merkle.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp index 3e66c6f2c6..37a1a84136 100644 --- a/src/test/merkleblock_tests.cpp +++ b/src/test/merkleblock_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "merkleblock.h" -#include "uint256.h" -#include "test/test_bitcoin.h" +#include <merkleblock.h> +#include <uint256.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 2851808cf4..b1a2032ea8 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -2,23 +2,23 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chainparams.h" -#include "coins.h" -#include "consensus/consensus.h" -#include "consensus/merkle.h" -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "validation.h" -#include "miner.h" -#include "policy/policy.h" -#include "pubkey.h" -#include "script/standard.h" -#include "txmempool.h" -#include "uint256.h" -#include "util.h" -#include "utilstrencodings.h" - -#include "test/test_bitcoin.h" +#include <chainparams.h> +#include <coins.h> +#include <consensus/consensus.h> +#include <consensus/merkle.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <validation.h> +#include <miner.h> +#include <policy/policy.h> +#include <pubkey.h> +#include <script/standard.h> +#include <txmempool.h> +#include <uint256.h> +#include <util.h> +#include <utilstrencodings.h> + +#include <test/test_bitcoin.h> #include <memory> diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index de7f3b48f5..ffba7d6d22 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -2,16 +2,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "key.h" -#include "keystore.h" -#include "policy/policy.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/interpreter.h" -#include "script/sign.h" -#include "script/ismine.h" -#include "uint256.h" -#include "test/test_bitcoin.h" +#include <key.h> +#include <keystore.h> +#include <policy/policy.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/interpreter.h> +#include <script/sign.h> +#include <script/ismine.h> +#include <uint256.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 31b05d868b..b4176a2b85 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1,17 +1,17 @@ // Copyright (c) 2012-2016 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 "addrman.h" -#include "test/test_bitcoin.h" +#include <addrman.h> +#include <test/test_bitcoin.h> #include <string> #include <boost/test/unit_test.hpp> -#include "hash.h" -#include "serialize.h" -#include "streams.h" -#include "net.h" -#include "netbase.h" -#include "chainparams.h" -#include "util.h" +#include <hash.h> +#include <serialize.h> +#include <streams.h> +#include <net.h> +#include <netbase.h> +#include <chainparams.h> +#include <util.h> class CAddrManSerializationMock : public CAddrMan { diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 1baf7643e5..f3a9b1fc65 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "netbase.h" -#include "test/test_bitcoin.h" -#include "utilstrencodings.h" +#include <netbase.h> +#include <test/test_bitcoin.h> +#include <utilstrencodings.h> #include <string> diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index c1d216d094..b7b632be3a 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/merkle.h" -#include "merkleblock.h" -#include "serialize.h" -#include "streams.h" -#include "uint256.h" -#include "arith_uint256.h" -#include "version.h" -#include "test/test_bitcoin.h" +#include <consensus/merkle.h> +#include <merkleblock.h> +#include <serialize.h> +#include <streams.h> +#include <uint256.h> +#include <arith_uint256.h> +#include <version.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index fd8f7191f4..d8026e4468 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "policy/policy.h" -#include "policy/fees.h" -#include "txmempool.h" -#include "uint256.h" -#include "util.h" +#include <policy/policy.h> +#include <policy/fees.h> +#include <txmempool.h> +#include <uint256.h> +#include <util.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index b13f2625aa..2837537c9a 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" -#include "chainparams.h" -#include "pow.h" -#include "random.h" -#include "util.h" -#include "test/test_bitcoin.h" +#include <chain.h> +#include <chainparams.h> +#include <pow.h> +#include <random.h> +#include <util.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 841282873f..1327d67650 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -3,13 +3,13 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <vector> -#include "prevector.h" +#include <prevector.h> -#include "reverse_iterator.h" -#include "serialize.h" -#include "streams.h" +#include <reverse_iterator.h> +#include <serialize.h> +#include <streams.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp index 0d541ec7d4..781b1e242d 100644 --- a/src/test/raii_event_tests.cpp +++ b/src/test/raii_event_tests.cpp @@ -10,9 +10,9 @@ #include <map> #include <stdlib.h> -#include "support/events.h" +#include <support/events.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 132e190051..1ca5a53d72 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "random.h" +#include <random.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 00dc47e13e..86d6161e20 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "reverselock.h" -#include "test/test_bitcoin.h" +#include <reverselock.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index c6643be7a7..710d09ead6 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/server.h" -#include "rpc/client.h" +#include <rpc/server.h> +#include <rpc/client.h> -#include "base58.h" -#include "core_io.h" -#include "netbase.h" +#include <base58.h> +#include <core_io.h> +#include <netbase.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 51f9e9f39f..b3ec6d34c7 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "compat/sanity.h" -#include "key.h" -#include "test/test_bitcoin.h" +#include <compat/sanity.h> +#include <key.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 1de865776e..7e86eed1c5 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "random.h" -#include "scheduler.h" +#include <random.h> +#include <scheduler.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/bind.hpp> #include <boost/thread.hpp> diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 58aa32c969..5a64aa3959 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -2,17 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/tx_verify.h" -#include "core_io.h" -#include "key.h" -#include "keystore.h" -#include "validation.h" -#include "policy/policy.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/ismine.h" -#include "test/test_bitcoin.h" +#include <consensus/tx_verify.h> +#include <core_io.h> +#include <key.h> +#include <keystore.h> +#include <validation.h> +#include <policy/policy.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/sign.h> +#include <script/ismine.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index bd2d9ed115..19060eccc9 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "key.h" -#include "keystore.h" -#include "script/ismine.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/standard.h" -#include "test/test_bitcoin.h" +#include <key.h> +#include <keystore.h> +#include <script/ismine.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/standard.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 011a5db795..f96d867bc6 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -2,21 +2,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "data/script_tests.json.h" - -#include "core_io.h" -#include "key.h" -#include "keystore.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "util.h" -#include "utilstrencodings.h" -#include "test/test_bitcoin.h" -#include "rpc/server.h" +#include <test/data/script_tests.json.h> + +#include <core_io.h> +#include <key.h> +#include <keystore.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/sign.h> +#include <util.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> +#include <rpc/server.h> #if defined(HAVE_CONSENSUS_LIB) -#include "script/bitcoinconsensus.h" +#include <script/bitcoinconsensus.h> #endif #include <fstream> @@ -166,6 +166,17 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript CMutableTransaction tx2 = tx; BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); + + // Verify that removing flags from a passing test or adding flags to a failing test does not change the result. + for (int i = 0; i < 16; ++i) { + int extra_flags = InsecureRandBits(16); + int combined_flags = expect ? (flags & ~extra_flags) : (flags | extra_flags); + // Weed out some invalid flag combinations. + if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue; + if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue; + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message + strprintf(" (with flags %x)", combined_flags)); + } + #if defined(HAVE_CONSENSUS_LIB) CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h index 94dd58526c..ad15427a9b 100644 --- a/src/test/scriptnum10.h +++ b/src/test/scriptnum10.h @@ -12,7 +12,7 @@ #include <stdint.h> #include <string> #include <vector> -#include "assert.h" +#include <assert.h> class scriptnum10_error : public std::runtime_error { diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index 280eb59ce8..aef500174a 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "scriptnum10.h" -#include "script/script.h" -#include "test/test_bitcoin.h" +#include <test/scriptnum10.h> +#include <script/script.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> #include <limits.h> diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 9661a66514..28ed2bfeb0 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -2,10 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "serialize.h" -#include "streams.h" -#include "hash.h" -#include "test/test_bitcoin.h" +#include <serialize.h> +#include <streams.h> +#include <hash.h> +#include <test/test_bitcoin.h> #include <stdint.h> diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index ecbdf57788..d97e106287 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -2,18 +2,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "data/sighash.json.h" -#include "hash.h" -#include "script/interpreter.h" -#include "script/script.h" -#include "serialize.h" -#include "streams.h" -#include "test/test_bitcoin.h" -#include "util.h" -#include "utilstrencodings.h" -#include "version.h" +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <test/data/sighash.json.h> +#include <hash.h> +#include <script/interpreter.h> +#include <script/script.h> +#include <serialize.h> +#include <streams.h> +#include <test/test_bitcoin.h> +#include <util.h> +#include <utilstrencodings.h> +#include <version.h> #include <iostream> diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index d3b8b07228..891cd1e1d8 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "pubkey.h" -#include "key.h" -#include "script/script.h" -#include "script/standard.h" -#include "uint256.h" -#include "test/test_bitcoin.h" +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <pubkey.h> +#include <key.h> +#include <script/script.h> +#include <script/standard.h> +#include <uint256.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 164cbd873f..1ffd9f2b42 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" -#include "util.h" -#include "test/test_bitcoin.h" +#include <chain.h> +#include <util.h> +#include <test/test_bitcoin.h> #include <vector> diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index af2a152aa5..3636e6c332 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "streams.h" -#include "support/allocators/zeroafterfree.h" -#include "test/test_bitcoin.h" +#include <streams.h> +#include <support/allocators/zeroafterfree.h> +#include <test/test_bitcoin.h> #include <boost/assign/std/vector.hpp> // for 'operator+=()' #include <boost/test/unit_test.hpp> diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index f9ce52c594..f52c8ccc21 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -2,26 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "test_bitcoin.h" - -#include "chainparams.h" -#include "consensus/consensus.h" -#include "consensus/validation.h" -#include "crypto/sha256.h" -#include "fs.h" -#include "key.h" -#include "validation.h" -#include "miner.h" -#include "net_processing.h" -#include "pubkey.h" -#include "random.h" -#include "txdb.h" -#include "txmempool.h" -#include "ui_interface.h" -#include "streams.h" -#include "rpc/server.h" -#include "rpc/register.h" -#include "script/sigcache.h" +#include <test/test_bitcoin.h> + +#include <chainparams.h> +#include <consensus/consensus.h> +#include <consensus/validation.h> +#include <crypto/sha256.h> +#include <validation.h> +#include <miner.h> +#include <net_processing.h> +#include <ui_interface.h> +#include <streams.h> +#include <rpc/server.h> +#include <rpc/register.h> +#include <script/sigcache.h> #include <memory> @@ -81,9 +75,9 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); mempool.setSanityCheck(1.0); - pblocktree = new CBlockTreeDB(1 << 20, true); - pcoinsdbview = new CCoinsViewDB(1 << 23, true); - pcoinsTip = new CCoinsViewCache(pcoinsdbview); + pblocktree.reset(new CBlockTreeDB(1 << 20, true)); + pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); + pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); if (!LoadGenesisBlock(chainparams)) { throw std::runtime_error("LoadGenesisBlock failed."); } @@ -110,9 +104,9 @@ TestingSetup::~TestingSetup() g_connman.reset(); peerLogic.reset(); UnloadBlockIndex(); - delete pcoinsTip; - delete pcoinsdbview; - delete pblocktree; + pcoinsTip.reset(); + pcoinsdbview.reset(); + pblocktree.reset(); fs::remove_all(pathTemp); } @@ -149,7 +143,10 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& block.vtx.push_back(MakeTransactionRef(tx)); // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; - IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); + { + LOCK(cs_main); + IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); + } while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 62ded2aaf5..80a9cbaeea 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -5,14 +5,14 @@ #ifndef BITCOIN_TEST_TEST_BITCOIN_H #define BITCOIN_TEST_TEST_BITCOIN_H -#include "chainparamsbase.h" -#include "fs.h" -#include "key.h" -#include "pubkey.h" -#include "random.h" -#include "scheduler.h" -#include "txdb.h" -#include "txmempool.h" +#include <chainparamsbase.h> +#include <fs.h> +#include <key.h> +#include <pubkey.h> +#include <random.h> +#include <scheduler.h> +#include <txdb.h> +#include <txmempool.h> #include <boost/thread.hpp> @@ -57,7 +57,6 @@ struct CConnmanTest { class PeerLogicValidation; struct TestingSetup: public BasicTestingSetup { - CCoinsViewDB *pcoinsdbview; fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp index 6694c5caa8..319d81187a 100644 --- a/src/test/test_bitcoin_fuzzy.cpp +++ b/src/test/test_bitcoin_fuzzy.cpp @@ -3,23 +3,23 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "consensus/merkle.h" -#include "primitives/block.h" -#include "script/script.h" -#include "addrman.h" -#include "chain.h" -#include "coins.h" -#include "compressor.h" -#include "net.h" -#include "protocol.h" -#include "streams.h" -#include "undo.h" -#include "version.h" -#include "pubkey.h" -#include "blockencodings.h" +#include <consensus/merkle.h> +#include <primitives/block.h> +#include <script/script.h> +#include <addrman.h> +#include <chain.h> +#include <coins.h> +#include <compressor.h> +#include <net.h> +#include <protocol.h> +#include <streams.h> +#include <undo.h> +#include <version.h> +#include <pubkey.h> +#include <blockencodings.h> #include <stdint.h> #include <unistd.h> diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp index b556c953b9..8d81ff6fc6 100644 --- a/src/test/test_bitcoin_main.cpp +++ b/src/test/test_bitcoin_main.cpp @@ -4,7 +4,7 @@ #define BOOST_TEST_MODULE Bitcoin Test Suite -#include "net.h" +#include <net.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 34863fd9d0..9ff95bd2b0 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#include "timedata.h" -#include "test/test_bitcoin.h" +#include <timedata.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index b7affaacde..d0aa8659c2 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#include "test/test_bitcoin.h" -#include "torcontrol.cpp" +#include <test/test_bitcoin.h> +#include <torcontrol.cpp> #include <boost/test/unit_test.hpp> diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index cb6ab7cdbe..34a182722d 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -2,24 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "data/tx_invalid.json.h" -#include "data/tx_valid.json.h" -#include "test/test_bitcoin.h" - -#include "clientversion.h" -#include "checkqueue.h" -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "key.h" -#include "keystore.h" -#include "validation.h" -#include "policy/policy.h" -#include "script/script.h" -#include "script/sign.h" -#include "script/script_error.h" -#include "script/standard.h" -#include "utilstrencodings.h" +#include <test/data/tx_invalid.json.h> +#include <test/data/tx_valid.json.h> +#include <test/test_bitcoin.h> + +#include <clientversion.h> +#include <checkqueue.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <key.h> +#include <keystore.h> +#include <validation.h> +#include <policy/policy.h> +#include <script/script.h> +#include <script/sign.h> +#include <script/script_error.h> +#include <script/standard.h> +#include <utilstrencodings.h> #include <map> #include <string> diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp new file mode 100644 index 0000000000..2d1eb7b772 --- /dev/null +++ b/src/test/txvalidation_tests.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 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 <validation.h> +#include <txmempool.h> +#include <amount.h> +#include <consensus/validation.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <test/test_bitcoin.h> + +#include <boost/test/unit_test.hpp> + + +BOOST_AUTO_TEST_SUITE(txvalidation_tests) + +/** + * Ensure that the mempool won't accept coinbase transactions. + */ +BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) +{ + CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; + CMutableTransaction coinbaseTx; + + coinbaseTx.nVersion = 1; + coinbaseTx.vin.resize(1); + coinbaseTx.vout.resize(1); + coinbaseTx.vin[0].scriptSig = CScript() << OP_11 << OP_EQUAL; + coinbaseTx.vout[0].nValue = 1 * CENT; + coinbaseTx.vout[0].scriptPubKey = scriptPubKey; + + assert(CTransaction(coinbaseTx).IsCoinBase()); + + CValidationState state; + + LOCK(cs_main); + + unsigned int initialPoolSize = mempool.size(); + + BOOST_CHECK_EQUAL( + false, + AcceptToMemoryPool(mempool, state, MakeTransactionRef(coinbaseTx), + nullptr /* pfMissingInputs */, + nullptr /* plTxnReplaced */, + true /* bypass_limits */, + 0 /* nAbsurdFee */)); + + // Check that the transaction hasn't been added to mempool. + BOOST_CHECK_EQUAL(mempool.size(), initialPoolSize); + + // Check that the validation state reflects the unsuccessful attempt. + BOOST_CHECK(state.IsInvalid()); + BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase"); + + int nDoS; + BOOST_CHECK_EQUAL(state.IsInvalid(nDoS), true); + BOOST_CHECK_EQUAL(nDoS, 100); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 82ca93e7da..fe8cb6126e 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -2,20 +2,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/validation.h" -#include "key.h" -#include "validation.h" -#include "miner.h" -#include "pubkey.h" -#include "txmempool.h" -#include "random.h" -#include "script/standard.h" -#include "script/sign.h" -#include "test/test_bitcoin.h" -#include "utiltime.h" -#include "core_io.h" -#include "keystore.h" -#include "policy/policy.h" +#include <consensus/validation.h> +#include <key.h> +#include <validation.h> +#include <miner.h> +#include <pubkey.h> +#include <txmempool.h> +#include <random.h> +#include <script/standard.h> +#include <script/sign.h> +#include <test/test_bitcoin.h> +#include <utiltime.h> +#include <core_io.h> +#include <keystore.h> +#include <policy/policy.h> #include <boost/test/unit_test.hpp> @@ -66,6 +66,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // Test 1: block with both of those transactions should be rejected. block = CreateAndProcessBlock(spends, scriptPubKey); + LOCK(cs_main); BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash()); // Test 2: ... and should be rejected if spend1 is in the memory pool @@ -102,7 +103,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // should fail. // Capture this interaction with the upgraded_nop argument: set it when evaluating // any script flag that is implemented as an upgraded NOP code. -void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache, bool upgraded_nop) +void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache) { PrecomputedTransactionData txdata(tx); // If we add many more flags, this loop can get too expensive, but we can @@ -119,29 +120,23 @@ void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_fl // WITNESS requires P2SH test_flags |= SCRIPT_VERIFY_P2SH; } - bool ret = CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, nullptr); + bool ret = CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, nullptr); // CheckInputs should succeed iff test_flags doesn't intersect with // failing_flags bool expected_return_value = !(test_flags & failing_flags); - if (expected_return_value && upgraded_nop) { - // If the script flag being tested corresponds to an upgraded NOP, - // then script execution should fail if DISCOURAGE_UPGRADABLE_NOPS - // is set. - expected_return_value = !(test_flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS); - } BOOST_CHECK_EQUAL(ret, expected_return_value); // Test the caching if (ret && add_to_cache) { // Check that we get a cache hit if the tx was valid std::vector<CScriptCheck> scriptchecks; - BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, &scriptchecks)); + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, &scriptchecks)); BOOST_CHECK(scriptchecks.empty()); } else { // Check that we get script executions to check, if the transaction // was invalid, or we didn't add to cache. std::vector<CScriptCheck> scriptchecks; - BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, test_flags, true, add_to_cache, txdata, &scriptchecks)); + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, &scriptchecks)); BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size()); } } @@ -151,7 +146,10 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) { // Test that passing CheckInputs with one set of script flags doesn't imply // that we would pass again with a different set of flags. - InitScriptExecutionCache(); + { + LOCK(cs_main); + InitScriptExecutionCache(); + } CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; CScript p2sh_scriptPubKey = GetScriptForDestination(CScriptID(p2pk_scriptPubKey)); @@ -201,20 +199,20 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) CValidationState state; PrecomputedTransactionData ptd_spend_tx(spend_tx); - BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr)); + BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr)); // If we call again asking for scriptchecks (as happens in // ConnectBlock), we should add a script check object for this -- we're // not caching invalidity (if that changes, delete this test case). std::vector<CScriptCheck> scriptchecks; - BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); + BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); BOOST_CHECK_EQUAL(scriptchecks.size(), 1); // Test that CheckInputs returns true iff DERSIG-enforcing flags are // not present. Don't add these checks to the cache, so that we can // test later that block validation works fine in the absence of cached // successes. - ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false, false); + ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false); // And if we produce a block with this tx, it should be valid (DERSIG not // enabled yet), even though there's no cache entry. @@ -239,7 +237,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end()); invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2; - ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true, false); + ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true); } // Test CHECKLOCKTIMEVERIFY @@ -262,13 +260,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101; - ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true); + ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true); // Make it valid, and check again invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100; CValidationState state; PrecomputedTransactionData txdata(invalid_with_cltv_tx); - BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip, true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); + BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); } // TEST CHECKSEQUENCEVERIFY @@ -290,13 +288,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101; - ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true); + ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true); // Make it valid, and check again invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100; CValidationState state; PrecomputedTransactionData txdata(invalid_with_csv_tx); - BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip, true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); + BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); } // TODO: add tests for remaining script flags @@ -319,11 +317,11 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) UpdateTransaction(valid_with_witness_tx, 0, sigdata); // This should be valid under all script flags. - ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true, false); + ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true); // Remove the witness, and check that it is now invalid. valid_with_witness_tx.vin[0].scriptWitness.SetNull(); - ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true, false); + ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true); } { @@ -348,7 +346,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) } // This should be valid under all script flags - ValidateCheckInputsForAllFlags(tx, 0, true, false); + ValidateCheckInputsForAllFlags(tx, 0, true); // Check that if the second input is invalid, but the first input is // valid, the transaction is not cached. @@ -358,12 +356,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) CValidationState state; PrecomputedTransactionData txdata(tx); // This transaction is now invalid under segwit, because of the second input. - BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr)); + BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr)); std::vector<CScriptCheck> scriptchecks; // Make sure this transaction was not cached (ie because the first // input was valid) - BOOST_CHECK(CheckInputs(tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks)); + BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks)); // Should get 2 script checks back -- caching is on a whole-transaction basis. BOOST_CHECK_EQUAL(scriptchecks.size(), 2); } diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 70d83a2e54..40ef9adb2e 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -1,10 +1,10 @@ // Copyright (c) 2011-2016 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 "arith_uint256.h" -#include "uint256.h" -#include "version.h" -#include "test/test_bitcoin.h" +#include <arith_uint256.h> +#include <uint256.h> +#include <version.h> +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> #include <stdint.h> diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index dffe8e55a8..7386204437 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -8,7 +8,7 @@ #include <string> #include <map> #include <univalue.h> -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 6ec544290d..998090cd9b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -2,14 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" - -#include "clientversion.h" -#include "primitives/transaction.h" -#include "sync.h" -#include "utilstrencodings.h" -#include "utilmoneystr.h" -#include "test/test_bitcoin.h" +#include <util.h> + +#include <clientversion.h> +#include <primitives/transaction.h> +#include <sync.h> +#include <utilstrencodings.h> +#include <utilmoneystr.h> +#include <test/test_bitcoin.h> #include <stdint.h> #include <vector> diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index db537d3932..7029b347dd 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" -#include "versionbits.h" -#include "test/test_bitcoin.h" -#include "chainparams.h" -#include "validation.h" -#include "consensus/params.h" +#include <chain.h> +#include <versionbits.h> +#include <test/test_bitcoin.h> +#include <chainparams.h> +#include <validation.h> +#include <consensus/params.h> #include <boost/test/unit_test.hpp> diff --git a/src/threadinterrupt.cpp b/src/threadinterrupt.cpp index 9d691079ed..7bcacc3014 100644 --- a/src/threadinterrupt.cpp +++ b/src/threadinterrupt.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "threadinterrupt.h" +#include <threadinterrupt.h> CThreadInterrupt::operator bool() const { diff --git a/src/timedata.cpp b/src/timedata.cpp index 5113bb60db..b91cf01723 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -3,17 +3,17 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "timedata.h" +#include <timedata.h> -#include "netaddress.h" -#include "sync.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" -#include "warnings.h" +#include <netaddress.h> +#include <sync.h> +#include <ui_interface.h> +#include <util.h> +#include <utilstrencodings.h> +#include <warnings.h> static CCriticalSection cs_nTimeOffset; diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 1cea197666..46f39d65a0 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "torcontrol.h" -#include "utilstrencodings.h" -#include "netbase.h" -#include "net.h" -#include "util.h" -#include "crypto/hmac_sha256.h" +#include <torcontrol.h> +#include <utilstrencodings.h> +#include <netbase.h> +#include <net.h> +#include <util.h> +#include <crypto/hmac_sha256.h> #include <vector> #include <deque> diff --git a/src/torcontrol.h b/src/torcontrol.h index 72dc82c5b1..a01eeefeb8 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -8,7 +8,7 @@ #ifndef BITCOIN_TORCONTROL_H #define BITCOIN_TORCONTROL_H -#include "scheduler.h" +#include <scheduler.h> extern const std::string DEFAULT_TOR_CONTROL; static const bool DEFAULT_LISTEN_ONION = true; diff --git a/src/txdb.cpp b/src/txdb.cpp index 134bb8721b..7a8e854b55 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -3,16 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "txdb.h" - -#include "chainparams.h" -#include "hash.h" -#include "random.h" -#include "pow.h" -#include "uint256.h" -#include "util.h" -#include "ui_interface.h" -#include "init.h" +#include <txdb.h> + +#include <chainparams.h> +#include <hash.h> +#include <random.h> +#include <pow.h> +#include <uint256.h> +#include <util.h> +#include <ui_interface.h> +#include <init.h> #include <stdint.h> diff --git a/src/txdb.h b/src/txdb.h index ec9f571b13..2e8095e3cd 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_TXDB_H #define BITCOIN_TXDB_H -#include "coins.h" -#include "dbwrapper.h" -#include "chain.h" +#include <coins.h> +#include <dbwrapper.h> +#include <chain.h> #include <map> #include <string> diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b0306811cb..392323808f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -3,20 +3,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "txmempool.h" - -#include "consensus/consensus.h" -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "validation.h" -#include "policy/policy.h" -#include "policy/fees.h" -#include "reverse_iterator.h" -#include "streams.h" -#include "timedata.h" -#include "util.h" -#include "utilmoneystr.h" -#include "utiltime.h" +#include <txmempool.h> + +#include <consensus/consensus.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <validation.h> +#include <policy/policy.h> +#include <policy/fees.h> +#include <reverse_iterator.h> +#include <streams.h> +#include <timedata.h> +#include <util.h> +#include <utilmoneystr.h> +#include <utiltime.h> CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee, int64_t _nTime, unsigned int _entryHeight, @@ -317,7 +317,7 @@ void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFe assert(int64_t(nCountWithDescendants) > 0); } -void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps) +void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps) { nSizeWithAncestors += modifySize; assert(int64_t(nSizeWithAncestors) > 0); diff --git a/src/txmempool.h b/src/txmempool.h index 929d223588..86a008d7b2 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -13,13 +13,13 @@ #include <utility> #include <string> -#include "amount.h" -#include "coins.h" -#include "indirectmap.h" -#include "policy/feerate.h" -#include "primitives/transaction.h" -#include "sync.h" -#include "random.h" +#include <amount.h> +#include <coins.h> +#include <indirectmap.h> +#include <policy/feerate.h> +#include <primitives/transaction.h> +#include <sync.h> +#include <random.h> #include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> @@ -109,7 +109,7 @@ public: // Adjusts the descendant state. void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount); // Adjusts the ancestor state - void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps); + void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps); // Updates the fee delta used for mining priority score, and the // modified fees with descendants. void UpdateFeeDelta(int64_t feeDelta); @@ -204,7 +204,7 @@ struct mempoolentry_txid class CompareTxMemPoolEntryByDescendantScore { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { bool fUseADescendants = UseDescendantScore(a); bool fUseBDescendants = UseDescendantScore(b); @@ -226,7 +226,7 @@ public: } // Calculate which score to use for an entry (avoiding division). - bool UseDescendantScore(const CTxMemPoolEntry &a) + bool UseDescendantScore(const CTxMemPoolEntry &a) const { double f1 = (double)a.GetModifiedFee() * a.GetSizeWithDescendants(); double f2 = (double)a.GetModFeesWithDescendants() * a.GetTxSize(); @@ -241,7 +241,7 @@ public: class CompareTxMemPoolEntryByScore { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { double f1 = (double)a.GetModifiedFee() * b.GetTxSize(); double f2 = (double)b.GetModifiedFee() * a.GetTxSize(); @@ -255,7 +255,7 @@ public: class CompareTxMemPoolEntryByEntryTime { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { return a.GetTime() < b.GetTime(); } @@ -264,7 +264,7 @@ public: class CompareTxMemPoolEntryByAncestorFee { public: - bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) + bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) const { double aFees = a.GetModFeesWithAncestors(); double aSize = a.GetSizeWithAncestors(); @@ -513,6 +513,9 @@ public: // to track size/count of descendant transactions. First version of // addUnchecked can be used to have it call CalculateMemPoolAncestors(), and // then invoke the second version. + // Note that addUnchecked is ONLY called from ATMP outside of tests + // and any other callers may break wallet's in-mempool tracking (due to + // lack of CValidationInterface::TransactionAddedToMempool callbacks). bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool validFeeEstimate = true); bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate = true); diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 74a13e0e05..c0f7defa46 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "ui_interface.h" -#include "util.h" +#include <ui_interface.h> +#include <util.h> CClientUIInterface uiInterface; diff --git a/src/uint256.cpp b/src/uint256.cpp index 736a0d4fe2..b7255231c1 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -3,9 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "uint256.h" +#include <uint256.h> -#include "utilstrencodings.h" +#include <utilstrencodings.h> #include <stdio.h> #include <string.h> diff --git a/src/uint256.h b/src/uint256.h index 94a4f7fc30..e45c990dae 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -12,14 +12,14 @@ #include <stdint.h> #include <string> #include <vector> -#include "crypto/common.h" +#include <crypto/common.h> /** Template base class for fixed-sized opaque blobs. */ template<unsigned int BITS> class base_blob { protected: - enum { WIDTH=BITS/8 }; + static constexpr int WIDTH = BITS / 8; uint8_t data[WIDTH]; public: base_blob() diff --git a/src/undo.h b/src/undo.h index a720de4ac5..b482fd3089 100644 --- a/src/undo.h +++ b/src/undo.h @@ -6,10 +6,10 @@ #ifndef BITCOIN_UNDO_H #define BITCOIN_UNDO_H -#include "compressor.h" -#include "consensus/consensus.h" -#include "primitives/transaction.h" -#include "serialize.h" +#include <compressor.h> +#include <consensus/consensus.h> +#include <primitives/transaction.h> +#include <serialize.h> /** Undo information for a CTxIn * diff --git a/src/util.cpp b/src/util.cpp index 51ccc94787..a3e4b0acfb 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3,18 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" -#endif - -#include "util.h" +#include <util.h> -#include "chainparamsbase.h" -#include "fs.h" -#include "random.h" -#include "serialize.h" -#include "utilstrencodings.h" -#include "utiltime.h" +#include <chainparamsbase.h> +#include <random.h> +#include <serialize.h> +#include <utilstrencodings.h> #include <stdarg.h> @@ -89,6 +83,7 @@ const int64_t nStartupTime = GetTime(); const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf"; const char * const BITCOIN_PID_FILENAME = "bitcoind.pid"; +const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; ArgsManager gArgs; bool fPrintToConsole = false; @@ -189,26 +184,40 @@ static void DebugPrintInit() vMsgsBeforeOpenLog = new std::list<std::string>; } -void OpenDebugLog() +fs::path GetDebugLogPath() +{ + fs::path logfile(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); + if (logfile.is_absolute()) { + return logfile; + } else { + return GetDataDir() / logfile; + } +} + +bool OpenDebugLog() { boost::call_once(&DebugPrintInit, debugPrintInitFlag); boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); assert(fileout == nullptr); assert(vMsgsBeforeOpenLog); - fs::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDebugLogPath(); + fileout = fsbridge::fopen(pathDebug, "a"); - if (fileout) { - setbuf(fileout, nullptr); // unbuffered - // dump buffered messages from before we opened the log - while (!vMsgsBeforeOpenLog->empty()) { - FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); - vMsgsBeforeOpenLog->pop_front(); - } + if (!fileout) { + return false; + } + + setbuf(fileout, nullptr); // unbuffered + // dump buffered messages from before we opened the log + while (!vMsgsBeforeOpenLog->empty()) { + FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); + vMsgsBeforeOpenLog->pop_front(); } delete vMsgsBeforeOpenLog; vMsgsBeforeOpenLog = nullptr; + return true; } struct CLogCategoryDesc @@ -220,6 +229,7 @@ struct CLogCategoryDesc const CLogCategoryDesc LogCategories[] = { {BCLog::NONE, "0"}, + {BCLog::NONE, "none"}, {BCLog::NET, "net"}, {BCLog::TOR, "tor"}, {BCLog::MEMPOOL, "mempool"}, @@ -354,7 +364,7 @@ int LogPrintStr(const std::string &str) // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; - fs::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDebugLogPath(); if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr) setbuf(fileout, nullptr); // unbuffered } @@ -574,7 +584,10 @@ const fs::path &GetDataDir(bool fNetSpecific) if (fNetSpecific) path /= BaseParams().DataDir(); - fs::create_directories(path); + if (fs::create_directories(path)) { + // This is the first run, create wallets subdirectory too + fs::create_directories(path / "wallets"); + } return path; } @@ -620,6 +633,9 @@ void ArgsManager::ReadConfigFile(const std::string& confPath) } // If datadir is changed in .conf file: ClearDatadirCache(); + if (!fs::is_directory(GetDataDir(false))) { + throw std::runtime_error(strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str())); + } } #ifndef WIN32 @@ -770,7 +786,7 @@ void ShrinkDebugFile() // Amount of debug.log to save at end when shrinking (must fit in memory) constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000; // Scroll debug.log if it's getting too big - fs::path pathLog = GetDataDir() / "debug.log"; + fs::path pathLog = GetDebugLogPath(); FILE* file = fsbridge::fopen(pathLog, "r"); // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes diff --git a/src/util.h b/src/util.h index 480a80c0a3..3cc4c26817 100644 --- a/src/util.h +++ b/src/util.h @@ -11,14 +11,14 @@ #define BITCOIN_UTIL_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "compat.h" -#include "fs.h" -#include "sync.h" -#include "tinyformat.h" -#include "utiltime.h" +#include <compat.h> +#include <fs.h> +#include <sync.h> +#include <tinyformat.h> +#include <utiltime.h> #include <atomic> #include <exception> @@ -28,6 +28,7 @@ #include <vector> #include <boost/signals2/signal.hpp> +#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted // Application startup time (used for uptime calculation) int64_t GetStartupTime(); @@ -35,6 +36,7 @@ int64_t GetStartupTime(); static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; +extern const char * const DEFAULT_DEBUGLOGFILE; /** Signals for translation. */ class CTranslationInterface @@ -132,6 +134,10 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c MarkUsed(args...); } +// Be conservative when using LogPrintf/error or other things which +// unconditionally log to debug.log! It should not be the case that an inbound +// peer can fill up a users disk with debug.log entries. + #ifdef USE_COVERAGE #define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0) #define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0) @@ -179,7 +185,8 @@ void CreatePidFile(const fs::path &path, pid_t pid); #ifdef WIN32 fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif -void OpenDebugLog(); +fs::path GetDebugLogPath(); +bool OpenDebugLog(); void ShrinkDebugFile(); void runCommand(const std::string& strCommand); @@ -326,4 +333,11 @@ template <typename Callable> void TraceThread(const char* name, Callable func) std::string CopyrightHolders(const std::string& strPrefix); +//! Substitute for C++14 std::make_unique. +template <typename T, typename... Args> +std::unique_ptr<T> MakeUnique(Args&&... args) +{ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + #endif // BITCOIN_UTIL_H diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index 6e6e33184e..656d7c51b7 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -3,11 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "utilmoneystr.h" +#include <utilmoneystr.h> -#include "primitives/transaction.h" -#include "tinyformat.h" -#include "utilstrencodings.h" +#include <primitives/transaction.h> +#include <tinyformat.h> +#include <utilstrencodings.h> std::string FormatMoney(const CAmount& n) { diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index bc885ee167..b1a4499e90 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -12,7 +12,7 @@ #include <stdint.h> #include <string> -#include "amount.h" +#include <amount.h> /* Do not use these functions to represent or parse monetary amounts to or from * JSON but use AmountFromValue and ValueFromAmount for that. diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 741680e93f..d90713ed6a 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -3,9 +3,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "utilstrencodings.h" +#include <utilstrencodings.h> -#include "tinyformat.h" +#include <tinyformat.h> #include <cstdlib> #include <cstring> diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 4cc77dbfeb..ca11cf341f 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -4,10 +4,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "utiltime.h" +#include <utiltime.h> #include <atomic> diff --git a/src/validation.cpp b/src/validation.cpp index efabe6293f..75c40b22fc 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3,46 +3,43 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "validation.h" - -#include "arith_uint256.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "checkqueue.h" -#include "consensus/consensus.h" -#include "consensus/merkle.h" -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "cuckoocache.h" -#include "fs.h" -#include "hash.h" -#include "init.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "pow.h" -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "random.h" -#include "reverse_iterator.h" -#include "script/script.h" -#include "script/sigcache.h" -#include "script/standard.h" -#include "timedata.h" -#include "tinyformat.h" -#include "txdb.h" -#include "txmempool.h" -#include "ui_interface.h" -#include "undo.h" -#include "util.h" -#include "utilmoneystr.h" -#include "utilstrencodings.h" -#include "validationinterface.h" -#include "versionbits.h" -#include "warnings.h" - -#include <atomic> +#include <validation.h> + +#include <arith_uint256.h> +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#include <checkqueue.h> +#include <consensus/consensus.h> +#include <consensus/merkle.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <cuckoocache.h> +#include <hash.h> +#include <init.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <pow.h> +#include <primitives/block.h> +#include <primitives/transaction.h> +#include <random.h> +#include <reverse_iterator.h> +#include <script/script.h> +#include <script/sigcache.h> +#include <script/standard.h> +#include <timedata.h> +#include <tinyformat.h> +#include <txdb.h> +#include <txmempool.h> +#include <ui_interface.h> +#include <undo.h> +#include <util.h> +#include <utilmoneystr.h> +#include <utilstrencodings.h> +#include <validationinterface.h> +#include <warnings.h> + #include <sstream> #include <boost/algorithm/string/replace.hpp> @@ -59,48 +56,7 @@ /** * Global state */ - -CCriticalSection cs_main; - -BlockMap mapBlockIndex; -CChain chainActive; -CBlockIndex *pindexBestHeader = nullptr; -CWaitableCriticalSection csBestBlock; -CConditionVariable cvBlockChange; -int nScriptCheckThreads = 0; -std::atomic_bool fImporting(false); -std::atomic_bool fReindex(false); -bool fTxIndex = false; -bool fHavePruned = false; -bool fPruneMode = false; -bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; -bool fRequireStandard = true; -bool fCheckBlockIndex = false; -bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; -size_t nCoinCacheUsage = 5000 * 300; -uint64_t nPruneTarget = 0; -int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; -bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; - -uint256 hashAssumeValid; -arith_uint256 nMinimumChainWork; - -CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); -CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; - -CBlockPolicyEstimator feeEstimator; -CTxMemPool mempool(&feeEstimator); - -static void CheckBlockIndex(const Consensus::Params& consensusParams); - -/** Constant stuff for coinbase transactions we create: */ -CScript COINBASE_FLAGS; - -const std::string strMessageMagic = "Bitcoin Signed Message:\n"; - -// Internal stuff namespace { - struct CBlockIndexWorkComparator { bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const { @@ -121,28 +77,39 @@ namespace { return false; } }; +} // anon namespace - CBlockIndex *pindexBestInvalid; +enum DisconnectResult +{ + DISCONNECT_OK, // All good. + DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. + DISCONNECT_FAILED // Something else went wrong. +}; +class ConnectTrace; + +/** + * CChainState stores and provides an API to update our local knowledge of the + * current best chain and header tree. + * + * It generally provides access to the current block tree, as well as functions + * to provide new data, which it will appropriately validate and incorporate in + * its state as necessary. + * + * Eventually, the API here is targeted at being exposed externally as a + * consumable libconsensus library, so any functions added must only call + * other class member functions, pure functions in other parts of the consensus + * library, callbacks via the validation interface, or read/write-to-disk + * functions (eventually this will also be via callbacks). + */ +class CChainState { +private: /** * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be * missing the data for the block. */ std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; - /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. - * Pruned nodes may have entries where B is missing data. - */ - std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; - - CCriticalSection cs_LastBlockFile; - std::vector<CBlockFileInfo> vinfoBlockFile; - int nLastBlockFile = 0; - /** Global flag to indicate we should check to see if there are - * block/undo files that should be deleted. Set on startup - * or if we allocate more file space when we're in prune mode - */ - bool fCheckForPruning = false; /** * Every received block is assigned a unique and increasing identifier, so we @@ -176,6 +143,113 @@ namespace { */ std::set<CBlockIndex*> g_failed_blocks; +public: + CChain chainActive; + BlockMap mapBlockIndex; + std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; + CBlockIndex *pindexBestInvalid = nullptr; + + bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree); + + bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock); + + bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex); + bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock); + + // Block (dis)connection on a given view: + DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view); + bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false); + + // Block disconnection on our pcoinsTip: + bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool); + + // Manual block validity manipulation: + bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex); + bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); + bool ResetBlockFailureFlags(CBlockIndex *pindex); + + bool ReplayBlocks(const CChainParams& params, CCoinsView* view); + bool RewindBlockIndex(const CChainParams& params); + bool LoadGenesisBlock(const CChainParams& chainparams); + + void PruneBlockIndexCandidates(); + + void UnloadBlockIndex(); + +private: + bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace); + bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool); + + CBlockIndex* AddToBlockIndex(const CBlockHeader& block); + /** Create a new block index entry for a given block hash */ + CBlockIndex * InsertBlockIndex(const uint256& hash); + void CheckBlockIndex(const Consensus::Params& consensusParams); + + 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); + + + bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params); +} g_chainstate; + + + +CCriticalSection cs_main; + +BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex; +CChain& chainActive = g_chainstate.chainActive; +CBlockIndex *pindexBestHeader = nullptr; +CWaitableCriticalSection csBestBlock; +CConditionVariable cvBlockChange; +int nScriptCheckThreads = 0; +std::atomic_bool fImporting(false); +std::atomic_bool fReindex(false); +bool fTxIndex = false; +bool fHavePruned = false; +bool fPruneMode = false; +bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; +bool fRequireStandard = true; +bool fCheckBlockIndex = false; +bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; +size_t nCoinCacheUsage = 5000 * 300; +uint64_t nPruneTarget = 0; +int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; +bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT; + +uint256 hashAssumeValid; +arith_uint256 nMinimumChainWork; + +CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); +CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; + +CBlockPolicyEstimator feeEstimator; +CTxMemPool mempool(&feeEstimator); + +/** Constant stuff for coinbase transactions we create: */ +CScript COINBASE_FLAGS; + +const std::string strMessageMagic = "Bitcoin Signed Message:\n"; + +// Internal stuff +namespace { + CBlockIndex *&pindexBestInvalid = g_chainstate.pindexBestInvalid; + + /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. + * Pruned nodes may have entries where B is missing data. + */ + std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = g_chainstate.mapBlocksUnlinked; + + CCriticalSection cs_LastBlockFile; + std::vector<CBlockFileInfo> vinfoBlockFile; + int nLastBlockFile = 0; + /** Global flag to indicate we should check to see if there are + * block/undo files that should be deleted. Set on startup + * or if we allocate more file space when we're in prune mode + */ + bool fCheckForPruning = false; + /** Dirty block index entries. */ std::set<CBlockIndex*> setDirtyBlockIndex; @@ -201,9 +275,9 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc return chain.Genesis(); } -CCoinsViewDB *pcoinsdbview = nullptr; -CCoinsViewCache *pcoinsTip = nullptr; -CBlockTreeDB *pblocktree = nullptr; +std::unique_ptr<CCoinsViewDB> pcoinsdbview; +std::unique_ptr<CCoinsViewCache> pcoinsTip; +std::unique_ptr<CBlockTreeDB> pblocktree; enum FlushStateMode { FLUSH_STATE_NONE, @@ -295,7 +369,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool } else { // pcoinsTip contains the UTXO set for chainActive.Tip() - CCoinsViewMemPool viewMemPool(pcoinsTip, mempool); + CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool); std::vector<int> prevheights; prevheights.resize(tx.vin.size()); for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { @@ -424,7 +498,7 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f mempool.UpdateTransactionsFromBlock(vHashUpdate); // We also need to remove any now-immature transactions - mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); + mempool.removeForReorg(pcoinsTip.get(), chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); // Re-limit mempool size, in case we added any transactions LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); } @@ -557,7 +631,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool LockPoints lp; { LOCK(pool.cs); - CCoinsViewMemPool viewMemPool(pcoinsTip, pool); + CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); view.SetBackend(viewMemPool); // do all inputs exist? @@ -926,47 +1000,51 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, pfMissingInputs, GetTime(), plTxnReplaced, bypass_limits, nAbsurdFee); } -/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */ -bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) +/** + * Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock. + * If blockIndex is provided, the transaction is fetched from the corresponding block. + */ +bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex) { - CBlockIndex *pindexSlow = nullptr; + CBlockIndex* pindexSlow = blockIndex; LOCK(cs_main); - CTransactionRef ptx = mempool.get(hash); - if (ptx) - { - txOut = ptx; - return true; - } - - if (fTxIndex) { - CDiskTxPos postx; - if (pblocktree->ReadTxIndex(hash, postx)) { - CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); - if (file.IsNull()) - return error("%s: OpenBlockFile failed", __func__); - CBlockHeader header; - try { - file >> header; - fseek(file.Get(), postx.nTxOffset, SEEK_CUR); - file >> txOut; - } catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - hashBlock = header.GetHash(); - if (txOut->GetHash() != hash) - return error("%s: txid mismatch", __func__); + if (!blockIndex) { + CTransactionRef ptx = mempool.get(hash); + if (ptx) { + txOut = ptx; return true; } - // transaction not found in index, nothing more can be done - return false; - } + if (fTxIndex) { + CDiskTxPos postx; + if (pblocktree->ReadTxIndex(hash, postx)) { + CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); + if (file.IsNull()) + return error("%s: OpenBlockFile failed", __func__); + CBlockHeader header; + try { + file >> header; + fseek(file.Get(), postx.nTxOffset, SEEK_CUR); + file >> txOut; + } catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + hashBlock = header.GetHash(); + if (txOut->GetHash() != hash) + return error("%s: txid mismatch", __func__); + return true; + } + + // transaction not found in index, nothing more can be done + return false; + } - if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it - const Coin& coin = AccessByTxid(*pcoinsTip, hash); - if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight]; + if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it + const Coin& coin = AccessByTxid(*pcoinsTip, hash); + if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight]; + } } if (pindexSlow) { @@ -1197,7 +1275,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) CheckForkWarningConditions(); } -void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { +void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { if (!state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; g_failed_blocks.insert(pindex); @@ -1380,8 +1458,13 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint return true; } -bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) +static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex) { + CDiskBlockPos pos = pindex->GetUndoPos(); + if (pos.IsNull()) { + return error("%s: no undo data available", __func__); + } + // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) @@ -1391,7 +1474,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin uint256 hashChecksum; CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data try { - verifier << hashBlock; + verifier << pindex->pprev->GetBlockHash(); verifier >> blockundo; filein >> hashChecksum; } @@ -1426,13 +1509,6 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std } // namespace -enum DisconnectResult -{ - DISCONNECT_OK, // All good. - DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. - DISCONNECT_FAILED // Something else went wrong. -}; - /** * Restore the UTXO in a Coin at a given COutPoint * @param undo The Coin to be restored. @@ -1469,17 +1545,12 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out) /** Undo the effects of this block (with given index) on the UTXO set represented by coins. * When FAILED is returned, view is left in an indeterminate state. */ -static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) +DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) { bool fClean = true; CBlockUndo blockUndo; - CDiskBlockPos pos = pindex->GetUndoPos(); - if (pos.IsNull()) { - error("DisconnectBlock(): no undo data available"); - return DISCONNECT_FAILED; - } - if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) { + if (!UndoReadFromDisk(blockUndo, pindex)) { error("DisconnectBlock(): failure reading undo data"); return DISCONNECT_FAILED; } @@ -1556,6 +1627,45 @@ void static FlushBlockFile(bool fFinalize = false) static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); +static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) +{ + // Write undo information to disk + if (pindex->GetUndoPos().IsNull()) { + CDiskBlockPos _pos; + if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) + return error("ConnectBlock(): FindUndoPos failed"); + if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) + return AbortNode(state, "Failed to write undo data"); + + // update nUndoPos in block index + pindex->nUndoPos = _pos.nPos; + pindex->nStatus |= BLOCK_HAVE_UNDO; + setDirtyBlockIndex.insert(pindex); + } + + return true; +} + +static bool WriteTxIndexDataForBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex) +{ + if (!fTxIndex) return true; + + CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); + std::vector<std::pair<uint256, CDiskTxPos> > vPos; + vPos.reserve(block.vtx.size()); + for (const CTransactionRef& tx : block.vtx) + { + vPos.push_back(std::make_pair(tx->GetHash(), pos)); + pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION); + } + + if (!pblocktree->WriteTxIndex(vPos)) { + return AbortNode(state, "Failed to write transaction index"); + } + + return true; +} + static CCheckQueue<CScriptCheck> scriptcheckqueue(128); void ThreadScriptCheck() { @@ -1656,8 +1766,8 @@ static int64_t nBlocksTotal = 0; /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() * can fail if those validity checks fail (among other reasons). */ -static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, - CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) +bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck) { AssertLockHeld(cs_main); assert(pindex); @@ -1667,6 +1777,18 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in + // NOTE: We don't currently (re-)invoke ContextualCheckBlock() or + // ContextualCheckBlockHeader() here. This means that if we add a new + // consensus rule that is enforced in one of those two functions, then we + // may have let in a block that violates the rule prior to updating the + // software, and we would NOT be enforcing the rule here. Fully solving + // upgrade from one software version to the next after a consensus rule + // change is potentially tricky and issue-specific (see RewindBlockIndex() + // for one general approach that was used for BIP 141 deployment). + // Also, currently the rule against blocks more than 2 hours in the future + // is enforced in ContextualCheckBlockHeader(); we wouldn't want to + // re-enforce that rule here (at least until we make it impossible for + // GetAdjustedTime() to go backward). if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck)) return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); @@ -1771,9 +1893,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd CAmount nFees = 0; int nInputs = 0; int64_t nSigOpsCost = 0; - CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); - std::vector<std::pair<uint256, CDiskTxPos> > vPos; - vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); std::vector<PrecomputedTransactionData> txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated @@ -1834,9 +1953,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd blockundo.vtxundo.push_back(CTxUndo()); } UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); - - vPos.push_back(std::make_pair(tx.GetHash(), pos)); - pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal); @@ -1856,28 +1972,16 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd if (fJustCheck) return true; - // Write undo information to disk - if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) - { - if (pindex->GetUndoPos().IsNull()) { - CDiskBlockPos _pos; - if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) - return error("ConnectBlock(): FindUndoPos failed"); - if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) - return AbortNode(state, "Failed to write undo data"); - - // update nUndoPos in block index - pindex->nUndoPos = _pos.nPos; - pindex->nStatus |= BLOCK_HAVE_UNDO; - } + if (!WriteUndoDataForBlock(blockundo, state, pindex, chainparams)) + return false; + if (!pindex->IsValid(BLOCK_VALID_SCRIPTS)) { pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); setDirtyBlockIndex.insert(pindex); } - if (fTxIndex) - if (!pblocktree->WriteTxIndex(vPos)) - return AbortNode(state, "Failed to write transaction index"); + if (!WriteTxIndexDataForBlock(block, state, pindex)) + return false; assert(pindex->phashBlock); // add this block to the view's block chain @@ -2029,10 +2133,8 @@ static void DoWarning(const std::string& strWarning) } } -/** Update chainActive and related internal data structures. */ -void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { - chainActive.SetTip(pindexNew); - +/** Check warning conditions and do some notifications on new chain tip set. */ +void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) { // New best block mempool.AddTransactionsUpdated(1); @@ -2042,7 +2144,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { if (!IsInitialBlockDownload()) { int nUpgraded = 0; - const CBlockIndex* pindex = chainActive.Tip(); + const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); @@ -2073,10 +2175,10 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { } } LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, - log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), - GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, + log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime()), + GuessVerificationProgress(chainParams.TxData(), pindexNew), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); if (!warningMessages.empty()) LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); LogPrintf("\n"); @@ -2093,7 +2195,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { * disconnectpool (note that the caller is responsible for mempool consistency * in any case). */ -bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) +bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -2105,7 +2207,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // Apply the block atomically to the chain state. int64_t nStart = GetTimeMicros(); { - CCoinsViewCache view(pcoinsTip); + CCoinsViewCache view(pcoinsTip.get()); assert(view.GetBestBlock() == pindexDelete->GetBlockHash()); if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK) return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); @@ -2130,7 +2232,8 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara } } - // Update chainActive and related variables. + chainActive.SetTip(pindexDelete->pprev); + UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: @@ -2215,7 +2318,7 @@ public: * * The block is added to connectTrace if connection succeeds. */ -bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) +bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. @@ -2235,7 +2338,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime3; LogPrint(BCLog::BENCH, " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * MILLI, nTimeReadFromDisk * MICRO); { - CCoinsViewCache view(pcoinsTip); + CCoinsViewCache view(pcoinsTip.get()); bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, chainparams); GetMainSignals().BlockChecked(blockConnecting, state); if (!rv) { @@ -2259,6 +2362,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); disconnectpool.removeForBlock(blockConnecting.vtx); // Update chainActive & related variables. + chainActive.SetTip(pindexNew); UpdateTip(pindexNew, chainparams); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; @@ -2273,7 +2377,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, * Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). */ -static CBlockIndex* FindMostWorkChain() { +CBlockIndex* CChainState::FindMostWorkChain() { do { CBlockIndex *pindexNew = nullptr; @@ -2328,7 +2432,7 @@ static CBlockIndex* FindMostWorkChain() { } /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */ -static void PruneBlockIndexCandidates() { +void CChainState::PruneBlockIndexCandidates() { // Note that we can't delete the current block itself, as we may need to return to it later in case a // reorganization to a better block fails. std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin(); @@ -2343,7 +2447,7 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) +bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) { AssertLockHeld(cs_main); const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -2413,7 +2517,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // any disconnected transactions back to the mempool. UpdateMempoolForReorg(disconnectpool, true); } - mempool.check(pcoinsTip); + mempool.check(pcoinsTip.get()); // Callbacks/notifications for a new best chain. if (fInvalidFound) @@ -2450,7 +2554,7 @@ static void NotifyHeaderTip() { * or an activated best chain. pblock is either nullptr or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { +bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { // Note that while we're often called here from ProcessNewBlock, this is // far from a guarantee. Things in the P2P/RPC will often end up calling // us in the middle of ProcessNewBlock - do not assume pblock is set @@ -2494,7 +2598,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) { assert(trace.pblock && trace.pindex); - GetMainSignals().BlockConnected(trace.pblock, trace.pindex, *trace.conflictedTxs); + GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs); } } // When we reach this point, we switched to a new tip (stored in pindexNewTip). @@ -2520,9 +2624,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return true; } +bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { + return g_chainstate.ActivateBestChain(state, chainparams, std::move(pblock)); +} - -bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) +bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) { { LOCK(cs_main); @@ -2548,10 +2654,13 @@ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIn } } - return ActivateBestChain(state, params); + return ActivateBestChain(state, params, std::shared_ptr<const CBlock>()); +} +bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) { + return g_chainstate.PreciousBlock(state, params, pindex); } -bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) +bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -2610,8 +2719,11 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); return true; } +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { + return g_chainstate.InvalidateBlock(state, chainparams, pindex); +} -bool ResetBlockFailureFlags(CBlockIndex *pindex) { +bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { AssertLockHeld(cs_main); int nHeight = pindex->nHeight; @@ -2644,8 +2756,11 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) { } return true; } +bool ResetBlockFailureFlags(CBlockIndex *pindex) { + return g_chainstate.ResetBlockFailureFlags(pindex); +} -static CBlockIndex* AddToBlockIndex(const CBlockHeader& block) +CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block) { // Check for duplicate uint256 hash = block.GetHash(); @@ -2680,7 +2795,7 @@ static CBlockIndex* AddToBlockIndex(const CBlockHeader& block) } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -static bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) +bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) { pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; @@ -2728,7 +2843,7 @@ static bool ReceivedBlockTransactions(const CBlock &block, CValidationState& sta return true; } -static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -2777,7 +2892,7 @@ static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned i } } else - return state.Error("out of disk space"); + return error("out of disk space"); } } @@ -2952,7 +3067,13 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO - * set; UTXO-related validity checks are done in ConnectBlock(). */ + * set; UTXO-related validity checks are done in ConnectBlock(). + * NOTE: This function is not currently invoked by ConnectBlock(), so we + * should consider upgrade issues if we change which consensus rules are + * enforced in this function (eg by adding a new consensus rule). See comment + * in ConnectBlock(). + * Note that -reindex-chainstate skips the validation that happens here! + */ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) { assert(pindexPrev != nullptr); @@ -2992,6 +3113,12 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta return true; } +/** NOTE: This function is not currently invoked by ConnectBlock(), so we + * should consider upgrade issues if we change which consensus rules are + * enforced in this function (eg by adding a new consensus rule). See comment + * in ConnectBlock(). + * Note that -reindex-chainstate skips the validation that happens here! + */ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; @@ -3073,7 +3200,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c return true; } -static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) +bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) { AssertLockHeld(cs_main); // Check for duplicate @@ -3140,7 +3267,7 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio LOCK(cs_main); for (const CBlockHeader& header : headers) { CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast - if (!AcceptBlockHeader(header, state, chainparams, &pindex)) { + if (!g_chainstate.AcceptBlockHeader(header, state, chainparams, &pindex)) { if (first_invalid) *first_invalid = header; return false; } @@ -3154,7 +3281,26 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio } /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) +static CDiskBlockPos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const CDiskBlockPos* dbp) { + unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); + CDiskBlockPos blockPos; + if (dbp != nullptr) + blockPos = *dbp; + if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) { + error("%s: FindBlockPos failed", __func__); + return CDiskBlockPos(); + } + if (dbp == nullptr) { + if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { + AbortNode("Failed to write block"); + return CDiskBlockPos(); + } + } + return blockPos; +} + +/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ +bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) { const CBlock& block = *pblock; @@ -3214,19 +3360,13 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation if (!IsInitialBlockDownload() && chainActive.Tip() == pindex->pprev) GetMainSignals().NewPoWValidBlock(pindex, pblock); - int nHeight = pindex->nHeight; - // Write block to history file try { - unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; - if (dbp != nullptr) - blockPos = *dbp; - if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) - return error("AcceptBlock(): FindBlockPos failed"); - if (dbp == nullptr) - if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) - AbortNode(state, "Failed to write block"); + 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"); } catch (const std::runtime_error& e) { @@ -3236,6 +3376,8 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation if (fCheckForPruning) FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files + CheckBlockIndex(chainparams.GetConsensus()); + return true; } @@ -3253,9 +3395,8 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons if (ret) { // Store to disk - ret = AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); + ret = g_chainstate.AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); } - CheckBlockIndex(chainparams.GetConsensus()); if (!ret) { GetMainSignals().BlockChecked(*pblock, state); return error("%s: AcceptBlock FAILED (%s)", __func__, state.GetDebugMessage()); @@ -3265,7 +3406,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons NotifyHeaderTip(); CValidationState state; // Only used to report errors, not invalidity - ignore it - if (!ActivateBestChain(state, chainparams, pblock)) + if (!g_chainstate.ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -3275,7 +3416,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, { AssertLockHeld(cs_main); assert(pindexPrev && pindexPrev == chainActive.Tip()); - CCoinsViewCache viewNew(pcoinsTip); + CCoinsViewCache viewNew(pcoinsTip.get()); CBlockIndex indexDummy(block); indexDummy.pprev = pindexPrev; indexDummy.nHeight = pindexPrev->nHeight + 1; @@ -3287,7 +3428,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); - if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) + if (!g_chainstate.ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -3315,8 +3456,8 @@ void PruneOneBlockFile(const int fileNumber) { LOCK(cs_LastBlockFile); - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) { - CBlockIndex* pindex = it->second; + for (const auto& entry : mapBlockIndex) { + CBlockIndex* pindex = entry.second; if (pindex->nFile == fileNumber) { pindex->nStatus &= ~BLOCK_HAVE_DATA; pindex->nStatus &= ~BLOCK_HAVE_UNDO; @@ -3464,7 +3605,7 @@ static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fRe return nullptr; fs::path path = GetBlockPosFilename(pos, prefix); fs::create_directories(path.parent_path()); - FILE* file = fsbridge::fopen(path, "rb+"); + FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+"); if (!file && !fReadOnly) file = fsbridge::fopen(path, "wb+"); if (!file) { @@ -3495,7 +3636,7 @@ fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile); } -CBlockIndex * InsertBlockIndex(uint256 hash) +CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash) { if (hash.IsNull()) return nullptr; @@ -3513,9 +3654,9 @@ CBlockIndex * InsertBlockIndex(uint256 hash) return pindexNew; } -bool static LoadBlockIndexDB(const CChainParams& chainparams) +bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) { - if (!pblocktree->LoadBlockIndexGuts(chainparams.GetConsensus(), InsertBlockIndex)) + if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash){ return this->InsertBlockIndex(hash); })) return false; boost::this_thread::interruption_point(); @@ -3562,6 +3703,14 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) pindexBestHeader = pindex; } + return true; +} + +bool static LoadBlockIndexDB(const CChainParams& chainparams) +{ + if (!g_chainstate.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree)) + return false; + // Load block file info pblocktree->ReadLastBlockFile(nLastBlockFile); vinfoBlockFile.resize(nLastBlockFile + 1); @@ -3634,7 +3783,7 @@ bool LoadChainTip(const CChainParams& chainparams) return false; chainActive.SetTip(it->second); - PruneBlockIndexCandidates(); + g_chainstate.PruneBlockIndexCandidates(); LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), @@ -3699,16 +3848,16 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; - CDiskBlockPos pos = pindex->GetUndoPos(); - if (!pos.IsNull()) { - if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) + if (!pindex->GetUndoPos().IsNull()) { + if (!UndoReadFromDisk(undo, pindex)) { return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + } } } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); - DisconnectResult res = DisconnectBlock(block, pindex, coins); + DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -3736,7 +3885,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins, chainparams)) + if (!g_chainstate.ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } @@ -3748,7 +3897,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } /** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */ -static bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) +bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) { // TODO: merge with ConnectBlock CBlock block; @@ -3768,7 +3917,7 @@ static bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, return true; } -bool ReplayBlocks(const CChainParams& params, CCoinsView* view) +bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view) { LOCK(cs_main); @@ -3833,7 +3982,11 @@ bool ReplayBlocks(const CChainParams& params, CCoinsView* view) return true; } -bool RewindBlockIndex(const CChainParams& params) +bool ReplayBlocks(const CChainParams& params, CCoinsView* view) { + return g_chainstate.ReplayBlocks(params, view); +} + +bool CChainState::RewindBlockIndex(const CChainParams& params) { LOCK(cs_main); @@ -3870,8 +4023,8 @@ bool RewindBlockIndex(const CChainParams& params) // Reduce validity flag and have-data flags. // We do this after actual disconnecting, otherwise we'll end up writing the lack of data // to disk before writing the chainstate, resulting in a failure to continue if interrupted. - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { - CBlockIndex* pindexIter = it->second; + for (const auto& entry : mapBlockIndex) { + CBlockIndex* pindexIter = entry.second; // Note: If we encounter an insufficiently validated block that // is on chainActive, it must be because we are a pruning node, and @@ -3914,10 +4067,21 @@ bool RewindBlockIndex(const CChainParams& params) PruneBlockIndexCandidates(); CheckBlockIndex(params.GetConsensus()); + } + return true; +} + +bool RewindBlockIndex(const CChainParams& params) { + if (!g_chainstate.RewindBlockIndex(params)) { + return false; + } + + if (chainActive.Tip() != nullptr) { // FlushStateToDisk can possibly read chainActive. Be conservative // and skip it here, we're about to -reindex-chainstate anyway, so // it'll get called a bunch real soon. + CValidationState state; if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) { return false; } @@ -3926,13 +4090,18 @@ bool RewindBlockIndex(const CChainParams& params) return true; } +void CChainState::UnloadBlockIndex() { + nBlockSequenceId = 1; + g_failed_blocks.clear(); + setBlockIndexCandidates.clear(); +} + // May NOT be used after any connections are up as much // of the peer-processing logic assumes a consistent // block index state void UnloadBlockIndex() { LOCK(cs_main); - setBlockIndexCandidates.clear(); chainActive.SetTip(nullptr); pindexBestInvalid = nullptr; pindexBestHeader = nullptr; @@ -3940,9 +4109,7 @@ void UnloadBlockIndex() mapBlocksUnlinked.clear(); vinfoBlockFile.clear(); nLastBlockFile = 0; - nBlockSequenceId = 1; setDirtyBlockIndex.clear(); - g_failed_blocks.clear(); setDirtyFileInfo.clear(); versionbitscache.Clear(); for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { @@ -3954,6 +4121,8 @@ void UnloadBlockIndex() } mapBlockIndex.clear(); fHavePruned = false; + + g_chainstate.UnloadBlockIndex(); } bool LoadBlockIndex(const CChainParams& chainparams) @@ -3981,7 +4150,7 @@ bool LoadBlockIndex(const CChainParams& chainparams) return true; } -bool LoadGenesisBlock(const CChainParams& chainparams) +bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) { LOCK(cs_main); @@ -3994,15 +4163,11 @@ bool LoadGenesisBlock(const CChainParams& chainparams) try { CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock()); - // Start new block file - unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; - CValidationState state; - if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime())) - return error("%s: FindBlockPos failed", __func__); - if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) + CDiskBlockPos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); + 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", __func__); } catch (const std::runtime_error& e) { @@ -4012,6 +4177,11 @@ bool LoadGenesisBlock(const CChainParams& chainparams) return true; } +bool LoadGenesisBlock(const CChainParams& chainparams) +{ + return g_chainstate.LoadGenesisBlock(chainparams); +} + bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) @@ -4072,7 +4242,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { LOCK(cs_main); CValidationState state; - if (AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) + if (g_chainstate.AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) nLoaded++; if (state.IsError()) break; @@ -4106,7 +4276,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB head.ToString()); LOCK(cs_main); CValidationState dummy; - if (AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) + if (g_chainstate.AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) { nLoaded++; queue.push_back(pblockrecursive->GetHash()); @@ -4129,7 +4299,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB return nLoaded > 0; } -void static CheckBlockIndex(const Consensus::Params& consensusParams) +void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams) { if (!fCheckBlockIndex) { return; @@ -4147,8 +4317,8 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams) // Build forward-pointing map of the entire block tree. std::multimap<CBlockIndex*,CBlockIndex*> forward; - for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) { - forward.insert(std::make_pair(it->second->pprev, it->second)); + for (auto& entry : mapBlockIndex) { + forward.insert(std::make_pair(entry.second->pprev, entry.second)); } assert(forward.size() == mapBlockIndex.size()); @@ -4471,7 +4641,7 @@ bool DumpMempool(void) } //! Guess how far we are in the verification process at the given block index -double GuessVerificationProgress(const ChainTxData& data, CBlockIndex *pindex) { +double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) { if (pindex == nullptr) return 0.0; diff --git a/src/validation.h b/src/validation.h index 93669de6c4..4c8e041af0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -7,17 +7,17 @@ #define BITCOIN_VALIDATION_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif -#include "amount.h" -#include "coins.h" -#include "fs.h" -#include "protocol.h" // For CMessageHeader::MessageStartChars -#include "policy/feerate.h" -#include "script/script_error.h" -#include "sync.h" -#include "versionbits.h" +#include <amount.h> +#include <coins.h> +#include <fs.h> +#include <protocol.h> // For CMessageHeader::MessageStartChars +#include <policy/feerate.h> +#include <script/script_error.h> +#include <sync.h> +#include <versionbits.h> #include <algorithm> #include <exception> @@ -159,7 +159,7 @@ extern CCriticalSection cs_main; extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap; -extern BlockMap mapBlockIndex; +extern BlockMap& mapBlockIndex; extern uint64_t nLastBlockTx; extern uint64_t nLastBlockWeight; extern const std::string strMessageMagic; @@ -203,6 +203,8 @@ extern bool fPruneMode; extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ static const unsigned int MIN_BLOCKS_TO_KEEP = 288; +/** Minimum blocks required to signal NODE_NETWORK_LIMITED */ +static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288; static const signed int DEFAULT_CHECKBLOCKS = 6; static const unsigned int DEFAULT_CHECKLEVEL = 3; @@ -273,13 +275,13 @@ void ThreadScriptCheck(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ 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); +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 */ 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); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ -double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex); +double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex* pindex); /** Calculate the amount of disk space the block & undo files currently use */ uint64_t CalculateCurrentUsage(); @@ -294,8 +296,6 @@ void PruneOneBlockFile(const int fileNumber); */ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); -/** Create a new block index entry for a given block hash */ -CBlockIndex * InsertBlockIndex(uint256 hash); /** Flush all state, indexes and buffers to disk. */ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ @@ -441,16 +441,16 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C bool ResetBlockFailureFlags(CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ -extern CChain chainActive; +extern CChain& chainActive; /** Global variable that points to the coins database (protected by cs_main) */ -extern CCoinsViewDB *pcoinsdbview; +extern std::unique_ptr<CCoinsViewDB> pcoinsdbview; /** Global variable that points to the active CCoinsView (protected by cs_main) */ -extern CCoinsViewCache *pcoinsTip; +extern std::unique_ptr<CCoinsViewCache> pcoinsTip; /** Global variable that points to the active block tree (protected by cs_main) */ -extern CBlockTreeDB *pblocktree; +extern std::unique_ptr<CBlockTreeDB> pblocktree; /** * Return the spend height, which is one more than the inputs.GetBestBlock(). diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 281bc04b0a..abbd8cc4d2 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -3,13 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "validationinterface.h" +#include <validationinterface.h> -#include "init.h" -#include "primitives/block.h" -#include "scheduler.h" -#include "sync.h" -#include "util.h" +#include <init.h> +#include <primitives/block.h> +#include <scheduler.h> +#include <sync.h> +#include <txmempool.h> +#include <util.h> #include <list> #include <atomic> @@ -21,6 +22,7 @@ struct MainSignalsInstance { boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool; boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected; boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected; + boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool; boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; boost::signals2::signal<void (const uint256 &)> Inventory; boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast; @@ -47,7 +49,17 @@ void CMainSignals::UnregisterBackgroundSignalScheduler() { } void CMainSignals::FlushBackgroundCallbacks() { - m_internals->m_schedulerClient.EmptyQueue(); + if (m_internals) { + m_internals->m_schedulerClient.EmptyQueue(); + } +} + +void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) { + pool.NotifyEntryRemoved.connect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); +} + +void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) { + pool.NotifyEntryRemoved.disconnect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); } CMainSignals& GetMainSignals() @@ -60,6 +72,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); @@ -75,11 +88,15 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.m_internals->TransactionRemovedFromMempool.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); } void UnregisterAllValidationInterfaces() { + if (!g_signals.m_internals) { + return; + } g_signals.m_internals->BlockChecked.disconnect_all_slots(); g_signals.m_internals->Broadcast.disconnect_all_slots(); g_signals.m_internals->Inventory.disconnect_all_slots(); @@ -87,32 +104,57 @@ void UnregisterAllValidationInterfaces() { g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots(); g_signals.m_internals->BlockConnected.disconnect_all_slots(); g_signals.m_internals->BlockDisconnected.disconnect_all_slots(); + g_signals.m_internals->TransactionRemovedFromMempool.disconnect_all_slots(); g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots(); g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots(); } +void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) { + g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func)); +} + +void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason reason) { + if (reason != MemPoolRemovalReason::BLOCK && reason != MemPoolRemovalReason::CONFLICT) { + m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] { + m_internals->TransactionRemovedFromMempool(ptx); + }); + } +} + void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { - m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); + m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, fInitialDownload, this] { + m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); + }); } void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { - m_internals->TransactionAddedToMempool(ptx); + m_internals->m_schedulerClient.AddToProcessQueue([ptx, this] { + m_internals->TransactionAddedToMempool(ptx); + }); } -void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) { - m_internals->BlockConnected(pblock, pindex, vtxConflicted); +void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>>& pvtxConflicted) { + m_internals->m_schedulerClient.AddToProcessQueue([pblock, pindex, pvtxConflicted, this] { + m_internals->BlockConnected(pblock, pindex, *pvtxConflicted); + }); } void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) { - m_internals->BlockDisconnected(pblock); + m_internals->m_schedulerClient.AddToProcessQueue([pblock, this] { + m_internals->BlockDisconnected(pblock); + }); } void CMainSignals::SetBestChain(const CBlockLocator &locator) { - m_internals->SetBestChain(locator); + m_internals->m_schedulerClient.AddToProcessQueue([locator, this] { + m_internals->SetBestChain(locator); + }); } void CMainSignals::Inventory(const uint256 &hash) { - m_internals->Inventory(hash); + m_internals->m_schedulerClient.AddToProcessQueue([hash, this] { + m_internals->Inventory(hash); + }); } void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) { diff --git a/src/validationinterface.h b/src/validationinterface.h index d6da2bc1fd..7b5d138414 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -6,9 +6,10 @@ #ifndef BITCOIN_VALIDATIONINTERFACE_H #define BITCOIN_VALIDATIONINTERFACE_H -#include <memory> +#include <primitives/transaction.h> // CTransaction(Ref) -#include "primitives/transaction.h" // CTransaction(Ref) +#include <functional> +#include <memory> class CBlock; class CBlockIndex; @@ -20,6 +21,8 @@ class CValidationInterface; class CValidationState; class uint256; class CScheduler; +class CTxMemPool; +enum class MemPoolRemovalReason; // These functions dispatch to one or all registered wallets @@ -29,23 +32,66 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn); void UnregisterValidationInterface(CValidationInterface* pwalletIn); /** Unregister all wallets from core */ void UnregisterAllValidationInterfaces(); +/** + * Pushes a function to callback onto the notification queue, guaranteeing any + * callbacks generated prior to now are finished when the function is called. + * + * Be very careful blocking on func to be called if any locks are held - + * validation interface clients may not be able to make progress as they often + * wait for things like cs_main, so blocking until func is called with cs_main + * will result in a deadlock (that DEBUG_LOCKORDER will miss). + */ +void CallFunctionInValidationInterfaceQueue(std::function<void ()> func); class CValidationInterface { protected: - /** Notifies listeners of updated block chain tip */ + /** + * Notifies listeners of updated block chain tip + * + * Called on a background thread. + */ virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} - /** Notifies listeners of a transaction having been added to mempool. */ + /** + * Notifies listeners of a transaction having been added to mempool. + * + * Called on a background thread. + */ virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} /** + * Notifies listeners of a transaction leaving mempool. + * + * This only fires for transactions which leave mempool because of expiry, + * size limiting, reorg (changes in lock times/coinbase maturity), or + * replacement. This does not include any transactions which are included + * in BlockConnectedDisconnected either in block->vtx or in txnConflicted. + * + * Called on a background thread. + */ + virtual void TransactionRemovedFromMempool(const CTransactionRef &ptx) {} + /** * Notifies listeners of a block being connected. * Provides a vector of transactions evicted from the mempool as a result. + * + * Called on a background thread. */ virtual void BlockConnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, const std::vector<CTransactionRef> &txnConflicted) {} - /** Notifies listeners of a block being disconnected */ + /** + * Notifies listeners of a block being disconnected + * + * Called on a background thread. + */ virtual void BlockDisconnected(const std::shared_ptr<const CBlock> &block) {} - /** Notifies listeners of the new active block chain on-disk. */ + /** + * Notifies listeners of the new active block chain on-disk. + * + * Called on a background thread. + */ virtual void SetBestChain(const CBlockLocator &locator) {} - /** Notifies listeners about an inventory item being seen on the network. */ + /** + * Notifies listeners about an inventory item being seen on the network. + * + * Called on a background thread. + */ virtual void Inventory(const uint256 &hash) {} /** Tells listeners to broadcast their data. */ virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} @@ -73,6 +119,9 @@ private: friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); + friend void ::CallFunctionInValidationInterfaceQueue(std::function<void ()> func); + + void MempoolEntryRemoved(CTransactionRef tx, MemPoolRemovalReason reason); public: /** Register a CScheduler to give callbacks which should run in the background (may only be called once) */ @@ -82,9 +131,14 @@ public: /** Call any remaining callbacks on the calling thread */ void FlushBackgroundCallbacks(); + /** Register with mempool to call TransactionRemovedFromMempool callbacks */ + void RegisterWithMempoolSignals(CTxMemPool& pool); + /** Unregister with mempool */ + void UnregisterWithMempoolSignals(CTxMemPool& pool); + void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void TransactionAddedToMempool(const CTransactionRef &); - void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef> &); + void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &); void BlockDisconnected(const std::shared_ptr<const CBlock> &); void SetBestChain(const CBlockLocator &); void Inventory(const uint256 &); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index fc1acb3258..3bd00ccb23 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "versionbits.h" -#include "consensus/params.h" +#include <versionbits.h> +#include <consensus/params.h> const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { { diff --git a/src/versionbits.h b/src/versionbits.h index 71dc0c8500..0e111ed7a1 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_CONSENSUS_VERSIONBITS #define BITCOIN_CONSENSUS_VERSIONBITS -#include "chain.h" +#include <chain.h> #include <map> /** What block version to use for new blocks (pre versionbits) */ diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index fc0e7c519e..15fd105779 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -5,10 +5,10 @@ #ifndef BITCOIN_WALLET_COINCONTROL_H #define BITCOIN_WALLET_COINCONTROL_H -#include "policy/feerate.h" -#include "policy/fees.h" -#include "primitives/transaction.h" -#include "wallet/wallet.h" +#include <policy/feerate.h> +#include <policy/fees.h> +#include <primitives/transaction.h> +#include <wallet/wallet.h> #include <boost/optional.hpp> diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 8db3bfd69c..4cd7db048b 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypter.h" +#include <wallet/crypter.h> -#include "crypto/aes.h" -#include "crypto/sha512.h" -#include "script/script.h" -#include "script/standard.h" -#include "util.h" +#include <crypto/aes.h> +#include <crypto/sha512.h> +#include <script/script.h> +#include <script/standard.h> +#include <util.h> #include <string> #include <vector> @@ -152,6 +152,15 @@ bool CCryptoKeyStore::SetCrypted() return true; } +bool CCryptoKeyStore::IsLocked() const +{ + if (!IsCrypted()) { + return false; + } + LOCK(cs_KeyStore); + return vMasterKey.empty(); +} + bool CCryptoKeyStore::Lock() { if (!SetCrypted()) @@ -206,21 +215,23 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) { - { - LOCK(cs_KeyStore); - if (!IsCrypted()) - return CBasicKeyStore::AddKeyPubKey(key, pubkey); + LOCK(cs_KeyStore); + if (!IsCrypted()) { + return CBasicKeyStore::AddKeyPubKey(key, pubkey); + } - if (IsLocked()) - return false; + if (IsLocked()) { + return false; + } - std::vector<unsigned char> vchCryptedSecret; - CKeyingMaterial vchSecret(key.begin(), key.end()); - if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) - return false; + std::vector<unsigned char> vchCryptedSecret; + CKeyingMaterial vchSecret(key.begin(), key.end()); + if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) { + return false; + } - if (!AddCryptedKey(pubkey, vchCryptedSecret)) - return false; + if (!AddCryptedKey(pubkey, vchCryptedSecret)) { + return false; } return true; } @@ -228,72 +239,88 @@ bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { - { - LOCK(cs_KeyStore); - if (!SetCrypted()) - return false; - - mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret); + LOCK(cs_KeyStore); + if (!SetCrypted()) { + return false; } + + mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret); return true; } +bool CCryptoKeyStore::HaveKey(const CKeyID &address) const +{ + LOCK(cs_KeyStore); + if (!IsCrypted()) { + return CBasicKeyStore::HaveKey(address); + } + return mapCryptedKeys.count(address) > 0; +} + bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const { - { - LOCK(cs_KeyStore); - if (!IsCrypted()) - return CBasicKeyStore::GetKey(address, keyOut); + LOCK(cs_KeyStore); + if (!IsCrypted()) { + return CBasicKeyStore::GetKey(address, keyOut); + } - CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); - if (mi != mapCryptedKeys.end()) - { - const CPubKey &vchPubKey = (*mi).second.first; - const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second; - return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut); - } + CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); + if (mi != mapCryptedKeys.end()) + { + const CPubKey &vchPubKey = (*mi).second.first; + const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second; + return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut); } return false; } bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::GetPubKey(address, vchPubKeyOut); + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); + if (mi != mapCryptedKeys.end()) { - LOCK(cs_KeyStore); - if (!IsCrypted()) - return CBasicKeyStore::GetPubKey(address, vchPubKeyOut); + vchPubKeyOut = (*mi).second.first; + return true; + } + // Check for watch-only pubkeys + return CBasicKeyStore::GetPubKey(address, vchPubKeyOut); +} - CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); - if (mi != mapCryptedKeys.end()) - { - vchPubKeyOut = (*mi).second.first; - return true; - } - // Check for watch-only pubkeys - return CBasicKeyStore::GetPubKey(address, vchPubKeyOut); +std::set<CKeyID> CCryptoKeyStore::GetKeys() const +{ + LOCK(cs_KeyStore); + if (!IsCrypted()) { + return CBasicKeyStore::GetKeys(); } + std::set<CKeyID> set_address; + for (const auto& mi : mapCryptedKeys) { + set_address.insert(mi.first); + } + return set_address; } bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) { + LOCK(cs_KeyStore); + if (!mapCryptedKeys.empty() || IsCrypted()) + return false; + + fUseCrypto = true; + for (KeyMap::value_type& mKey : mapKeys) { - LOCK(cs_KeyStore); - if (!mapCryptedKeys.empty() || IsCrypted()) + const CKey &key = mKey.second; + CPubKey vchPubKey = key.GetPubKey(); + CKeyingMaterial vchSecret(key.begin(), key.end()); + std::vector<unsigned char> vchCryptedSecret; + if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) + return false; + if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) return false; - - fUseCrypto = true; - for (KeyMap::value_type& mKey : mapKeys) - { - const CKey &key = mKey.second; - CPubKey vchPubKey = key.GetPubKey(); - CKeyingMaterial vchSecret(key.begin(), key.end()); - std::vector<unsigned char> vchCryptedSecret; - if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) - return false; - if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) - return false; - } - mapKeys.clear(); } + mapKeys.clear(); return true; } diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 1416ae7d02..7b0936ba0d 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -5,9 +5,9 @@ #ifndef BITCOIN_WALLET_CRYPTER_H #define BITCOIN_WALLET_CRYPTER_H -#include "keystore.h" -#include "serialize.h" -#include "support/allocators/secure.h" +#include <keystore.h> +#include <serialize.h> +#include <support/allocators/secure.h> #include <atomic> @@ -139,52 +139,16 @@ public: { } - bool IsCrypted() const - { - return fUseCrypto; - } - - bool IsLocked() const - { - if (!IsCrypted()) - return false; - bool result; - { - LOCK(cs_KeyStore); - result = vMasterKey.empty(); - } - return result; - } - + bool IsCrypted() const { return fUseCrypto; } + bool IsLocked() const; bool Lock(); virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret); bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; - bool HaveKey(const CKeyID &address) const override - { - { - LOCK(cs_KeyStore); - if (!IsCrypted()) { - return CBasicKeyStore::HaveKey(address); - } - return mapCryptedKeys.count(address) > 0; - } - return false; - } + bool HaveKey(const CKeyID &address) const override; bool GetKey(const CKeyID &address, CKey& keyOut) const override; bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override; - std::set<CKeyID> GetKeys() const override - { - LOCK(cs_KeyStore); - if (!IsCrypted()) { - return CBasicKeyStore::GetKeys(); - } - std::set<CKeyID> set_address; - for (const auto& mi : mapCryptedKeys) { - set_address.insert(mi.first); - } - return set_address; - } + std::set<CKeyID> GetKeys() const override; /** * Wallet status (encrypted, locked) changed. diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 5d48b01c2e..d4cd30dfac 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -3,14 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "db.h" +#include <wallet/db.h> -#include "addrman.h" -#include "fs.h" -#include "hash.h" -#include "protocol.h" -#include "util.h" -#include "utilstrencodings.h" +#include <addrman.h> +#include <hash.h> +#include <protocol.h> +#include <util.h> +#include <utilstrencodings.h> +#include <wallet/walletutil.h> #include <stdint.h> @@ -75,13 +75,12 @@ void CDBEnv::EnvShutdown() void CDBEnv::Reset() { - delete dbenv; - dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS); + dbenv.reset(new DbEnv(DB_CXX_NO_EXCEPTIONS)); fDbEnvInit = false; fMockDb = false; } -CDBEnv::CDBEnv() : dbenv(nullptr) +CDBEnv::CDBEnv() { Reset(); } @@ -89,8 +88,6 @@ CDBEnv::CDBEnv() : dbenv(nullptr) CDBEnv::~CDBEnv() { EnvShutdown(); - delete dbenv; - dbenv = nullptr; } void CDBEnv::Close() @@ -182,7 +179,7 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); - Db db(dbenv, 0); + Db db(dbenv.get(), 0); int result = db.verify(strFile.c_str(), nullptr, nullptr, 0); if (result == 0) return VERIFY_OK; @@ -225,7 +222,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco } LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); - std::unique_ptr<Db> pdbCopy(new Db(bitdb.dbenv, 0)); + std::unique_ptr<Db> pdbCopy = MakeUnique<Db>(bitdb.dbenv.get(), 0); int ret = pdbCopy->open(nullptr, // Txn pointer filename.c_str(), // Filename "main", // Logical db name @@ -260,7 +257,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco return fSuccess; } -bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) +bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr) { LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); LogPrintf("Using wallet %s\n", walletFile); @@ -268,15 +265,15 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD // Wallet file must be a plain filename without a directory if (walletFile != fs::basename(walletFile) + fs::extension(walletFile)) { - errorStr = strprintf(_("Wallet %s resides outside data directory %s"), walletFile, dataDir.string()); + errorStr = strprintf(_("Wallet %s resides outside wallet directory %s"), walletFile, walletDir.string()); return false; } - if (!bitdb.Open(dataDir)) + if (!bitdb.Open(walletDir)) { // try moving the database env out of the way - fs::path pathDatabase = dataDir / "database"; - fs::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); + fs::path pathDatabase = walletDir / "database"; + fs::path pathDatabaseBak = walletDir / strprintf("database.%d.bak", GetTime()); try { fs::rename(pathDatabase, pathDatabaseBak); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); @@ -285,18 +282,18 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD } // try again - if (!bitdb.Open(dataDir)) { + if (!bitdb.Open(walletDir)) { // if it still fails, it probably means we can't even create the database env - errorStr = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); + errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir); return false; } } return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) { - if (fs::exists(dataDir / walletFile)) + if (fs::exists(walletDir / walletFile)) { std::string backup_filename; CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); @@ -306,7 +303,7 @@ bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& data " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, backup_filename, dataDir); + walletFile, backup_filename, walletDir); } if (r == CDBEnv::RECOVER_FAIL) { @@ -334,7 +331,7 @@ bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector<C std::stringstream strDump; - Db db(dbenv, 0); + Db db(dbenv.get(), 0); int result = db.verify(strFile.c_str(), nullptr, &strDump, flags); if (result == DB_VERIFY_BAD) { LogPrintf("CDBEnv::Salvage: Database salvage found errors, all data may not be recoverable.\n"); @@ -410,13 +407,13 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb { LOCK(env->cs_db); - if (!env->Open(GetDataDir())) + if (!env->Open(GetWalletDir())) throw std::runtime_error("CDB: Failed to open database environment."); pdb = env->mapDb[strFilename]; if (pdb == nullptr) { int ret; - std::unique_ptr<Db> pdb_temp(new Db(env->dbenv, 0)); + std::unique_ptr<Db> pdb_temp = MakeUnique<Db>(env->dbenv.get(), 0); bool fMockDb = env->IsMock(); if (fMockDb) { @@ -525,7 +522,7 @@ bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip) std::string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(dbw, "r"); - Db* pdbCopy = new Db(env->dbenv, 0); + std::unique_ptr<Db> pdbCopy = MakeUnique<Db>(env->dbenv.get(), 0); int ret = pdbCopy->open(nullptr, // Txn pointer strFileRes.c_str(), // Filename @@ -574,13 +571,12 @@ bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip) } else { pdbCopy->close(0); } - delete pdbCopy; } if (fSuccess) { - Db dbA(env->dbenv, 0); + Db dbA(env->dbenv.get(), 0); if (dbA.remove(strFile.c_str(), nullptr, 0)) fSuccess = false; - Db dbB(env->dbenv, 0); + Db dbB(env->dbenv.get(), 0); if (dbB.rename(strFileRes.c_str(), nullptr, strFile.c_str(), 0)) fSuccess = false; } @@ -699,7 +695,7 @@ bool CWalletDBWrapper::Backup(const std::string& strDest) env->mapFileUseCount.erase(strFile); // Copy wallet file - fs::path pathSrc = GetDataDir() / strFile; + fs::path pathSrc = GetWalletDir() / strFile; fs::path pathDest(strDest); if (fs::is_directory(pathDest)) pathDest /= strFile; diff --git a/src/wallet/db.h b/src/wallet/db.h index 14283ac8f8..ed2ee65cac 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -6,12 +6,12 @@ #ifndef BITCOIN_WALLET_DB_H #define BITCOIN_WALLET_DB_H -#include "clientversion.h" -#include "fs.h" -#include "serialize.h" -#include "streams.h" -#include "sync.h" -#include "version.h" +#include <clientversion.h> +#include <fs.h> +#include <serialize.h> +#include <streams.h> +#include <sync.h> +#include <version.h> #include <atomic> #include <map> @@ -36,7 +36,7 @@ private: public: mutable CCriticalSection cs_db; - DbEnv *dbenv; + std::unique_ptr<DbEnv> dbenv; std::map<std::string, int> mapFileUseCount; std::map<std::string, Db*> mapDb; @@ -167,9 +167,9 @@ public: ideal to be called periodically */ static bool PeriodicFlush(CWalletDBWrapper& dbw); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); public: template <typename K, typename T> diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 8b7c50b4e9..9bfcab54a5 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -2,19 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "consensus/validation.h" -#include "wallet/coincontrol.h" -#include "wallet/feebumper.h" -#include "wallet/fees.h" -#include "wallet/wallet.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "validation.h" //for mempool access -#include "txmempool.h" -#include "utilmoneystr.h" -#include "util.h" -#include "net.h" +#include <consensus/validation.h> +#include <wallet/coincontrol.h> +#include <wallet/feebumper.h> +#include <wallet/fees.h> +#include <wallet/wallet.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <validation.h> //for mempool access +#include <txmempool.h> +#include <utilmoneystr.h> +#include <util.h> +#include <net.h> // Calculate the size of the transaction assuming all signatures are max size // Use DummySignatureCreator, which inserts 72 byte signatures everywhere. @@ -23,7 +23,7 @@ // calculation, but we should be able to refactor after priority is removed). // NOTE: this requires that all inputs must be in mapWallet (eg the tx should // be IsAllFromMe). -int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *pWallet) +static int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet) { CMutableTransaction txNew(tx); std::vector<CInputCoin> vCoins; @@ -31,11 +31,11 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *pWal // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our // wallet, with a valid index into the vout array. for (auto& input : tx.vin) { - const auto mi = pWallet->mapWallet.find(input.prevout.hash); - assert(mi != pWallet->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size()); + const auto mi = wallet->mapWallet.find(input.prevout.hash); + assert(mi != wallet->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size()); vCoins.emplace_back(CInputCoin(&(mi->second), input.prevout.n)); } - if (!pWallet->DummySignTx(txNew, vCoins)) { + if (!wallet->DummySignTx(txNew, vCoins)) { // This should never happen, because IsAllFromMe(ISMINE_SPENDABLE) // implies that we can sign for every input. return -1; @@ -43,103 +43,102 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *pWal return GetVirtualTransactionSize(txNew); } -bool CFeeBumper::preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx) { - if (pWallet->HasWalletSpend(wtx.GetHash())) { - vErrors.push_back("Transaction has descendants in the wallet"); - currentResult = BumpFeeResult::INVALID_PARAMETER; - return false; +//! Check whether transaction has descendant in wallet or mempool, or has been +//! mined, or conflicts with a mined transaction. Return a feebumper::Result. +static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) +{ + if (wallet->HasWalletSpend(wtx.GetHash())) { + errors.push_back("Transaction has descendants in the wallet"); + return feebumper::Result::INVALID_PARAMETER; } { LOCK(mempool.cs); auto it_mp = mempool.mapTx.find(wtx.GetHash()); if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) { - vErrors.push_back("Transaction has descendants in the mempool"); - currentResult = BumpFeeResult::INVALID_PARAMETER; - return false; + errors.push_back("Transaction has descendants in the mempool"); + return feebumper::Result::INVALID_PARAMETER; } } if (wtx.GetDepthInMainChain() != 0) { - vErrors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); - currentResult = BumpFeeResult::WALLET_ERROR; - return false; + errors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); + return feebumper::Result::WALLET_ERROR; } - return true; + return feebumper::Result::OK; } -CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, const CCoinControl& coin_control, CAmount totalFee) - : - txid(std::move(txidIn)), - nOldFee(0), - nNewFee(0) +namespace feebumper { + +bool TransactionCanBeBumped(CWallet* wallet, const uint256& txid) { - vErrors.clear(); - bumpedTxid.SetNull(); - AssertLockHeld(pWallet->cs_wallet); - auto it = pWallet->mapWallet.find(txid); - if (it == pWallet->mapWallet.end()) { - vErrors.push_back("Invalid or non-wallet transaction id"); - currentResult = BumpFeeResult::INVALID_ADDRESS_OR_KEY; - return; + LOCK2(cs_main, wallet->cs_wallet); + const CWalletTx* wtx = wallet->GetWalletTx(txid); + return wtx && SignalsOptInRBF(*wtx->tx) && !wtx->mapValue.count("replaced_by_txid"); +} + +Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors, + CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) +{ + LOCK2(cs_main, wallet->cs_wallet); + errors.clear(); + auto it = wallet->mapWallet.find(txid); + if (it == wallet->mapWallet.end()) { + errors.push_back("Invalid or non-wallet transaction id"); + return Result::INVALID_ADDRESS_OR_KEY; } const CWalletTx& wtx = it->second; - if (!preconditionChecks(pWallet, wtx)) { - return; + Result result = PreconditionChecks(wallet, wtx, errors); + if (result != Result::OK) { + return result; } if (!SignalsOptInRBF(*wtx.tx)) { - vErrors.push_back("Transaction is not BIP 125 replaceable"); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + errors.push_back("Transaction is not BIP 125 replaceable"); + return Result::WALLET_ERROR; } if (wtx.mapValue.count("replaced_by_txid")) { - vErrors.push_back(strprintf("Cannot bump transaction %s which was already bumped by transaction %s", txid.ToString(), wtx.mapValue.at("replaced_by_txid"))); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + errors.push_back(strprintf("Cannot bump transaction %s which was already bumped by transaction %s", txid.ToString(), wtx.mapValue.at("replaced_by_txid"))); + return Result::WALLET_ERROR; } // check that original tx consists entirely of our inputs // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee) - if (!pWallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { - vErrors.push_back("Transaction contains inputs that don't belong to this wallet"); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { + errors.push_back("Transaction contains inputs that don't belong to this wallet"); + return Result::WALLET_ERROR; } // figure out which output was change // if there was no change output or multiple change outputs, fail int nOutput = -1; for (size_t i = 0; i < wtx.tx->vout.size(); ++i) { - if (pWallet->IsChange(wtx.tx->vout[i])) { + if (wallet->IsChange(wtx.tx->vout[i])) { if (nOutput != -1) { - vErrors.push_back("Transaction has multiple change outputs"); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + errors.push_back("Transaction has multiple change outputs"); + return Result::WALLET_ERROR; } nOutput = i; } } if (nOutput == -1) { - vErrors.push_back("Transaction does not have a change output"); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + errors.push_back("Transaction does not have a change output"); + return Result::WALLET_ERROR; } // Calculate the expected size of the new transaction. int64_t txSize = GetVirtualTransactionSize(*(wtx.tx)); - const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, pWallet); + const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet); if (maxNewTxSize < 0) { - vErrors.push_back("Transaction contains inputs that cannot be signed"); - currentResult = BumpFeeResult::INVALID_ADDRESS_OR_KEY; - return; + errors.push_back("Transaction contains inputs that cannot be signed"); + return Result::INVALID_ADDRESS_OR_KEY; } // calculate the old fee and fee-rate - nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); - CFeeRate nOldFeeRate(nOldFee, txSize); + old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); + CFeeRate nOldFeeRate(old_fee, txSize); CFeeRate nNewFeeRate; // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to // future proof against changes to network wide policy for incremental relay @@ -149,26 +148,24 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, const CCoin walletIncrementalRelayFee = ::incrementalRelayFee; } - if (totalFee > 0) { + if (total_fee > 0) { CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize); - if (totalFee < minTotalFee) { - vErrors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", + if (total_fee < minTotalFee) { + errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize)))); - currentResult = BumpFeeResult::INVALID_PARAMETER; - return; + return Result::INVALID_PARAMETER; } CAmount requiredFee = GetRequiredFee(maxNewTxSize); - if (totalFee < requiredFee) { - vErrors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)", + if (total_fee < requiredFee) { + errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)", FormatMoney(requiredFee))); - currentResult = BumpFeeResult::INVALID_PARAMETER; - return; + return Result::INVALID_PARAMETER; } - nNewFee = totalFee; - nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); + new_fee = total_fee; + nNewFeeRate = CFeeRate(total_fee, maxNewTxSize); } else { - nNewFee = GetMinimumFee(maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */); - nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); + new_fee = GetMinimumFee(maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */); + nNewFeeRate = CFeeRate(new_fee, maxNewTxSize); // New fee rate must be at least old rate + minimum incremental relay rate // walletIncrementalRelayFee.GetFeePerK() should be exact, because it's initialized @@ -177,53 +174,50 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, const CCoin // add 1 satoshi to the result, because it may have been rounded down. if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK()) { nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK()); - nNewFee = nNewFeeRate.GetFee(maxNewTxSize); + new_fee = nNewFeeRate.GetFee(maxNewTxSize); } } // Check that in all cases the new fee doesn't violate maxTxFee - if (nNewFee > maxTxFee) { - vErrors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)", - FormatMoney(nNewFee), FormatMoney(maxTxFee))); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + if (new_fee > maxTxFee) { + errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)", + FormatMoney(new_fee), FormatMoney(maxTxFee))); + return Result::WALLET_ERROR; } // check that fee rate is higher than mempool's minimum fee // (no point in bumping fee if we know that the new tx won't be accepted to the mempool) // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a - // moment earlier. In this case, we report an error to the user, who may use totalFee to make an adjustment. + // moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment. CFeeRate minMempoolFeeRate = mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { - vErrors.push_back(strprintf( + errors.push_back(strprintf( "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " "the totalFee value should be at least %s or the settxfee value should be at least %s to add transaction", FormatMoney(nNewFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)), FormatMoney(minMempoolFeeRate.GetFeePerK()))); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + return Result::WALLET_ERROR; } // Now modify the output to increase the fee. // If the output is not large enough to pay the fee, fail. - CAmount nDelta = nNewFee - nOldFee; + CAmount nDelta = new_fee - old_fee; assert(nDelta > 0); mtx = *wtx.tx; CTxOut* poutput = &(mtx.vout[nOutput]); if (poutput->nValue < nDelta) { - vErrors.push_back("Change output is too small to bump the fee"); - currentResult = BumpFeeResult::WALLET_ERROR; - return; + errors.push_back("Change output is too small to bump the fee"); + return Result::WALLET_ERROR; } // If the output would become dust, discard it (converting the dust to fee) poutput->nValue -= nDelta; if (poutput->nValue <= GetDustThreshold(*poutput, ::dustRelayFee)) { LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n"); - nNewFee += poutput->nValue; + new_fee += poutput->nValue; mtx.vout.erase(mtx.vout.begin() + nOutput); } @@ -234,36 +228,36 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, const CCoin } } - currentResult = BumpFeeResult::OK; + return Result::OK; } -bool CFeeBumper::signTransaction(CWallet *pWallet) -{ - return pWallet->SignTransaction(mtx); +bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) { + LOCK2(cs_main, wallet->cs_wallet); + return wallet->SignTransaction(mtx); } -bool CFeeBumper::commit(CWallet *pWallet) +Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) { - AssertLockHeld(pWallet->cs_wallet); - if (!vErrors.empty() || currentResult != BumpFeeResult::OK) { - return false; + LOCK2(cs_main, wallet->cs_wallet); + if (!errors.empty()) { + return Result::MISC_ERROR; } - auto it = txid.IsNull() ? pWallet->mapWallet.end() : pWallet->mapWallet.find(txid); - if (it == pWallet->mapWallet.end()) { - vErrors.push_back("Invalid or non-wallet transaction id"); - currentResult = BumpFeeResult::MISC_ERROR; - return false; + auto it = txid.IsNull() ? wallet->mapWallet.end() : wallet->mapWallet.find(txid); + if (it == wallet->mapWallet.end()) { + errors.push_back("Invalid or non-wallet transaction id"); + return Result::MISC_ERROR; } CWalletTx& oldWtx = it->second; // make sure the transaction still has no descendants and hasn't been mined in the meantime - if (!preconditionChecks(pWallet, oldWtx)) { - return false; + Result result = PreconditionChecks(wallet, oldWtx, errors); + if (result != Result::OK) { + return result; } - CWalletTx wtxBumped(pWallet, MakeTransactionRef(std::move(mtx))); + CWalletTx wtxBumped(wallet, MakeTransactionRef(std::move(mtx))); // commit/broadcast the tx - CReserveKey reservekey(pWallet); + CReserveKey reservekey(wallet); wtxBumped.mapValue = oldWtx.mapValue; wtxBumped.mapValue["replaces_txid"] = oldWtx.GetHash().ToString(); wtxBumped.vOrderForm = oldWtx.vOrderForm; @@ -271,27 +265,29 @@ bool CFeeBumper::commit(CWallet *pWallet) wtxBumped.fTimeReceivedIsTxTime = true; wtxBumped.fFromMe = true; CValidationState state; - if (!pWallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) { + if (!wallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) { // NOTE: CommitTransaction never returns false, so this should never happen. - vErrors.push_back(strprintf("The transaction was rejected: %s", state.GetRejectReason())); - return false; + errors.push_back(strprintf("The transaction was rejected: %s", state.GetRejectReason())); + return Result::WALLET_ERROR; } - bumpedTxid = wtxBumped.GetHash(); + bumped_txid = wtxBumped.GetHash(); if (state.IsInvalid()) { // This can happen if the mempool rejected the transaction. Report // what happened in the "errors" response. - vErrors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state))); + errors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state))); } // mark the original tx as bumped - if (!pWallet->MarkReplaced(oldWtx.GetHash(), wtxBumped.GetHash())) { + if (!wallet->MarkReplaced(oldWtx.GetHash(), wtxBumped.GetHash())) { // TODO: see if JSON-RPC has a standard way of returning a response // along with an exception. It would be good to return information about // wtxBumped to the caller even if marking the original transaction // replaced does not succeed for some reason. - vErrors.push_back("Created new bumpfee transaction but could not mark the original transaction as replaced"); + errors.push_back("Created new bumpfee transaction but could not mark the original transaction as replaced"); } - return true; + return Result::OK; } +} // namespace feebumper + diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index 3d64e53c15..8eec30440c 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -13,7 +13,9 @@ class uint256; class CCoinControl; enum class FeeEstimateMode; -enum class BumpFeeResult +namespace feebumper { + +enum class Result { OK, INVALID_ADDRESS_OR_KEY, @@ -23,39 +25,34 @@ enum class BumpFeeResult MISC_ERROR, }; -class CFeeBumper -{ -public: - CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, const CCoinControl& coin_control, CAmount totalFee); - BumpFeeResult getResult() const { return currentResult; } - const std::vector<std::string>& getErrors() const { return vErrors; } - CAmount getOldFee() const { return nOldFee; } - CAmount getNewFee() const { return nNewFee; } - uint256 getBumpedTxId() const { return bumpedTxid; } - - /* signs the new transaction, - * returns false if the tx couldn't be found or if it was - * impossible to create the signature(s) - */ - bool signTransaction(CWallet *pWallet); - - /* commits the fee bump, - * returns true, in case of CWallet::CommitTransaction was successful - * but, eventually sets vErrors if the tx could not be added to the mempool (will try later) - * or if the old transaction could not be marked as replaced - */ - bool commit(CWallet *pWalletNonConst); - -private: - bool preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx); - - const uint256 txid; - uint256 bumpedTxid; - CMutableTransaction mtx; - std::vector<std::string> vErrors; - BumpFeeResult currentResult; - CAmount nOldFee; - CAmount nNewFee; -}; +//! Return whether transaction can be bumped. +bool TransactionCanBeBumped(CWallet* wallet, const uint256& txid); + +//! Create bumpfee transaction. +Result CreateTransaction(const CWallet* wallet, + const uint256& txid, + const CCoinControl& coin_control, + CAmount total_fee, + std::vector<std::string>& errors, + CAmount& old_fee, + CAmount& new_fee, + CMutableTransaction& mtx); + +//! Sign the new transaction, +//! @return false if the tx couldn't be found or if it was +//! impossible to create the signature(s) +bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx); + +//! Commit the bumpfee transaction. +//! @return success in case of CWallet::CommitTransaction was successful, +//! but sets errors if the tx could not be added to the mempool (will try later) +//! or if the old transaction could not be marked as replaced. +Result CommitTransaction(CWallet* wallet, + const uint256& txid, + CMutableTransaction&& mtx, + std::vector<std::string>& errors, + uint256& bumped_txid); + +} // namespace feebumper #endif // BITCOIN_WALLET_FEEBUMPER_H diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 76eeeeda05..73985dcf25 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -3,14 +3,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/fees.h" +#include <wallet/fees.h> -#include "policy/policy.h" -#include "txmempool.h" -#include "util.h" -#include "validation.h" -#include "wallet/coincontrol.h" -#include "wallet/wallet.h" +#include <policy/policy.h> +#include <txmempool.h> +#include <util.h> +#include <validation.h> +#include <wallet/coincontrol.h> +#include <wallet/wallet.h> CAmount GetRequiredFee(unsigned int nTxBytes) diff --git a/src/wallet/fees.h b/src/wallet/fees.h index 7b8a7dc868..225aff08ad 100644 --- a/src/wallet/fees.h +++ b/src/wallet/fees.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_WALLET_FEES_H #define BITCOIN_WALLET_FEES_H -#include "amount.h" +#include <amount.h> class CBlockPolicyEstimator; class CCoinControl; diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 6b5d4cc668..67c46df87d 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -3,14 +3,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/init.h" +#include <wallet/init.h> -#include "net.h" -#include "util.h" -#include "utilmoneystr.h" -#include "validation.h" -#include "wallet/wallet.h" -#include "wallet/rpcwallet.h" +#include <net.h> +#include <util.h> +#include <utilmoneystr.h> +#include <validation.h> +#include <wallet/rpcwallet.h> +#include <wallet/wallet.h> +#include <wallet/walletutil.h> std::string GetWalletHelpString(bool showDebug) { @@ -34,6 +35,7 @@ std::string GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); + strUsage += HelpMessageOpt("-walletdir=<dir>", _("Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)")); strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); @@ -191,6 +193,12 @@ bool VerifyWallets() return true; } + if (gArgs.IsArgSet("-walletdir") && !fs::is_directory(GetWalletDir())) { + return InitError(strprintf(_("Error: Specified wallet directory \"%s\" does not exist."), gArgs.GetArg("-walletdir", "").c_str())); + } + + LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); + uiInterface.InitMessage(_("Verifying wallet(s)...")); // Keep track of each wallet absolute path to detect duplicates. @@ -205,7 +213,7 @@ bool VerifyWallets() return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile)); } - fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); + fs::path wallet_path = fs::absolute(walletFile, GetWalletDir()); if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) { return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile)); @@ -216,7 +224,7 @@ bool VerifyWallets() } std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + if (!CWalletDB::VerifyEnvironment(walletFile, GetWalletDir().string(), strError)) { return InitError(strError); } @@ -230,7 +238,7 @@ bool VerifyWallets() } std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetWalletDir().string(), strWarning, strError); if (!strWarning.empty()) { InitWarning(strWarning); } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 30246a534b..71d50be634 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -2,22 +2,22 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "chain.h" -#include "rpc/safemode.h" -#include "rpc/server.h" -#include "init.h" -#include "validation.h" -#include "script/script.h" -#include "script/standard.h" -#include "sync.h" -#include "util.h" -#include "utiltime.h" -#include "wallet.h" -#include "merkleblock.h" -#include "core_io.h" - -#include "rpcwallet.h" +#include <base58.h> +#include <chain.h> +#include <rpc/safemode.h> +#include <rpc/server.h> +#include <wallet/init.h> +#include <validation.h> +#include <script/script.h> +#include <script/standard.h> +#include <sync.h> +#include <util.h> +#include <utiltime.h> +#include <wallet/wallet.h> +#include <merkleblock.h> +#include <core_io.h> + +#include <wallet/rpcwallet.h> #include <fstream> #include <stdint.h> @@ -165,7 +165,7 @@ UniValue abortrescan(const JSONRPCRequest& request) if (request.fHelp || request.params.size() > 0) throw std::runtime_error( "abortrescan\n" - "\nStops current wallet rescan triggered e.g. by an importprivkey call.\n" + "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n" "\nExamples:\n" "\nImport a private key\n" + HelpExampleCli("importprivkey", "\"mykey\"") + diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d4015f6c89..473acd8367 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3,29 +3,30 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "amount.h" -#include "base58.h" -#include "chain.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "httpserver.h" -#include "validation.h" -#include "net.h" -#include "policy/feerate.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "rpc/mining.h" -#include "rpc/safemode.h" -#include "rpc/server.h" -#include "script/sign.h" -#include "timedata.h" -#include "util.h" -#include "utilmoneystr.h" -#include "wallet/coincontrol.h" -#include "wallet/feebumper.h" -#include "wallet/wallet.h" -#include "wallet/walletdb.h" +#include <amount.h> +#include <base58.h> +#include <chain.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <httpserver.h> +#include <validation.h> +#include <net.h> +#include <policy/feerate.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <rpc/mining.h> +#include <rpc/safemode.h> +#include <rpc/server.h> +#include <script/sign.h> +#include <timedata.h> +#include <util.h> +#include <utilmoneystr.h> +#include <wallet/coincontrol.h> +#include <wallet/feebumper.h> +#include <wallet/wallet.h> +#include <wallet/walletdb.h> +#include <wallet/walletutil.h> #include <init.h> // For StartShutdown @@ -455,6 +456,11 @@ UniValue sendtoaddress(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); CTxDestination dest = DecodeDestination(request.params[0].get_str()); @@ -533,6 +539,11 @@ UniValue listaddressgroupings(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); UniValue jsonGroupings(UniValue::VARR); @@ -645,6 +656,11 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); // Bitcoin address @@ -654,7 +670,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) } CScript scriptPubKey = GetScriptForDestination(dest); if (!IsMine(*pwallet, scriptPubKey)) { - return ValueFromAmount(0); + throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet"); } // Minimum confirmations @@ -707,6 +723,11 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); // Minimum confirmations @@ -780,6 +801,11 @@ UniValue getbalance(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); const UniValue& account_value = request.params[0]; @@ -825,6 +851,11 @@ UniValue getunconfirmedbalance(const JSONRPCRequest &request) "Returns the server's total unconfirmed balance\n"); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); return ValueFromAmount(pwallet->GetUnconfirmedBalance()); @@ -919,6 +950,11 @@ UniValue sendfrom(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); std::string strAccount = AccountFromValue(request.params[0]); @@ -1004,6 +1040,11 @@ UniValue sendmany(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); if (pwallet->GetBroadcastTransactions() && !g_connman) { @@ -1398,14 +1439,14 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA if (fByAccounts) { - for (std::map<std::string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) + for (const auto& entry : mapAccountTally) { - CAmount nAmount = (*it).second.nAmount; - int nConf = (*it).second.nConf; + CAmount nAmount = entry.second.nAmount; + int nConf = entry.second.nConf; UniValue obj(UniValue::VOBJ); - if((*it).second.fIsWatchonly) + if (entry.second.fIsWatchonly) obj.push_back(Pair("involvesWatchonly", true)); - obj.push_back(Pair("account", (*it).first)); + obj.push_back(Pair("account", entry.first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf))); ret.push_back(obj); @@ -1455,6 +1496,11 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); return ListReceived(pwallet, request.params, false); @@ -1495,6 +1541,11 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); return ListReceived(pwallet, request.params, true); @@ -1683,6 +1734,11 @@ UniValue listtransactions(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); std::string strAccount = "*"; @@ -1777,6 +1833,11 @@ UniValue listaccounts(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); int nMinDepth = 1; @@ -1886,6 +1947,11 @@ UniValue listsinceblock(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain. @@ -2019,6 +2085,11 @@ UniValue gettransaction(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); uint256 hash; @@ -2081,6 +2152,11 @@ UniValue abandontransaction(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); uint256 hash; @@ -2115,6 +2191,10 @@ UniValue backupwallet(const JSONRPCRequest& request) + HelpExampleRpc("backupwallet", "\"backup.dat\"") ); + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); std::string strDest = request.params[0].get_str(); @@ -2434,6 +2514,10 @@ UniValue lockunspent(const JSONRPCRequest& request) + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") ); + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); RPCTypeCheckArgument(request.params[0], UniValue::VBOOL); @@ -2448,12 +2532,15 @@ UniValue lockunspent(const JSONRPCRequest& request) RPCTypeCheckArgument(request.params[1], UniValue::VARR); - UniValue outputs = request.params[1].get_array(); - for (unsigned int idx = 0; idx < outputs.size(); idx++) { - const UniValue& output = outputs[idx]; - if (!output.isObject()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object"); - const UniValue& o = output.get_obj(); + const UniValue& output_params = request.params[1]; + + // Create and validate the COutPoints first. + + std::vector<COutPoint> outputs; + outputs.reserve(output_params.size()); + + for (unsigned int idx = 0; idx < output_params.size(); idx++) { + const UniValue& o = output_params[idx].get_obj(); RPCTypeCheckObj(o, { @@ -2461,20 +2548,50 @@ UniValue lockunspent(const JSONRPCRequest& request) {"vout", UniValueType(UniValue::VNUM)}, }); - std::string txid = find_value(o, "txid").get_str(); - if (!IsHex(txid)) + const std::string& txid = find_value(o, "txid").get_str(); + if (!IsHex(txid)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); + } - int nOutput = find_value(o, "vout").get_int(); - if (nOutput < 0) + const int nOutput = find_value(o, "vout").get_int(); + if (nOutput < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); + } - COutPoint outpt(uint256S(txid), nOutput); + const COutPoint outpt(uint256S(txid), nOutput); - if (fUnlock) - pwallet->UnlockCoin(outpt); - else - pwallet->LockCoin(outpt); + const auto it = pwallet->mapWallet.find(outpt.hash); + if (it == pwallet->mapWallet.end()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction"); + } + + const CWalletTx& trans = it->second; + + if (outpt.n >= trans.tx->vout.size()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds"); + } + + if (pwallet->IsSpent(outpt.hash, outpt.n)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output"); + } + + const bool is_locked = pwallet->IsLockedCoin(outpt.hash, outpt.n); + + if (fUnlock && !is_locked) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output"); + } + + if (!fUnlock && is_locked) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked"); + } + + outputs.push_back(outpt); + } + + // Atomically set (un)locked status for the outputs. + for (const COutPoint& outpt : outputs) { + if (fUnlock) pwallet->UnlockCoin(outpt); + else pwallet->LockCoin(outpt); } return true; @@ -2593,6 +2710,11 @@ UniValue getwalletinfo(const JSONRPCRequest& request) ); ObserveSafeMode(); + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); UniValue obj(UniValue::VOBJ); @@ -2802,9 +2924,12 @@ UniValue listunspent(const JSONRPCRequest& request) nMaximumCount = options["maximumCount"].get_int64(); } + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + UniValue results(UniValue::VARR); std::vector<COutput> vecOutputs; - assert(pwallet != nullptr); LOCK2(cs_main, pwallet->cs_wallet); pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth); @@ -2912,6 +3037,10 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) ObserveSafeMode(); RPCTypeCheck(request.params, {UniValue::VSTR}); + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + CCoinControl coinControl; int changePosition = -1; bool lockUnspents = false; @@ -3122,48 +3251,57 @@ UniValue bumpfee(const JSONRPCRequest& request) } } + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + LOCK2(cs_main, pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); - CFeeBumper feeBump(pwallet, hash, coin_control, totalFee); - BumpFeeResult res = feeBump.getResult(); - if (res != BumpFeeResult::OK) - { + + std::vector<std::string> errors; + CAmount old_fee; + CAmount new_fee; + CMutableTransaction mtx; + feebumper::Result res = feebumper::CreateTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx); + if (res != feebumper::Result::OK) { switch(res) { - case BumpFeeResult::INVALID_ADDRESS_OR_KEY: - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, feeBump.getErrors()[0]); + case feebumper::Result::INVALID_ADDRESS_OR_KEY: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errors[0]); break; - case BumpFeeResult::INVALID_REQUEST: - throw JSONRPCError(RPC_INVALID_REQUEST, feeBump.getErrors()[0]); + case feebumper::Result::INVALID_REQUEST: + throw JSONRPCError(RPC_INVALID_REQUEST, errors[0]); break; - case BumpFeeResult::INVALID_PARAMETER: - throw JSONRPCError(RPC_INVALID_PARAMETER, feeBump.getErrors()[0]); + case feebumper::Result::INVALID_PARAMETER: + throw JSONRPCError(RPC_INVALID_PARAMETER, errors[0]); break; - case BumpFeeResult::WALLET_ERROR: - throw JSONRPCError(RPC_WALLET_ERROR, feeBump.getErrors()[0]); + case feebumper::Result::WALLET_ERROR: + throw JSONRPCError(RPC_WALLET_ERROR, errors[0]); break; default: - throw JSONRPCError(RPC_MISC_ERROR, feeBump.getErrors()[0]); + throw JSONRPCError(RPC_MISC_ERROR, errors[0]); break; } } // sign bumped transaction - if (!feeBump.signTransaction(pwallet)) { + if (!feebumper::SignTransaction(pwallet, mtx)) { throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction."); } // commit the bumped transaction - if(!feeBump.commit(pwallet)) { - throw JSONRPCError(RPC_WALLET_ERROR, feeBump.getErrors()[0]); + uint256 txid; + if (feebumper::CommitTransaction(pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { + throw JSONRPCError(RPC_WALLET_ERROR, errors[0]); } UniValue result(UniValue::VOBJ); - result.push_back(Pair("txid", feeBump.getBumpedTxId().GetHex())); - result.push_back(Pair("origfee", ValueFromAmount(feeBump.getOldFee()))); - result.push_back(Pair("fee", ValueFromAmount(feeBump.getNewFee()))); - UniValue errors(UniValue::VARR); - for (const std::string& err: feeBump.getErrors()) - errors.push_back(err); - result.push_back(Pair("errors", errors)); + result.push_back(Pair("txid", txid.GetHex())); + result.push_back(Pair("origfee", ValueFromAmount(old_fee))); + result.push_back(Pair("fee", ValueFromAmount(new_fee))); + UniValue result_errors(UniValue::VARR); + for (const std::string& error : errors) { + result_errors.push_back(error); + } + result.push_back(Pair("errors", result_errors)); return result; } diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index 64244dceea..b95bb14335 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -2,26 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/wallet.h" +#include <wallet/wallet.h> -#include "wallet/test/wallet_test_fixture.h" +#include <wallet/test/wallet_test_fixture.h> #include <stdint.h> #include <boost/test/unit_test.hpp> -extern CWallet* pwalletMain; - BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup) static void -GetResults(std::map<CAmount, CAccountingEntry>& results) +GetResults(CWallet *wallet, std::map<CAmount, CAccountingEntry>& results) { std::list<CAccountingEntry> aes; results.clear(); - BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK); - pwalletMain->ListAccountCreditDebit("", aes); + BOOST_CHECK(wallet->ReorderTransactions() == DB_LOAD_OK); + wallet->ListAccountCreditDebit("", aes); for (CAccountingEntry& ae : aes) { results[ae.nOrderPos] = ae; @@ -54,7 +52,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.strOtherAccount = "c"; pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(pwalletMain->nOrderPosNext == 3); BOOST_CHECK(2 == results.size()); @@ -70,7 +68,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = pwalletMain->IncOrderPosNext(); pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 4); @@ -102,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) vpwtx[2]->nTimeReceived = (unsigned int)1333333329; vpwtx[2]->nOrderPos = -1; - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 3); BOOST_CHECK(pwalletMain->nOrderPosNext == 6); @@ -120,7 +118,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nOrderPos = -1; pwalletMain->AddAccountingEntry(ae); - GetResults(results); + GetResults(pwalletMain.get(), results); BOOST_CHECK(results.size() == 4); BOOST_CHECK(pwalletMain->nOrderPosNext == 7); diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index f4dabc50c0..3ff8c6d224 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "test/test_bitcoin.h" -#include "utilstrencodings.h" -#include "wallet/crypter.h" +#include <test/test_bitcoin.h> +#include <utilstrencodings.h> +#include <wallet/crypter.h> #include <vector> diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index e2f48c45ab..3ee83d2d7c 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -2,13 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/test/wallet_test_fixture.h" +#include <wallet/test/wallet_test_fixture.h> -#include "rpc/server.h" -#include "wallet/db.h" -#include "wallet/wallet.h" - -CWallet *pwalletMain; +#include <rpc/server.h> +#include <wallet/db.h> WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName) @@ -17,18 +14,16 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): bool fFirstRun; std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat")); - pwalletMain = new CWallet(std::move(dbw)); + pwalletMain = MakeUnique<CWallet>(std::move(dbw)); pwalletMain->LoadWallet(fFirstRun); - RegisterValidationInterface(pwalletMain); + RegisterValidationInterface(pwalletMain.get()); RegisterWalletRPCCommands(tableRPC); } WalletTestingSetup::~WalletTestingSetup() { - UnregisterValidationInterface(pwalletMain); - delete pwalletMain; - pwalletMain = nullptr; + UnregisterValidationInterface(pwalletMain.get()); bitdb.Flush(true); bitdb.Reset(); diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index 9373b7907c..292d654438 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -5,13 +5,17 @@ #ifndef BITCOIN_WALLET_TEST_FIXTURE_H #define BITCOIN_WALLET_TEST_FIXTURE_H -#include "test/test_bitcoin.h" +#include <test/test_bitcoin.h> + +#include <wallet/wallet.h> /** Testing setup and teardown for wallet. */ struct WalletTestingSetup: public TestingSetup { explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~WalletTestingSetup(); + + std::unique_ptr<CWallet> pwalletMain; }; #endif diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 2b12168c65..80e31a1ce0 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -2,25 +2,23 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/wallet.h" +#include <wallet/wallet.h> #include <set> #include <stdint.h> #include <utility> #include <vector> -#include "consensus/validation.h" -#include "rpc/server.h" -#include "test/test_bitcoin.h" -#include "validation.h" -#include "wallet/coincontrol.h" -#include "wallet/test/wallet_test_fixture.h" +#include <consensus/validation.h> +#include <rpc/server.h> +#include <test/test_bitcoin.h> +#include <validation.h> +#include <wallet/coincontrol.h> +#include <wallet/test/wallet_test_fixture.h> #include <boost/test/unit_test.hpp> #include <univalue.h> -extern CWallet* pwalletMain; - extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue dumpwallet(const JSONRPCRequest& request); extern UniValue importwallet(const JSONRPCRequest& request); @@ -489,6 +487,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) vpwallets[0] = &wallet; ::importwallet(request); + LOCK(wallet.cs_wallet); BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); BOOST_CHECK_EQUAL(coinbaseTxns.size(), 103); for (size_t i = 0; i < coinbaseTxns.size(); ++i) { @@ -534,6 +533,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64 SetMockTime(mockTime); CBlockIndex* block = nullptr; if (blockTime > 0) { + LOCK(cs_main); auto inserted = mapBlockIndex.emplace(GetRandHash(), new CBlockIndex); assert(inserted.second); const uint256& hash = inserted.first->first; @@ -547,6 +547,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64 wtx.SetMerkleBranch(block, 0); } wallet.AddToWallet(wtx); + LOCK(wallet.cs_wallet); return wallet.mapWallet.at(wtx.GetHash()).nTimeSmart; } @@ -583,6 +584,7 @@ BOOST_AUTO_TEST_CASE(ComputeTimeSmart) BOOST_AUTO_TEST_CASE(LoadReceiveRequests) { CTxDestination dest = CKeyID(); + LOCK(pwalletMain->cs_wallet); pwalletMain->AddDestData(dest, "misc", "val_misc"); pwalletMain->AddDestData(dest, "rr0", "val_rr0"); pwalletMain->AddDestData(dest, "rr1", "val_rr1"); @@ -625,6 +627,7 @@ public: BOOST_CHECK(wallet->CreateTransaction({recipient}, wtx, reservekey, fee, changePos, error, dummy)); CValidationState state; BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state)); + LOCK(wallet->cs_wallet); auto it = wallet->mapWallet.find(wtx.GetHash()); BOOST_CHECK(it != wallet->mapWallet.end()); CreateAndProcessBlock({CMutableTransaction(*it->second.tx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a357224a86..b9b4d8ddff 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3,36 +3,35 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/wallet.h" - -#include "base58.h" -#include "checkpoints.h" -#include "chain.h" -#include "wallet/coincontrol.h" -#include "consensus/consensus.h" -#include "consensus/validation.h" -#include "fs.h" -#include "init.h" -#include "key.h" -#include "keystore.h" -#include "validation.h" -#include "net.h" -#include "policy/fees.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "script/script.h" -#include "script/sign.h" -#include "scheduler.h" -#include "timedata.h" -#include "txmempool.h" -#include "util.h" -#include "ui_interface.h" -#include "utilmoneystr.h" -#include "wallet/fees.h" +#include <wallet/wallet.h> + +#include <base58.h> +#include <checkpoints.h> +#include <chain.h> +#include <wallet/coincontrol.h> +#include <consensus/consensus.h> +#include <consensus/validation.h> +#include <fs.h> +#include <wallet/init.h> +#include <key.h> +#include <keystore.h> +#include <validation.h> +#include <net.h> +#include <policy/fees.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <primitives/block.h> +#include <primitives/transaction.h> +#include <script/script.h> +#include <scheduler.h> +#include <timedata.h> +#include <txmempool.h> +#include <util.h> +#include <utilmoneystr.h> +#include <wallet/fees.h> #include <assert.h> +#include <future> #include <boost/algorithm/string/replace.hpp> #include <boost/thread.hpp> @@ -283,7 +282,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, } } -bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &meta) +bool CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta) { AssertLockHeld(cs_wallet); // mapKeyMetadata UpdateTimeFirstKey(meta.nCreateTime); @@ -291,6 +290,14 @@ bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &m return true; } +bool CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta) +{ + AssertLockHeld(cs_wallet); // m_script_metadata + UpdateTimeFirstKey(meta.nCreateTime); + m_script_metadata[script_id] = meta; + return true; +} + bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); @@ -339,7 +346,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) { if (!CCryptoKeyStore::AddWatchOnly(dest)) return false; - const CKeyMetadata& meta = mapKeyMetadata[CScriptID(dest)]; + const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); return CWalletDB(*dbw).WriteWatchOnly(dest, meta); @@ -347,7 +354,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime) { - mapKeyMetadata[CScriptID(dest)].nCreateTime = nCreateTime; + m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime; return AddWatchOnly(dest); } @@ -704,9 +711,9 @@ DBErrors CWallet::ReorderTransactions() typedef std::multimap<int64_t, TxPair > TxItems; TxItems txByTime; - for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (auto& entry : mapWallet) { - CWalletTx* wtx = &((*it).second); + CWalletTx* wtx = &entry.second; txByTime.insert(std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr))); } std::list<CAccountingEntry> acentries; @@ -1217,6 +1224,19 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) { LOCK2(cs_main, cs_wallet); SyncTransaction(ptx); + + auto it = mapWallet.find(ptx->GetHash()); + if (it != mapWallet.end()) { + it->second.fInMempool = true; + } +} + +void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) { + LOCK(cs_wallet); + auto it = mapWallet.find(ptx->GetHash()); + if (it != mapWallet.end()) { + it->second.fInMempool = false; + } } void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) { @@ -1231,10 +1251,14 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const for (const CTransactionRef& ptx : vtxConflicted) { SyncTransaction(ptx); + TransactionRemovedFromMempool(ptx); } for (size_t i = 0; i < pblock->vtx.size(); i++) { SyncTransaction(pblock->vtx[i], pindex, i); + TransactionRemovedFromMempool(pblock->vtx[i]); } + + m_last_block_processed = pindex; } void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) { @@ -1247,6 +1271,36 @@ void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) { +void CWallet::BlockUntilSyncedToCurrentChain() { + AssertLockNotHeld(cs_main); + AssertLockNotHeld(cs_wallet); + + { + // Skip the queue-draining stuff if we know we're caught up with + // chainActive.Tip()... + // We could also take cs_wallet here, and call m_last_block_processed + // protected by cs_wallet instead of cs_main, but as long as we need + // cs_main here anyway, its easier to just call it cs_main-protected. + LOCK(cs_main); + const CBlockIndex* initialChainTip = chainActive.Tip(); + + if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) { + return; + } + } + + // ...otherwise put a callback in the validation interface queue and wait + // for the queue to drain enough to execute it (indicating we are caught up + // at least with the time we entered this function). + + std::promise<void> promise; + CallFunctionInValidationInterfaceQueue([&promise] { + promise.set_value(); + }); + promise.get_future().wait(); +} + + isminetype CWallet::IsMine(const CTxIn &txin) const { { @@ -1665,11 +1719,8 @@ void CWallet::ReacceptWalletTransactions() } // Try to add wallet transactions to memory pool - for (std::pair<const int64_t, CWalletTx*>& item : mapSorted) - { + for (std::pair<const int64_t, CWalletTx*>& item : mapSorted) { CWalletTx& wtx = *(item.second); - - LOCK(mempool.cs); CValidationState state; wtx.AcceptToMemoryPool(maxTxFee, state); } @@ -1871,8 +1922,7 @@ CAmount CWalletTx::GetChange() const bool CWalletTx::InMempool() const { - LOCK(mempool.cs); - return mempool.exists(GetHash()); + return fInMempool; } bool CWalletTx::IsTrusted() const @@ -1979,9 +2029,9 @@ CAmount CWallet::GetBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (pcoin->IsTrusted()) nTotal += pcoin->GetAvailableCredit(); } @@ -1995,9 +2045,9 @@ CAmount CWallet::GetUnconfirmedBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableCredit(); } @@ -2010,9 +2060,9 @@ CAmount CWallet::GetImmatureBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; nTotal += pcoin->GetImmatureCredit(); } } @@ -2024,9 +2074,9 @@ CAmount CWallet::GetWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (pcoin->IsTrusted()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } @@ -2040,9 +2090,9 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) nTotal += pcoin->GetAvailableWatchOnlyCredit(); } @@ -2055,9 +2105,9 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const CWalletTx* pcoin = &(*it).second; + const CWalletTx* pcoin = &entry.second; nTotal += pcoin->GetImmatureWatchOnlyCredit(); } } @@ -2131,10 +2181,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CAmount nTotal = 0; - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (const auto& entry : mapWallet) { - const uint256& wtxid = it->first; - const CWalletTx* pcoin = &(*it).second; + const uint256& wtxid = entry.first; + const CWalletTx* pcoin = &entry.second; if (!CheckFinalTx(*pcoin->tx)) continue; @@ -2195,10 +2245,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount) continue; - if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i))) + if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i))) continue; - if (IsLockedCoin((*it).first, i)) + if (IsLockedCoin(entry.first, i)) continue; if (IsSpent(wtxid, i)) @@ -2980,14 +3030,18 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon // Track how many getdata requests our transaction gets mapRequestCount[wtxNew.GetHash()] = 0; + // Get the inserted-CWalletTx from mapWallet so that the + // fInMempool flag is cached properly + CWalletTx& wtx = mapWallet[wtxNew.GetHash()]; + if (fBroadcastTransactions) { // Broadcast - if (!wtxNew.AcceptToMemoryPool(maxTxFee, state)) { + if (!wtx.AcceptToMemoryPool(maxTxFee, state)) { LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason()); // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } else { - wtxNew.RelayWalletTransaction(connman); + wtx.RelayWalletTransaction(connman); } } } @@ -3654,9 +3708,9 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c // find first block that affects those keys, if there are any left std::vector<CKeyID> vAffected; - for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { + for (const auto& entry : mapWallet) { // iterate over all wallet transactions... - const CWalletTx &wtx = (*it).second; + const CWalletTx &wtx = entry.second; BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) { // ... which are already in a block @@ -3676,8 +3730,8 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c } // Extract block timestamps for those keys - for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) - mapKeyBirth[it->first] = it->second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off + for (const auto& entry : mapKeyFirstBlock) + mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off } /** @@ -3806,7 +3860,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) uiInterface.InitMessage(_("Zapping all transactions from wallet...")); std::unique_ptr<CWalletDBWrapper> dbw(new CWalletDBWrapper(&bitdb, walletFile)); - std::unique_ptr<CWallet> tempWallet(new CWallet(std::move(dbw))); + std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(std::move(dbw)); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); @@ -3903,8 +3957,6 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - RegisterValidationInterface(walletInstance); - // Try to top up keypool. No-op if the wallet is locked. walletInstance->TopUpKeyPool(); @@ -3916,6 +3968,10 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) if (walletdb.ReadBestBlock(locator)) pindexRescan = FindForkInGlobalIndex(chainActive, locator); } + + walletInstance->m_last_block_processed = chainActive.Tip(); + RegisterValidationInterface(walletInstance); + if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { //We can't rescan beyond non-pruned blocks, stop and throw an error @@ -4059,8 +4115,20 @@ int CMerkleTx::GetBlocksToMaturity() const } -bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) +bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) { - return ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */, + // Quick check to avoid re-setting fInMempool to false + if (mempool.exists(tx->GetHash())) { + return false; + } + + // We must set fInMempool here - while it will be re-set to true by the + // entered-mempool callback, if we did not there would be a race where a + // user could call sendmoney in a loop and hit spurious out of funds errors + // because we think that the transaction they just generated's change is + // unavailable as we're not yet aware its in mempool. + bool ret = ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, nAbsurdFee); + fInMempool = ret; + return ret; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index db2861c043..93d1857c7f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -6,18 +6,18 @@ #ifndef BITCOIN_WALLET_WALLET_H #define BITCOIN_WALLET_WALLET_H -#include "amount.h" -#include "policy/feerate.h" -#include "streams.h" -#include "tinyformat.h" -#include "ui_interface.h" -#include "utilstrencodings.h" -#include "validationinterface.h" -#include "script/ismine.h" -#include "script/sign.h" -#include "wallet/crypter.h" -#include "wallet/walletdb.h" -#include "wallet/rpcwallet.h" +#include <amount.h> +#include <policy/feerate.h> +#include <streams.h> +#include <tinyformat.h> +#include <ui_interface.h> +#include <utilstrencodings.h> +#include <validationinterface.h> +#include <script/ismine.h> +#include <script/sign.h> +#include <wallet/crypter.h> +#include <wallet/walletdb.h> +#include <wallet/rpcwallet.h> #include <algorithm> #include <atomic> @@ -248,8 +248,6 @@ public: int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; } int GetBlocksToMaturity() const; - /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ - bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state); bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); } bool isAbandoned() const { return (hashBlock == ABANDON_HASH); } void setAbandoned() { hashBlock = ABANDON_HASH; } @@ -326,6 +324,7 @@ public: mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; + mutable bool fInMempool; mutable CAmount nDebitCached; mutable CAmount nCreditCached; mutable CAmount nImmatureCreditCached; @@ -365,6 +364,7 @@ public: fImmatureWatchCreditCached = false; fAvailableWatchCreditCached = false; fChangeCached = false; + fInMempool = false; nDebitCached = 0; nCreditCached = 0; nImmatureCreditCached = 0; @@ -469,6 +469,9 @@ public: // RelayWalletTransaction may only be called if fBroadcastTransactions! bool RelayWalletTransaction(CConnman* connman); + /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ + bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state); + std::set<uint256> GetConflicts() const; }; @@ -718,6 +721,18 @@ private: std::unique_ptr<CWalletDBWrapper> dbw; + /** + * The following is used to keep track of how far behind the wallet is + * from the chain sync, and to allow clients to block on us being caught up. + * + * Note that this is *not* how far we've processed, we may need some rescan + * to have seen all transactions in the chain, but is only used to track + * live BlockConnected callbacks. + * + * Protected by cs_main (see BlockUntilSyncedToCurrentChain) + */ + const CBlockIndex* m_last_block_processed; + public: /* * Main wallet lock. @@ -746,9 +761,11 @@ public: void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool); - // Map from Key ID (for regular keys) or Script ID (for watch-only keys) to - // key metadata. - std::map<CTxDestination, CKeyMetadata> mapKeyMetadata; + // Map from Key ID to key metadata. + std::map<CKeyID, CKeyMetadata> mapKeyMetadata; + + // Map from Script ID to key metadata (for watch-only keys). + std::map<CScriptID, CKeyMetadata> m_script_metadata; typedef std::map<unsigned int, CMasterKey> MasterKeyMap; MasterKeyMap mapMasterKeys; @@ -859,7 +876,8 @@ public: //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } //! Load metadata (used by LoadWallet) - bool LoadKeyMetadata(const CTxDestination& pubKey, const CKeyMetadata &metadata); + bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata); + bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata); bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } void UpdateTimeFirstKey(int64_t nCreateTime); @@ -916,6 +934,7 @@ public: bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); int64_t RescanFromTime(int64_t startTime, bool update); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate = false); + void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions! @@ -1102,6 +1121,14 @@ public: caller must ensure the current wallet version is correct before calling this function). */ bool SetHDMasterKey(const CPubKey& key); + + /** + * Blocks until the wallet state is up-to-date to /at least/ the current + * chain at the time this function is entered + * Obviously holding cs_main/cs_wallet when going into this call may cause + * deadlock + */ + void BlockUntilSyncedToCurrentChain(); }; /** A key allocated from the key pool. */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 180706b1ed..efc50f72eb 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -3,18 +3,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet/walletdb.h" - -#include "base58.h" -#include "consensus/tx_verify.h" -#include "consensus/validation.h" -#include "fs.h" -#include "protocol.h" -#include "serialize.h" -#include "sync.h" -#include "util.h" -#include "utiltime.h" -#include "wallet/wallet.h" +#include <wallet/walletdb.h> + +#include <base58.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <fs.h> +#include <protocol.h> +#include <serialize.h> +#include <sync.h> +#include <util.h> +#include <utiltime.h> +#include <wallet/wallet.h> #include <atomic> @@ -423,27 +423,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } wss.fIsEncrypted = true; } - else if (strType == "keymeta" || strType == "watchmeta") + else if (strType == "keymeta") { - CTxDestination keyID; - if (strType == "keymeta") - { - CPubKey vchPubKey; - ssKey >> vchPubKey; - keyID = vchPubKey.GetID(); - } - else if (strType == "watchmeta") - { - CScript script; - ssKey >> script; - keyID = CScriptID(script); - } - + CPubKey vchPubKey; + ssKey >> vchPubKey; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nKeyMeta++; - - pwallet->LoadKeyMetadata(keyID, keyMeta); + pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); + } + else if (strType == "watchmeta") + { + CScript script; + ssKey >> script; + CKeyMetadata keyMeta; + ssValue >> keyMeta; + wss.nKeyMeta++; + pwallet->LoadScriptMetadata(CScriptID(script), keyMeta); } else if (strType == "defaultkey") { @@ -814,14 +810,14 @@ bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDa return true; } -bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) +bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr) { - return CDB::VerifyEnvironment(walletFile, dataDir, errorStr); + return CDB::VerifyEnvironment(walletFile, walletDir, errorStr); } -bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) +bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr) { - return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); + return CDB::VerifyDatabaseFile(walletFile, walletDir, warningStr, errorStr, CWalletDB::Recover); } bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 3a146179af..e815bcfeda 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -6,10 +6,10 @@ #ifndef BITCOIN_WALLET_WALLETDB_H #define BITCOIN_WALLET_WALLETDB_H -#include "amount.h" -#include "primitives/transaction.h" -#include "wallet/db.h" -#include "key.h" +#include <amount.h> +#include <primitives/transaction.h> +#include <wallet/db.h> +#include <key.h> #include <list> #include <stdint.h> @@ -226,9 +226,9 @@ public: /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ static bool IsKeyType(const std::string& strType); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr); //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp new file mode 100644 index 0000000000..fbb5215a51 --- /dev/null +++ b/src/wallet/walletutil.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 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 "wallet/walletutil.h" + +fs::path GetWalletDir() +{ + fs::path path; + + if (gArgs.IsArgSet("-walletdir")) { + path = fs::system_complete(gArgs.GetArg("-walletdir", "")); + if (!fs::is_directory(path)) { + // If the path specified doesn't exist, we return the deliberately + // invalid empty string. + path = ""; + } + } else { + path = GetDataDir(); + // If a wallets directory exists, use that, otherwise default to GetDataDir + if (fs::is_directory(path / "wallets")) { + path /= "wallets"; + } + } + + return path; +} diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h new file mode 100644 index 0000000000..a94f286a44 --- /dev/null +++ b/src/wallet/walletutil.h @@ -0,0 +1,13 @@ +// Copyright (c) 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. + +#ifndef BITCOIN_WALLET_UTIL_H +#define BITCOIN_WALLET_UTIL_H + +#include "util.h" + +//! Get the path of the wallet directory. +fs::path GetWalletDir(); + +#endif // BITCOIN_WALLET_UTIL_H diff --git a/src/warnings.cpp b/src/warnings.cpp index d4e33b701a..c52a1fdb47 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sync.h" -#include "clientversion.h" -#include "util.h" -#include "warnings.h" +#include <sync.h> +#include <clientversion.h> +#include <util.h> +#include <warnings.h> CCriticalSection cs_warnings; std::string strMiscWarning; diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 9f5cb3ba67..ce5c753eb4 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "zmqabstractnotifier.h" -#include "util.h" +#include <zmq/zmqabstractnotifier.h> +#include <util.h> CZMQAbstractNotifier::~CZMQAbstractNotifier() diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 7828822149..6fbaba2036 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H #define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H -#include "zmqconfig.h" +#include <zmq/zmqconfig.h> class CBlockIndex; class CZMQAbstractNotifier; diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index 610d7fbda4..ce8f3e13db 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -6,7 +6,7 @@ #define BITCOIN_ZMQ_ZMQCONFIG_H #if defined(HAVE_CONFIG_H) -#include "config/bitcoin-config.h" +#include <config/bitcoin-config.h> #endif #include <stdarg.h> @@ -16,8 +16,8 @@ #include <zmq.h> #endif -#include "primitives/block.h" -#include "primitives/transaction.h" +#include <primitives/block.h> +#include <primitives/transaction.h> void zmqError(const char *str); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 9909395d84..b663615752 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "zmqnotificationinterface.h" -#include "zmqpublishnotifier.h" +#include <zmq/zmqnotificationinterface.h> +#include <zmq/zmqpublishnotifier.h> -#include "version.h" -#include "validation.h" -#include "streams.h" -#include "util.h" +#include <version.h> +#include <validation.h> +#include <streams.h> +#include <util.h> void zmqError(const char *str) { @@ -40,15 +40,15 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>; factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>; - for (std::map<std::string, CZMQNotifierFactory>::const_iterator i=factories.begin(); i!=factories.end(); ++i) + for (const auto& entry : factories) { - std::string arg("-zmq" + i->first); + std::string arg("-zmq" + entry.first); if (gArgs.IsArgSet(arg)) { - CZMQNotifierFactory factory = i->second; + CZMQNotifierFactory factory = entry.second; std::string address = gArgs.GetArg(arg, ""); CZMQAbstractNotifier *notifier = factory(); - notifier->SetType(i->first); + notifier->SetType(entry.first); notifier->SetAddress(address); notifiers.push_back(notifier); } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index cb92216fa4..222d31e2ad 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H #define BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H -#include "validationinterface.h" +#include <validationinterface.h> #include <string> #include <map> #include <list> diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index ab54e2bb8b..acccb896c0 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -2,13 +2,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "chain.h" -#include "chainparams.h" -#include "streams.h" -#include "zmqpublishnotifier.h" -#include "validation.h" -#include "util.h" -#include "rpc/server.h" +#include <chain.h> +#include <chainparams.h> +#include <streams.h> +#include <zmq/zmqpublishnotifier.h> +#include <validation.h> +#include <util.h> +#include <rpc/server.h> static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers; diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 1790fe5698..0e9bb23e5b 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H #define BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H -#include "zmqabstractnotifier.h" +#include <zmq/zmqabstractnotifier.h> class CBlockIndex; |