aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.bench.include7
-rw-r--r--src/Makefile.qttest.include4
-rw-r--r--src/Makefile.test.include9
-rw-r--r--src/bench/bench.cpp19
-rw-r--r--src/bench/bench_bitcoin.cpp26
-rw-r--r--src/bench/block_assemble.cpp75
-rw-r--r--src/bench/duplicate_inputs.cpp37
-rw-r--r--src/bench/wallet_balance.cpp53
-rw-r--r--src/blockfilter.cpp58
-rw-r--r--src/blockfilter.h13
-rw-r--r--src/chain.cpp7
-rw-r--r--src/chain.h4
-rw-r--r--src/checkpoints.cpp32
-rw-r--r--src/checkpoints.h27
-rw-r--r--src/coins.h4
-rw-r--r--src/index/base.cpp63
-rw-r--r--src/index/base.h21
-rw-r--r--src/index/blockfilterindex.cpp467
-rw-r--r--src/index/blockfilterindex.h94
-rw-r--r--src/init.cpp56
-rw-r--r--src/interfaces/chain.cpp18
-rw-r--r--src/interfaces/chain.h17
-rw-r--r--src/interfaces/wallet.cpp9
-rw-r--r--src/policy/policy.cpp2
-rw-r--r--src/primitives/transaction.h4
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/clientmodel.cpp1
-rw-r--r--src/qt/forms/receivecoinsdialog.ui2
-rw-r--r--src/qt/guiutil.cpp5
-rw-r--r--src/qt/guiutil.h5
-rw-r--r--src/qt/intro.cpp13
-rw-r--r--src/qt/intro.h5
-rw-r--r--src/qt/optionsdialog.cpp8
-rw-r--r--src/qt/optionsmodel.cpp5
-rw-r--r--src/qt/test/addressbooktests.cpp2
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/test/wallettests.cpp2
-rw-r--r--src/rpc/blockchain.cpp87
-rw-r--r--src/rpc/mining.cpp18
-rw-r--r--src/rpc/mining.h15
-rw-r--r--src/rpc/misc.cpp7
-rw-r--r--src/rpc/rawtransaction.cpp18
-rw-r--r--src/rpc/rawtransaction_util.cpp12
-rw-r--r--src/rpc/rawtransaction_util.h22
-rw-r--r--src/script/ismine.h29
-rw-r--r--src/script/script.h9
-rw-r--r--src/script/standard.h3
-rw-r--r--src/serialize.h11
-rw-r--r--src/test/README.md2
-rw-r--r--src/test/addrman_tests.cpp4
-rw-r--r--src/test/allocator_tests.cpp4
-rw-r--r--src/test/amount_tests.cpp4
-rw-r--r--src/test/arith_uint256_tests.cpp4
-rw-r--r--src/test/base32_tests.cpp4
-rw-r--r--src/test/base58_tests.cpp4
-rw-r--r--src/test/base64_tests.cpp4
-rw-r--r--src/test/bech32_tests.cpp2
-rw-r--r--src/test/bip32_tests.cpp4
-rw-r--r--src/test/blockchain_tests.cpp2
-rw-r--r--src/test/blockencodings_tests.cpp5
-rw-r--r--src/test/blockfilter_index_tests.cpp307
-rw-r--r--src/test/blockfilter_tests.cpp29
-rw-r--r--src/test/bloom_tests.cpp4
-rw-r--r--src/test/bswap_tests.cpp4
-rw-r--r--src/test/checkqueue_tests.cpp5
-rw-r--r--src/test/coins_tests.cpp4
-rw-r--r--src/test/compress_tests.cpp4
-rw-r--r--src/test/crypto_tests.cpp4
-rw-r--r--src/test/cuckoocache_tests.cpp4
-rw-r--r--src/test/data/blockfilters.json10
-rw-r--r--src/test/dbwrapper_tests.cpp4
-rw-r--r--src/test/denialofservice_tests.cpp4
-rw-r--r--src/test/descriptor_tests.cpp4
-rw-r--r--src/test/flatfile_tests.cpp2
-rw-r--r--src/test/fs_tests.cpp4
-rw-r--r--src/test/fuzz/deserialize.cpp2
-rw-r--r--src/test/getarg_tests.cpp4
-rw-r--r--src/test/hash_tests.cpp4
-rw-r--r--src/test/key_io_tests.cpp4
-rw-r--r--src/test/key_properties.cpp4
-rw-r--r--src/test/key_tests.cpp4
-rw-r--r--src/test/limitedmap_tests.cpp4
-rw-r--r--src/test/mempool_tests.cpp4
-rw-r--r--src/test/merkle_tests.cpp4
-rw-r--r--src/test/merkleblock_tests.cpp4
-rw-r--r--src/test/miner_tests.cpp4
-rw-r--r--src/test/multisig_tests.cpp4
-rw-r--r--src/test/net_tests.cpp4
-rw-r--r--src/test/netbase_tests.cpp4
-rw-r--r--src/test/pmt_tests.cpp4
-rw-r--r--src/test/policyestimator_tests.cpp4
-rw-r--r--src/test/pow_tests.cpp4
-rw-r--r--src/test/prevector_tests.cpp4
-rw-r--r--src/test/raii_event_tests.cpp4
-rw-r--r--src/test/random_tests.cpp4
-rw-r--r--src/test/reverselock_tests.cpp4
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/test/sanity_tests.cpp4
-rw-r--r--src/test/scheduler_tests.cpp4
-rw-r--r--src/test/script_p2sh_tests.cpp4
-rw-r--r--src/test/script_standard_tests.cpp4
-rw-r--r--src/test/script_tests.cpp4
-rw-r--r--src/test/scriptnum_tests.cpp4
-rw-r--r--src/test/serialize_tests.cpp4
-rw-r--r--src/test/setup_common.cpp (renamed from src/test/test_bitcoin.cpp)20
-rw-r--r--src/test/setup_common.h (renamed from src/test/test_bitcoin.h)6
-rw-r--r--src/test/sighash_tests.cpp4
-rw-r--r--src/test/sigopcount_tests.cpp4
-rw-r--r--src/test/skiplist_tests.cpp50
-rw-r--r--src/test/streams_tests.cpp4
-rw-r--r--src/test/sync_tests.cpp4
-rw-r--r--src/test/timedata_tests.cpp4
-rw-r--r--src/test/torcontrol_tests.cpp5
-rw-r--r--src/test/transaction_tests.cpp4
-rw-r--r--src/test/txindex_tests.cpp4
-rw-r--r--src/test/txvalidation_tests.cpp4
-rw-r--r--src/test/txvalidationcache_tests.cpp4
-rw-r--r--src/test/uint256_tests.cpp4
-rw-r--r--src/test/util.cpp91
-rw-r--r--src/test/util.h38
-rw-r--r--src/test/util_tests.cpp8
-rw-r--r--src/test/validation_block_tests.cpp4
-rw-r--r--src/test/validation_tests.cpp2
-rw-r--r--src/test/versionbits_tests.cpp4
-rw-r--r--src/txdb.h2
-rw-r--r--src/ui_interface.cpp4
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/validation.cpp36
-rw-r--r--src/validation.h1
-rw-r--r--src/validationinterface.h1
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/feebumper.cpp155
-rw-r--r--src/wallet/feebumper.h13
-rw-r--r--src/wallet/rpcwallet.cpp50
-rw-r--r--src/wallet/test/coinselector_tests.cpp8
-rw-r--r--src/wallet/test/db_tests.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.h2
-rw-r--r--src/wallet/test/init_tests.cpp2
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp2
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp7
-rw-r--r--src/wallet/test/wallet_test_fixture.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp114
-rw-r--r--src/wallet/wallet.h68
146 files changed, 1977 insertions, 733 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6bc3655cad..4fe5898829 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -113,7 +113,6 @@ BITCOIN_CORE_H = \
chainparams.h \
chainparamsbase.h \
chainparamsseeds.h \
- checkpoints.h \
checkqueue.h \
clientversion.h \
coins.h \
@@ -134,6 +133,7 @@ BITCOIN_CORE_H = \
httprpc.h \
httpserver.h \
index/base.h \
+ index/blockfilterindex.h \
index/txindex.h \
indirectmap.h \
init.h \
@@ -174,7 +174,6 @@ BITCOIN_CORE_H = \
reverselock.h \
rpc/blockchain.h \
rpc/client.h \
- rpc/mining.h \
rpc/protocol.h \
rpc/server.h \
rpc/rawtransaction_util.h \
@@ -258,12 +257,12 @@ libbitcoin_server_a_SOURCES = \
blockencodings.cpp \
blockfilter.cpp \
chain.cpp \
- checkpoints.cpp \
consensus/tx_verify.cpp \
flatfile.cpp \
httprpc.cpp \
httpserver.cpp \
index/base.cpp \
+ index/blockfilterindex.cpp \
index/txindex.cpp \
interfaces/chain.cpp \
interfaces/node.cpp \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index b84360e84b..ae7eb19ceb 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -32,7 +32,11 @@ bench_bench_bitcoin_SOURCES = \
bench/bech32.cpp \
bench/lockedpool.cpp \
bench/poly1305.cpp \
- bench/prevector.cpp
+ bench/prevector.cpp \
+ test/setup_common.h \
+ test/setup_common.cpp \
+ test/util.h \
+ test/util.cpp
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
@@ -60,6 +64,7 @@ endif
if ENABLE_WALLET
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
+bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
endif
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 61977b50cd..4acfff809e 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -33,10 +33,10 @@ TEST_QT_H = \
qt/test/wallettests.h
TEST_BITCOIN_CPP = \
- test/test_bitcoin.cpp
+ test/setup_common.cpp
TEST_BITCOIN_H = \
- test/test_bitcoin.h
+ test/setup_common.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index a6e0785616..692f8d97b3 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -52,12 +52,12 @@ GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.r
BITCOIN_TEST_SUITE = \
test/main.cpp \
- test/test_bitcoin.h \
- test/test_bitcoin.cpp
+ test/setup_common.h \
+ test/setup_common.cpp
FUZZ_SUITE = \
- test/test_bitcoin.h \
- test/test_bitcoin.cpp \
+ test/setup_common.h \
+ test/setup_common.cpp \
test/fuzz/fuzz.cpp \
test/fuzz/fuzz.h
@@ -92,6 +92,7 @@ BITCOIN_TESTS =\
test/blockchain_tests.cpp \
test/blockencodings_tests.cpp \
test/blockfilter_tests.cpp \
+ test/blockfilter_index_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/checkqueue_tests.cpp \
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 966b99f6c8..b08ecbb621 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -1,15 +1,19 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
+#include <chainparams.h>
+#include <test/setup_common.h>
+#include <validation.h>
+
+#include <algorithm>
#include <assert.h>
-#include <iostream>
#include <iomanip>
-#include <algorithm>
-#include <regex>
+#include <iostream>
#include <numeric>
+#include <regex>
void benchmark::ConsolePrinter::header()
{
@@ -108,6 +112,13 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
printer.header();
for (const auto& p : benchmarks()) {
+ TestingSetup test{CBaseChainParams::REGTEST};
+ {
+ assert(::chainActive.Height() == 0);
+ const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), Params().GetConsensus())};
+ assert(witness_enabled);
+ }
+
if (!std::regex_match(p.first, baseMatch, reFilter)) {
continue;
}
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index d67b2c5bc7..3cf0bf9530 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,14 +6,11 @@
#include <crypto/sha256.h>
#include <key.h>
-#include <util/system.h>
#include <util/strencodings.h>
-#include <validation.h>
+#include <util/system.h>
#include <memory>
-const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
-
static const int64_t DEFAULT_BENCH_EVALUATIONS = 5;
static const char* DEFAULT_BENCH_FILTER = ".*";
static const char* DEFAULT_BENCH_SCALING = "1.0";
@@ -36,14 +33,6 @@ static void SetupBenchArgs()
gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
}
-static fs::path SetDataDir()
-{
- fs::path ret = fs::temp_directory_path() / "bench_bitcoin" / fs::unique_path();
- fs::create_directories(ret);
- gArgs.ForceSetArg("-datadir", ret.string());
- return ret;
-}
-
int main(int argc, char** argv)
{
SetupBenchArgs();
@@ -59,13 +48,6 @@ int main(int argc, char** argv)
return EXIT_SUCCESS;
}
- // Set the datadir after parsing the bench options
- const fs::path bench_datadir{SetDataDir()};
-
- SHA256AutoDetect();
- ECC_Start();
- SetupEnvironment();
-
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
@@ -88,9 +70,5 @@ int main(int argc, char** argv)
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
- fs::remove_all(bench_datadir);
-
- ECC_Stop();
-
return EXIT_SUCCESS;
}
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index cd4543c012..fb33c09ab2 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -1,58 +1,18 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <chainparams.h>
-#include <coins.h>
-#include <consensus/merkle.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
-#include <miner.h>
-#include <policy/policy.h>
-#include <pow.h>
-#include <scheduler.h>
-#include <txdb.h>
+#include <test/util.h>
#include <txmempool.h>
-#include <util/time.h>
#include <validation.h>
-#include <validationinterface.h>
-#include <boost/thread.hpp>
#include <list>
#include <vector>
-static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
-{
- auto block = std::make_shared<CBlock>(
- BlockAssembler{Params()}
- .CreateNewBlock(coinbase_scriptPubKey)
- ->block);
-
- block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
- block->hashMerkleRoot = BlockMerkleRoot(*block);
-
- return block;
-}
-
-
-static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
-{
- auto block = PrepareBlock(coinbase_scriptPubKey);
-
- while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
- ++block->nNonce;
- assert(block->nNonce);
- }
-
- bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
- assert(processed);
-
- return CTxIn{block->vtx[0]->GetHash(), 0};
-}
-
-
static void AssembleBlock(benchmark::State& state)
{
const std::vector<unsigned char> op_true{OP_TRUE};
@@ -64,32 +24,6 @@ static void AssembleBlock(benchmark::State& state)
const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
- // Switch to regtest so we can mine faster
- // Also segwit is active, so we can include witness transactions
- SelectParams(CBaseChainParams::REGTEST);
-
- InitScriptExecutionCache();
-
- boost::thread_group thread_group;
- CScheduler scheduler;
- {
- LOCK(cs_main);
- ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
- ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
- }
- {
- const CChainParams& chainparams = Params();
- thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
- LoadGenesisBlock(chainparams);
- CValidationState state;
- ActivateBestChain(state, chainparams);
- assert(::chainActive.Tip() != nullptr);
- const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
- assert(witness_enabled);
- }
-
// Collect some loose transactions that spend the coinbases of our mined blocks
constexpr size_t NUM_BLOCKS{200};
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
@@ -114,11 +48,6 @@ static void AssembleBlock(benchmark::State& state)
while (state.KeepRunning()) {
PrepareBlock(SCRIPT_PUB);
}
-
- thread_group.interrupt_all();
- thread_group.join_all();
- GetMainSignals().FlushBackgroundCallbacks();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
}
BENCHMARK(AssembleBlock, 700);
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index 1f6840d813..2d7a351523 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,15 +10,11 @@
#include <miner.h>
#include <policy/policy.h>
#include <pow.h>
-#include <scheduler.h>
-#include <txdb.h>
+#include <test/util.h>
#include <txmempool.h>
-#include <util/time.h>
#include <validation.h>
#include <validationinterface.h>
-#include <boost/thread.hpp>
-
#include <list>
#include <vector>
@@ -27,31 +23,7 @@ static void DuplicateInputs(benchmark::State& state)
{
const CScript SCRIPT_PUB{CScript(OP_TRUE)};
- // Switch to regtest so we can mine faster
- // Also segwit is active, so we can include witness transactions
- SelectParams(CBaseChainParams::REGTEST);
-
- InitScriptExecutionCache();
-
- boost::thread_group thread_group;
- CScheduler scheduler;
const CChainParams& chainparams = Params();
- {
- LOCK(cs_main);
- ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
- ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
- }
- {
- thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
- LoadGenesisBlock(chainparams);
- CValidationState cvstate;
- ActivateBestChain(cvstate, chainparams);
- assert(::chainActive.Tip() != nullptr);
- const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
- assert(witness_enabled);
- }
CBlock block{};
CMutableTransaction coinbaseTx{};
@@ -92,11 +64,6 @@ static void DuplicateInputs(benchmark::State& state)
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
}
-
- thread_group.interrupt_all();
- thread_group.join_all();
- GetMainSignals().FlushBackgroundCallbacks();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
}
BENCHMARK(DuplicateInputs, 10);
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
new file mode 100644
index 0000000000..46ca12826b
--- /dev/null
+++ b/src/bench/wallet_balance.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <interfaces/chain.h>
+#include <key_io.h>
+#include <optional.h>
+#include <test/util.h>
+#include <validationinterface.h>
+#include <wallet/wallet.h>
+
+static void WalletBalance(benchmark::State& state, const bool set_dirty, const bool add_watchonly, const bool add_mine)
+{
+ const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
+
+ std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain();
+ CWallet wallet{chain.get(), WalletLocation(), WalletDatabase::CreateMock()};
+ {
+ bool first_run;
+ if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
+ wallet.handleNotifications();
+ }
+
+
+ const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
+ if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
+
+ for (int i = 0; i < 100; ++i) {
+ generatetoaddress(address_mine.get_value_or(ADDRESS_WATCHONLY));
+ generatetoaddress(ADDRESS_WATCHONLY);
+ }
+ SyncWithValidationInterfaceQueue();
+
+ auto bal = wallet.GetBalance(); // Cache
+
+ while (state.KeepRunning()) {
+ if (set_dirty) wallet.MarkDirty();
+ bal = wallet.GetBalance();
+ if (add_mine) assert(bal.m_mine_trusted > 0);
+ if (add_watchonly) assert(bal.m_watchonly_trusted > 0);
+ }
+}
+
+static void WalletBalanceDirty(benchmark::State& state) { WalletBalance(state, /* set_dirty */ true, /* add_watchonly */ true, /* add_mine */ true); }
+static void WalletBalanceClean(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ true); }
+static void WalletBalanceMine(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ false, /* add_mine */ true); }
+static void WalletBalanceWatch(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ false); }
+
+BENCHMARK(WalletBalanceDirty, 2500);
+BENCHMARK(WalletBalanceClean, 8000);
+BENCHMARK(WalletBalanceMine, 16000);
+BENCHMARK(WalletBalanceWatch, 8000);
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index e15213c552..787390be31 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -2,6 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <mutex>
+#include <sstream>
+
#include <blockfilter.h>
#include <crypto/siphash.h>
#include <hash.h>
@@ -15,6 +18,10 @@ static constexpr int GCS_SER_TYPE = SER_NETWORK;
/// Protocol version used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_VERSION = 0;
+static const std::map<BlockFilterType, std::string> g_filter_types = {
+ {BlockFilterType::BASIC, "basic"},
+};
+
template <typename OStream>
static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
{
@@ -197,6 +204,57 @@ bool GCSFilter::MatchAny(const ElementSet& elements) const
return MatchInternal(queries.data(), queries.size());
}
+const std::string& BlockFilterTypeName(BlockFilterType filter_type)
+{
+ static std::string unknown_retval = "";
+ auto it = g_filter_types.find(filter_type);
+ return it != g_filter_types.end() ? it->second : unknown_retval;
+}
+
+bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type) {
+ for (const auto& entry : g_filter_types) {
+ if (entry.second == name) {
+ filter_type = entry.first;
+ return true;
+ }
+ }
+ return false;
+}
+
+const std::vector<BlockFilterType>& AllBlockFilterTypes()
+{
+ static std::vector<BlockFilterType> types;
+
+ static std::once_flag flag;
+ std::call_once(flag, []() {
+ types.reserve(g_filter_types.size());
+ for (auto entry : g_filter_types) {
+ types.push_back(entry.first);
+ }
+ });
+
+ return types;
+}
+
+const std::string& ListBlockFilterTypes()
+{
+ static std::string type_list;
+
+ static std::once_flag flag;
+ std::call_once(flag, []() {
+ std::stringstream ret;
+ bool first = true;
+ for (auto entry : g_filter_types) {
+ if (!first) ret << ", ";
+ ret << entry.second;
+ first = false;
+ }
+ type_list = ret.str();
+ });
+
+ return type_list;
+}
+
static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
const CBlockUndo& block_undo)
{
diff --git a/src/blockfilter.h b/src/blockfilter.h
index e5e087ed5a..914b94fec1 100644
--- a/src/blockfilter.h
+++ b/src/blockfilter.h
@@ -6,6 +6,7 @@
#define BITCOIN_BLOCKFILTER_H
#include <stdint.h>
+#include <string>
#include <unordered_set>
#include <vector>
@@ -89,6 +90,18 @@ enum class BlockFilterType : uint8_t
INVALID = 255,
};
+/** Get the human-readable name for a filter type. Returns empty string for unknown types. */
+const std::string& BlockFilterTypeName(BlockFilterType filter_type);
+
+/** Find a filter type by its human-readable name. */
+bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type);
+
+/** Get a list of known filter types. */
+const std::vector<BlockFilterType>& AllBlockFilterTypes();
+
+/** Get a comma-separated list of known filter type names. */
+const std::string& ListBlockFilterTypes();
+
/**
* Complete block filter struct as defined in BIP 157. Serialization matches
* payload of "cfilter" messages.
diff --git a/src/chain.cpp b/src/chain.cpp
index d462f94ab5..5520d8149a 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -59,10 +59,11 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
return pindex;
}
-CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
+CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime, int height) const
{
- std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
- [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
+ std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
+ std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), blockparams,
+ [](CBlockIndex* pBlock, const std::pair<int64_t, int>& blockparams) -> bool { return pBlock->GetBlockTimeMax() < blockparams.first || pBlock->nHeight < blockparams.second; });
return (lower == vChain.end() ? nullptr : *lower);
}
diff --git a/src/chain.h b/src/chain.h
index 2b6d2d082c..dd9cc2a598 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -465,8 +465,8 @@ public:
/** Find the last common block between this chain and a block index entry. */
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
- /** Find the earliest block with timestamp equal or greater than the given. */
- CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
+ /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
+ CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
};
#endif // BITCOIN_CHAIN_H
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
deleted file mode 100644
index ad5edfeb39..0000000000
--- a/src/checkpoints.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <checkpoints.h>
-
-#include <chain.h>
-#include <chainparams.h>
-#include <reverse_iterator.h>
-#include <validation.h>
-
-#include <stdint.h>
-
-
-namespace Checkpoints {
-
- CBlockIndex* GetLastCheckpoint(const CCheckpointData& data)
- {
- const MapCheckpoints& checkpoints = data.mapCheckpoints;
-
- for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
- {
- const uint256& hash = i.second;
- CBlockIndex* pindex = LookupBlockIndex(hash);
- if (pindex) {
- return pindex;
- }
- }
- return nullptr;
- }
-
-} // namespace Checkpoints
diff --git a/src/checkpoints.h b/src/checkpoints.h
deleted file mode 100644
index a25e97e469..0000000000
--- a/src/checkpoints.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_CHECKPOINTS_H
-#define BITCOIN_CHECKPOINTS_H
-
-#include <uint256.h>
-
-#include <map>
-
-class CBlockIndex;
-struct CCheckpointData;
-
-/**
- * Block-chain checkpoints are compiled-in sanity checks.
- * They are updated every release or three.
- */
-namespace Checkpoints
-{
-
-//! Returns last CBlockIndex* that is a checkpoint
-CBlockIndex* GetLastCheckpoint(const CCheckpointData& data);
-
-} //namespace Checkpoints
-
-#endif // BITCOIN_CHECKPOINTS_H
diff --git a/src/coins.h b/src/coins.h
index d39ebf9062..482e233e8c 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -294,6 +294,10 @@ public:
bool HaveInputs(const CTransaction& tx) const;
private:
+ /**
+ * @note this is marked const, but may actually append to `cacheCoins`, increasing
+ * memory usage.
+ */
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
};
diff --git a/src/index/base.cpp b/src/index/base.cpp
index f6f59572ce..9e48f0bd27 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -41,9 +41,9 @@ bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
return success;
}
-bool BaseIndex::DB::WriteBestBlock(const CBlockLocator& locator)
+void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator)
{
- return Write(DB_BEST_BLOCK, locator);
+ batch.Write(DB_BEST_BLOCK, locator);
}
BaseIndex::~BaseIndex()
@@ -95,7 +95,11 @@ void BaseIndex::ThreadSync()
int64_t last_locator_write_time = 0;
while (true) {
if (m_interrupt) {
- WriteBestBlock(pindex);
+ m_best_block_index = pindex;
+ // No need to handle errors in Commit. If it fails, the error will be already be
+ // logged. The best way to recover is to continue, as index cannot be corrupted by
+ // a missed commit to disk for an advanced index state.
+ Commit();
return;
}
@@ -103,11 +107,17 @@ void BaseIndex::ThreadSync()
LOCK(cs_main);
const CBlockIndex* pindex_next = NextSyncBlock(pindex);
if (!pindex_next) {
- WriteBestBlock(pindex);
m_best_block_index = pindex;
m_synced = true;
+ // No need to handle errors in Commit. See rationale above.
+ Commit();
break;
}
+ if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
+ FatalError("%s: Failed to rewind index %s to a previous chain tip",
+ __func__, GetName());
+ return;
+ }
pindex = pindex_next;
}
@@ -119,8 +129,10 @@ void BaseIndex::ThreadSync()
}
if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) {
- WriteBestBlock(pindex);
+ m_best_block_index = pindex;
last_locator_write_time = current_time;
+ // No need to handle errors in Commit. See rationale above.
+ Commit();
}
CBlock block;
@@ -144,12 +156,35 @@ void BaseIndex::ThreadSync()
}
}
-bool BaseIndex::WriteBestBlock(const CBlockIndex* block_index)
+bool BaseIndex::Commit()
+{
+ CDBBatch batch(GetDB());
+ if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) {
+ return error("%s: Failed to commit latest %s state", __func__, GetName());
+ }
+ return true;
+}
+
+bool BaseIndex::CommitInternal(CDBBatch& batch)
{
LOCK(cs_main);
- if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) {
- return error("%s: Failed to write locator to disk", __func__);
+ GetDB().WriteBestBlock(batch, chainActive.GetLocator(m_best_block_index));
+ return true;
+}
+
+bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+{
+ assert(current_tip == m_best_block_index);
+ assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
+
+ // In the case of a reorg, ensure persisted block locator is not stale.
+ m_best_block_index = new_tip;
+ if (!Commit()) {
+ // If commit fails, revert the best block index to avoid corruption.
+ m_best_block_index = current_tip;
+ return false;
}
+
return true;
}
@@ -180,6 +215,11 @@ void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const
best_block_index->GetBlockHash().ToString());
return;
}
+ if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) {
+ FatalError("%s: Failed to rewind index %s to a previous chain tip",
+ __func__, GetName());
+ return;
+ }
}
if (WriteBlock(*block, pindex)) {
@@ -224,9 +264,10 @@ void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
return;
}
- if (!GetDB().WriteBestBlock(locator)) {
- error("%s: Failed to write locator to disk", __func__);
- }
+ // No need to handle errors in Commit. If it fails, the error will be already be logged. The
+ // best way to recover is to continue, as index cannot be corrupted by a missed commit to disk
+ // for an advanced index state.
+ Commit();
}
bool BaseIndex::BlockUntilSyncedToCurrentChain()
diff --git a/src/index/base.h b/src/index/base.h
index 04ee6e6cc2..31acbed0c1 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -32,7 +32,7 @@ protected:
bool ReadBestBlock(CBlockLocator& locator) const;
/// Write block locator of the chain that the txindex is in sync with.
- bool WriteBestBlock(const CBlockLocator& locator);
+ void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);
};
private:
@@ -54,8 +54,15 @@ private:
/// over and the sync thread exits.
void ThreadSync();
- /// Write the current chain block locator to the DB.
- bool WriteBestBlock(const CBlockIndex* block_index);
+ /// Write the current index state (eg. chain block locator and subclass-specific items) to disk.
+ ///
+ /// Recommendations for error handling:
+ /// If called on a successor of the previous committed best block in the index, the index can
+ /// continue processing without risk of corruption, though the index state will need to catch up
+ /// from further behind on reboot. If the new state is not a successor of the previous state (due
+ /// to a chain reorganization), the index must halt until Commit succeeds or else it could end up
+ /// getting corrupted.
+ bool Commit();
protected:
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
@@ -69,6 +76,14 @@ protected:
/// Write update index entries for a newly connected block.
virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
+ /// Virtual method called internally by Commit that can be overridden to atomically
+ /// commit more index state.
+ virtual bool CommitInternal(CDBBatch& batch);
+
+ /// Rewind index to an earlier chain tip during a chain reorg. The tip must
+ /// be an ancestor of the current best block.
+ virtual bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
+
virtual DB& GetDB() const = 0;
/// Get the name of the index for display in logs.
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
new file mode 100644
index 0000000000..20f33baf2c
--- /dev/null
+++ b/src/index/blockfilterindex.cpp
@@ -0,0 +1,467 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <map>
+
+#include <dbwrapper.h>
+#include <index/blockfilterindex.h>
+#include <util/system.h>
+#include <validation.h>
+
+/* The index database stores three items for each block: the disk location of the encoded filter,
+ * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by
+ * height, and those belonging to blocks that have been reorganized out of the active chain are
+ * indexed by block hash. This ensures that filter data for any block that becomes part of the
+ * active chain can always be retrieved, alleviating timing concerns.
+ *
+ * The filters themselves are stored in flat files and referenced by the LevelDB entries. This
+ * minimizes the amount of data written to LevelDB and keeps the database values constant size. The
+ * disk location of the next block filter to be written (represented as a FlatFilePos) is stored
+ * under the DB_FILTER_POS key.
+ *
+ * Keys for the height index have the type [DB_BLOCK_HEIGHT, uint32 (BE)]. The height is represented
+ * as big-endian so that sequential reads of filters by height are fast.
+ * Keys for the hash index have the type [DB_BLOCK_HASH, uint256].
+ */
+constexpr char DB_BLOCK_HASH = 's';
+constexpr char DB_BLOCK_HEIGHT = 't';
+constexpr char DB_FILTER_POS = 'P';
+
+constexpr unsigned int MAX_FLTR_FILE_SIZE = 0x1000000; // 16 MiB
+/** The pre-allocation chunk size for fltr?????.dat files */
+constexpr unsigned int FLTR_FILE_CHUNK_SIZE = 0x100000; // 1 MiB
+
+namespace {
+
+struct DBVal {
+ uint256 hash;
+ uint256 header;
+ FlatFilePos pos;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(hash);
+ READWRITE(header);
+ READWRITE(pos);
+ }
+};
+
+struct DBHeightKey {
+ int height;
+
+ DBHeightKey() : height(0) {}
+ DBHeightKey(int height_in) : height(height_in) {}
+
+ template<typename Stream>
+ void Serialize(Stream& s) const
+ {
+ ser_writedata8(s, DB_BLOCK_HEIGHT);
+ ser_writedata32be(s, height);
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream& s)
+ {
+ char prefix = ser_readdata8(s);
+ if (prefix != DB_BLOCK_HEIGHT) {
+ throw std::ios_base::failure("Invalid format for block filter index DB height key");
+ }
+ height = ser_readdata32be(s);
+ }
+};
+
+struct DBHashKey {
+ uint256 hash;
+
+ DBHashKey(const uint256& hash_in) : hash(hash_in) {}
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ char prefix = DB_BLOCK_HASH;
+ READWRITE(prefix);
+ if (prefix != DB_BLOCK_HASH) {
+ throw std::ios_base::failure("Invalid format for block filter index DB hash key");
+ }
+
+ READWRITE(hash);
+ }
+};
+
+}; // namespace
+
+static std::map<BlockFilterType, BlockFilterIndex> g_filter_indexes;
+
+BlockFilterIndex::BlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory, bool f_wipe)
+ : m_filter_type(filter_type)
+{
+ const std::string& filter_name = BlockFilterTypeName(filter_type);
+ if (filter_name.empty()) throw std::invalid_argument("unknown filter_type");
+
+ fs::path path = GetDataDir() / "indexes" / "blockfilter" / filter_name;
+ fs::create_directories(path);
+
+ m_name = filter_name + " block filter index";
+ m_db = MakeUnique<BaseIndex::DB>(path / "db", n_cache_size, f_memory, f_wipe);
+ m_filter_fileseq = MakeUnique<FlatFileSeq>(std::move(path), "fltr", FLTR_FILE_CHUNK_SIZE);
+}
+
+bool BlockFilterIndex::Init()
+{
+ if (!m_db->Read(DB_FILTER_POS, m_next_filter_pos)) {
+ // Check that the cause of the read failure is that the key does not exist. Any other errors
+ // indicate database corruption or a disk failure, and starting the index would cause
+ // further corruption.
+ if (m_db->Exists(DB_FILTER_POS)) {
+ return error("%s: Cannot read current %s state; index may be corrupted",
+ __func__, GetName());
+ }
+
+ // If the DB_FILTER_POS is not set, then initialize to the first location.
+ m_next_filter_pos.nFile = 0;
+ m_next_filter_pos.nPos = 0;
+ }
+ return BaseIndex::Init();
+}
+
+bool BlockFilterIndex::CommitInternal(CDBBatch& batch)
+{
+ const FlatFilePos& pos = m_next_filter_pos;
+
+ // Flush current filter file to disk.
+ CAutoFile file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (file.IsNull()) {
+ return error("%s: Failed to open filter file %d", __func__, pos.nFile);
+ }
+ if (!FileCommit(file.Get())) {
+ return error("%s: Failed to commit filter file %d", __func__, pos.nFile);
+ }
+
+ batch.Write(DB_FILTER_POS, pos);
+ return BaseIndex::CommitInternal(batch);
+}
+
+bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const
+{
+ CAutoFile filein(m_filter_fileseq->Open(pos, true), SER_DISK, CLIENT_VERSION);
+ if (filein.IsNull()) {
+ return false;
+ }
+
+ uint256 block_hash;
+ std::vector<unsigned char> encoded_filter;
+ try {
+ filein >> block_hash >> encoded_filter;
+ filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter));
+ }
+ catch (const std::exception& e) {
+ return error("%s: Failed to deserialize block filter from disk: %s", __func__, e.what());
+ }
+
+ return true;
+}
+
+size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter)
+{
+ assert(filter.GetFilterType() == GetFilterType());
+
+ size_t data_size =
+ GetSerializeSize(filter.GetBlockHash(), CLIENT_VERSION) +
+ GetSerializeSize(filter.GetEncodedFilter(), CLIENT_VERSION);
+
+ // If writing the filter would overflow the file, flush and move to the next one.
+ if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
+ CAutoFile last_file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (last_file.IsNull()) {
+ LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+ if (!TruncateFile(last_file.Get(), pos.nPos)) {
+ LogPrintf("%s: Failed to truncate filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+ if (!FileCommit(last_file.Get())) {
+ LogPrintf("%s: Failed to commit filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+
+ pos.nFile++;
+ pos.nPos = 0;
+ }
+
+ // Pre-allocate sufficient space for filter data.
+ bool out_of_space;
+ m_filter_fileseq->Allocate(pos, data_size, out_of_space);
+ if (out_of_space) {
+ LogPrintf("%s: out of disk space\n", __func__);
+ return 0;
+ }
+
+ CAutoFile fileout(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (fileout.IsNull()) {
+ LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+
+ fileout << filter.GetBlockHash() << filter.GetEncodedFilter();
+ return data_size;
+}
+
+bool BlockFilterIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
+{
+ CBlockUndo block_undo;
+ uint256 prev_header;
+
+ if (pindex->nHeight > 0) {
+ if (!UndoReadFromDisk(block_undo, pindex)) {
+ return false;
+ }
+
+ std::pair<uint256, DBVal> read_out;
+ if (!m_db->Read(DBHeightKey(pindex->nHeight - 1), read_out)) {
+ return false;
+ }
+
+ uint256 expected_block_hash = pindex->pprev->GetBlockHash();
+ if (read_out.first != expected_block_hash) {
+ return error("%s: previous block header belongs to unexpected block %s; expected %s",
+ __func__, read_out.first.ToString(), expected_block_hash.ToString());
+ }
+
+ prev_header = read_out.second.header;
+ }
+
+ BlockFilter filter(m_filter_type, block, block_undo);
+
+ size_t bytes_written = WriteFilterToDisk(m_next_filter_pos, filter);
+ if (bytes_written == 0) return false;
+
+ std::pair<uint256, DBVal> value;
+ value.first = pindex->GetBlockHash();
+ value.second.hash = filter.GetHash();
+ value.second.header = filter.ComputeHeader(prev_header);
+ value.second.pos = m_next_filter_pos;
+
+ if (!m_db->Write(DBHeightKey(pindex->nHeight), value)) {
+ return false;
+ }
+
+ m_next_filter_pos.nPos += bytes_written;
+ return true;
+}
+
+static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
+ const std::string& index_name,
+ int start_height, int stop_height)
+{
+ DBHeightKey key(start_height);
+ db_it.Seek(key);
+
+ for (int height = start_height; height <= stop_height; ++height) {
+ if (!db_it.GetKey(key) || key.height != height) {
+ return error("%s: unexpected key in %s: expected (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ std::pair<uint256, DBVal> value;
+ if (!db_it.GetValue(value)) {
+ return error("%s: unable to read value in %s at key (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ batch.Write(DBHashKey(value.first), std::move(value.second));
+
+ db_it.Next();
+ }
+ return true;
+}
+
+bool BlockFilterIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+{
+ assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
+
+ CDBBatch batch(*m_db);
+ std::unique_ptr<CDBIterator> db_it(m_db->NewIterator());
+
+ // During a reorg, we need to copy all filters for blocks that are getting disconnected from the
+ // height index to the hash index so we can still find them when the height index entries are
+ // overwritten.
+ if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip->nHeight, current_tip->nHeight)) {
+ return false;
+ }
+
+ // The latest filter position gets written in Commit by the call to the BaseIndex::Rewind.
+ // But since this creates new references to the filter, the position should get updated here
+ // atomically as well in case Commit fails.
+ batch.Write(DB_FILTER_POS, m_next_filter_pos);
+ if (!m_db->WriteBatch(batch)) return false;
+
+ return BaseIndex::Rewind(current_tip, new_tip);
+}
+
+static bool LookupOne(const CDBWrapper& db, const CBlockIndex* block_index, DBVal& result)
+{
+ // First check if the result is stored under the height index and the value there matches the
+ // block hash. This should be the case if the block is on the active chain.
+ std::pair<uint256, DBVal> read_out;
+ if (!db.Read(DBHeightKey(block_index->nHeight), read_out)) {
+ return false;
+ }
+ if (read_out.first == block_index->GetBlockHash()) {
+ result = std::move(read_out.second);
+ return true;
+ }
+
+ // If value at the height index corresponds to an different block, the result will be stored in
+ // the hash index.
+ return db.Read(DBHashKey(block_index->GetBlockHash()), result);
+}
+
+static bool LookupRange(CDBWrapper& db, const std::string& index_name, int start_height,
+ const CBlockIndex* stop_index, std::vector<DBVal>& results)
+{
+ if (start_height < 0) {
+ return error("%s: start height (%d) is negative", __func__, start_height);
+ }
+ if (start_height > stop_index->nHeight) {
+ return error("%s: start height (%d) is greater than stop height (%d)",
+ __func__, start_height, stop_index->nHeight);
+ }
+
+ size_t results_size = static_cast<size_t>(stop_index->nHeight - start_height + 1);
+ std::vector<std::pair<uint256, DBVal>> values(results_size);
+
+ DBHeightKey key(start_height);
+ std::unique_ptr<CDBIterator> db_it(db.NewIterator());
+ db_it->Seek(DBHeightKey(start_height));
+ for (int height = start_height; height <= stop_index->nHeight; ++height) {
+ if (!db_it->Valid() || !db_it->GetKey(key) || key.height != height) {
+ return false;
+ }
+
+ size_t i = static_cast<size_t>(height - start_height);
+ if (!db_it->GetValue(values[i])) {
+ return error("%s: unable to read value in %s at key (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ db_it->Next();
+ }
+
+ results.resize(results_size);
+
+ // Iterate backwards through block indexes collecting results in order to access the block hash
+ // of each entry in case we need to look it up in the hash index.
+ for (const CBlockIndex* block_index = stop_index;
+ block_index && block_index->nHeight >= start_height;
+ block_index = block_index->pprev) {
+ uint256 block_hash = block_index->GetBlockHash();
+
+ size_t i = static_cast<size_t>(block_index->nHeight - start_height);
+ if (block_hash == values[i].first) {
+ results[i] = std::move(values[i].second);
+ continue;
+ }
+
+ if (!db.Read(DBHashKey(block_hash), results[i])) {
+ return error("%s: unable to read value in %s at key (%c, %s)",
+ __func__, index_name, DB_BLOCK_HASH, block_hash.ToString());
+ }
+ }
+
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const
+{
+ DBVal entry;
+ if (!LookupOne(*m_db, block_index, entry)) {
+ return false;
+ }
+
+ return ReadFilterFromDisk(entry.pos, filter_out);
+}
+
+bool BlockFilterIndex::LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) const
+{
+ DBVal entry;
+ if (!LookupOne(*m_db, block_index, entry)) {
+ return false;
+ }
+
+ header_out = entry.header;
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilterRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<BlockFilter>& filters_out) const
+{
+ std::vector<DBVal> entries;
+ if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
+ return false;
+ }
+
+ filters_out.resize(entries.size());
+ auto filter_pos_it = filters_out.begin();
+ for (const auto& entry : entries) {
+ if (!ReadFilterFromDisk(entry.pos, *filter_pos_it)) {
+ return false;
+ }
+ ++filter_pos_it;
+ }
+
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilterHashRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<uint256>& hashes_out) const
+
+{
+ std::vector<DBVal> entries;
+ if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
+ return false;
+ }
+
+ hashes_out.clear();
+ hashes_out.reserve(entries.size());
+ for (const auto& entry : entries) {
+ hashes_out.push_back(entry.hash);
+ }
+ return true;
+}
+
+BlockFilterIndex* GetBlockFilterIndex(BlockFilterType filter_type)
+{
+ auto it = g_filter_indexes.find(filter_type);
+ return it != g_filter_indexes.end() ? &it->second : nullptr;
+}
+
+void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn)
+{
+ for (auto& entry : g_filter_indexes) fn(entry.second);
+}
+
+bool InitBlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory, bool f_wipe)
+{
+ auto result = g_filter_indexes.emplace(std::piecewise_construct,
+ std::forward_as_tuple(filter_type),
+ std::forward_as_tuple(filter_type,
+ n_cache_size, f_memory, f_wipe));
+ return result.second;
+}
+
+bool DestroyBlockFilterIndex(BlockFilterType filter_type)
+{
+ return g_filter_indexes.erase(filter_type);
+}
+
+void DestroyAllBlockFilterIndexes()
+{
+ g_filter_indexes.clear();
+}
diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h
new file mode 100644
index 0000000000..436d52515f
--- /dev/null
+++ b/src/index/blockfilterindex.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_INDEX_BLOCKFILTERINDEX_H
+#define BITCOIN_INDEX_BLOCKFILTERINDEX_H
+
+#include <blockfilter.h>
+#include <chain.h>
+#include <flatfile.h>
+#include <index/base.h>
+
+/**
+ * BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of
+ * blocks by height. An index is constructed for each supported filter type with its own database
+ * (ie. filter data for different types are stored in separate databases).
+ *
+ * This index is used to serve BIP 157 net requests.
+ */
+class BlockFilterIndex final : public BaseIndex
+{
+private:
+ BlockFilterType m_filter_type;
+ std::string m_name;
+ std::unique_ptr<BaseIndex::DB> m_db;
+
+ FlatFilePos m_next_filter_pos;
+ std::unique_ptr<FlatFileSeq> m_filter_fileseq;
+
+ bool ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const;
+ size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter);
+
+protected:
+ bool Init() override;
+
+ bool CommitInternal(CDBBatch& batch) override;
+
+ bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
+
+ bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip) override;
+
+ BaseIndex::DB& GetDB() const override { return *m_db; }
+
+ const char* GetName() const override { return m_name.c_str(); }
+
+public:
+ /** Constructs the index, which becomes available to be queried. */
+ explicit BlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+
+ BlockFilterType GetFilterType() const { return m_filter_type; }
+
+ /** Get a single filter by block. */
+ bool LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const;
+
+ /** Get a single filter header by block. */
+ bool LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) const;
+
+ /** Get a range of filters between two heights on a chain. */
+ bool LookupFilterRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<BlockFilter>& filters_out) const;
+
+ /** Get a range of filter hashes between two heights on a chain. */
+ bool LookupFilterHashRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<uint256>& hashes_out) const;
+};
+
+/**
+ * Get a block filter index by type. Returns nullptr if index has not been initialized or was
+ * already destroyed.
+ */
+BlockFilterIndex* GetBlockFilterIndex(BlockFilterType filter_type);
+
+/** Iterate over all running block filter indexes, invoking fn on each. */
+void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn);
+
+/**
+ * Initialize a block filter index for the given type if one does not already exist. Returns true if
+ * a new index is created and false if one has already been initialized.
+ */
+bool InitBlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+
+/**
+ * Destroy the block filter index with the given type. Returns false if no such index exists. This
+ * just releases the allocated memory and closes the database connection, it does not delete the
+ * index data.
+ */
+bool DestroyBlockFilterIndex(BlockFilterType filter_type);
+
+/** Destroy all open block filter indexes. */
+void DestroyAllBlockFilterIndexes();
+
+#endif // BITCOIN_INDEX_BLOCKFILTERINDEX_H
diff --git a/src/init.cpp b/src/init.cpp
index 5b194add12..29c9694213 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -12,14 +12,15 @@
#include <addrman.h>
#include <amount.h>
#include <banman.h>
+#include <blockfilter.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 <index/blockfilterindex.h>
#include <interfaces/chain.h>
#include <index/txindex.h>
#include <key.h>
@@ -191,6 +192,7 @@ void Interrupt()
if (g_txindex) {
g_txindex->Interrupt();
}
+ ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); });
}
void Shutdown(InitInterfaces& interfaces)
@@ -222,6 +224,7 @@ void Shutdown(InitInterfaces& interfaces)
if (peerLogic) UnregisterValidationInterface(peerLogic.get());
if (g_connman) g_connman->Stop();
if (g_txindex) g_txindex->Stop();
+ ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); });
StopTorControl();
@@ -236,6 +239,7 @@ void Shutdown(InitInterfaces& interfaces)
g_connman.reset();
g_banman.reset();
g_txindex.reset();
+ DestroyAllBlockFilterIndexes();
if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool();
@@ -341,14 +345,15 @@ static void registerSignalHandler(int signal, void(*handler)(int))
}
#endif
+static boost::signals2::connection rpc_notify_block_change_connection;
static void OnRPCStarted()
{
- uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange);
+ rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange);
}
static void OnRPCStopped()
{
- uiInterface.NotifyBlockTip_disconnect(&RPCNotifyBlockChange);
+ rpc_notify_block_change_connection.disconnect();
RPCNotifyBlockChange(false, nullptr);
g_best_block_cv.notify_all();
LogPrint(BCLog::RPC, "RPC stopped.\n");
@@ -406,6 +411,10 @@ void SetupServerArgs()
hidden_args.emplace_back("-sysperms");
#endif
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blockfilterindex=<type>",
+ strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
+ " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
+ false, OptionsCategory::OPTIONS);
gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
@@ -873,6 +882,7 @@ int nUserMaxConnections;
int nFD;
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED);
int64_t peer_connect_timeout;
+std::vector<BlockFilterType> g_enabled_filter_types;
} // namespace
@@ -954,10 +964,29 @@ bool AppInitParameterInteraction()
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
}
+ // parse and validate enabled filter types
+ std::string blockfilterindex_value = gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
+ if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
+ g_enabled_filter_types = AllBlockFilterTypes();
+ } else if (blockfilterindex_value != "0") {
+ const std::vector<std::string> names = gArgs.GetArgs("-blockfilterindex");
+ g_enabled_filter_types.reserve(names.size());
+ for (const auto& name : names) {
+ BlockFilterType filter_type;
+ if (!BlockFilterTypeByName(name, filter_type)) {
+ return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
+ }
+ g_enabled_filter_types.push_back(filter_type);
+ }
+ }
+
// if using block pruning, then disallow txindex
if (gArgs.GetArg("-prune", 0)) {
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
return InitError(_("Prune mode is incompatible with -txindex."));
+ if (!g_enabled_filter_types.empty()) {
+ return InitError(_("Prune mode is incompatible with -blockfilterindex."));
+ }
}
// -bind and -whitebind can't be set when not listening
@@ -1432,6 +1461,13 @@ bool AppInitMain(InitInterfaces& interfaces)
nTotalCache -= nBlockTreeDBCache;
int64_t nTxIndexCache = std::min(nTotalCache / 8, gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0);
nTotalCache -= nTxIndexCache;
+ int64_t filter_index_cache = 0;
+ if (!g_enabled_filter_types.empty()) {
+ size_t n_indexes = g_enabled_filter_types.size();
+ int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20);
+ filter_index_cache = max_cache / n_indexes;
+ nTotalCache -= filter_index_cache * n_indexes;
+ }
int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
nTotalCache -= nCoinDBCache;
@@ -1442,6 +1478,10 @@ bool AppInitMain(InitInterfaces& interfaces)
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
LogPrintf("* Using %.1f MiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024));
}
+ for (BlockFilterType filter_type : g_enabled_filter_types) {
+ LogPrintf("* Using %.1f MiB for %s block filter index database\n",
+ filter_index_cache * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
+ }
LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
@@ -1629,6 +1669,11 @@ bool AppInitMain(InitInterfaces& interfaces)
g_txindex->Start();
}
+ for (const auto& filter_type : g_enabled_filter_types) {
+ InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
+ GetBlockFilterIndex(filter_type)->Start();
+ }
+
// ********************************************************* Step 9: load wallet
for (const auto& client : interfaces.chain_clients) {
if (!client->load()) {
@@ -1671,8 +1716,9 @@ bool AppInitMain(InitInterfaces& interfaces)
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
+ boost::signals2::connection block_notify_genesis_wait_connection;
if (chainActive.Tip() == nullptr) {
- uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait);
+ block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait);
} else {
fHaveGenesis = true;
}
@@ -1696,7 +1742,7 @@ bool AppInitMain(InitInterfaces& interfaces)
while (!fHaveGenesis && !ShutdownRequested()) {
g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500));
}
- uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait);
+ block_notify_genesis_wait_connection.disconnect();
}
if (ShutdownRequested()) {
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index 16e0d1d6c0..839af650bb 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -84,29 +84,15 @@ class LockImpl : public Chain::Lock
CBlockIndex* block = ::chainActive[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
- Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) override
+ Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
{
- CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time);
+ CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time, height);
if (block) {
if (hash) *hash = block->GetBlockHash();
return block->nHeight;
}
return nullopt;
}
- Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height) override
- {
- // TODO: Could update CChain::FindEarliestAtLeast() to take a height
- // parameter and use it with std::lower_bound() to make this
- // implementation more efficient and allow combining
- // findFirstBlockWithTime and findFirstBlockWithTimeAndHeight into one
- // method.
- for (CBlockIndex* block = ::chainActive[height]; block; block = ::chainActive.Next(block)) {
- if (block->GetBlockTime() >= time) {
- return block->nHeight;
- }
- }
- return nullopt;
- }
Optional<int> findPruned(int start_height, Optional<int> stop_height) override
{
if (::fPruneMode) {
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index d62ee683fa..7564ad26ac 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -105,20 +105,11 @@ public:
virtual bool haveBlockOnDisk(int height) = 0;
//! Return height of the first block in the chain with timestamp equal
- //! or greater than the given time, or nullopt if there is no block with
- //! a high enough timestamp. Also return the block hash as an optional
- //! output parameter (to avoid the cost of a second lookup in case this
- //! information is needed.)
- virtual Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) = 0;
-
- //! Return height of the first block in the chain with timestamp equal
//! or greater than the given time and height equal or greater than the
- //! given height, or nullopt if there is no such block.
- //!
- //! Calling this with height 0 is equivalent to calling
- //! findFirstBlockWithTime, but less efficient because it requires a
- //! linear instead of a binary search.
- virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height) = 0;
+ //! given height, or nullopt if there is no block with a high enough
+ //! timestamp and height. Also return the block hash as an optional output parameter
+ //! (to avoid the cost of a second lookup in case this information is needed.)
+ virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
//! Return height of last block in the specified range which is pruned, or
//! nullopt if no block in the range is pruned. Range is inclusive.
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index e5aee2d806..b57299d78d 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -269,8 +269,13 @@ public:
CAmount& new_fee,
CMutableTransaction& mtx) override
{
- return feebumper::CreateTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
- feebumper::Result::OK;
+ if (total_fee > 0) {
+ return feebumper::CreateTotalBumpTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
+ feebumper::Result::OK;
+ } else {
+ return feebumper::CreateRateBumpTransaction(m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) ==
+ feebumper::Result::OK;
+ }
}
bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(m_wallet.get(), mtx); }
bool commitBumpTransaction(const uint256& txid,
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 6f8542123d..63a3d06267 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -59,7 +59,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
std::vector<std::vector<unsigned char> > vSolutions;
whichType = Solver(scriptPubKey, vSolutions);
- if (whichType == TX_NONSTANDARD || whichType == TX_WITNESS_UNKNOWN) {
+ if (whichType == TX_NONSTANDARD) {
return false;
} else if (whichType == TX_MULTISIG) {
unsigned char m = vSolutions.front()[0];
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index f6f8e31363..aad991e2f1 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -222,6 +222,10 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
for (size_t i = 0; i < tx.vin.size(); i++) {
s >> tx.vin[i].scriptWitness.stack;
}
+ if (!tx.HasWitness()) {
+ /* It's illegal to encode witnesses when all witness stacks are empty. */
+ throw std::ios_base::failure("Superfluous witness record");
+ }
}
if (flags) {
/* Unknown flag in the serialization */
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 726dafccb0..50d6afabcd 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -107,7 +107,7 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
ui->newAddress->setVisible(true);
break;
case ReceivingTab:
- ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction."));
+ ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses."));
ui->deleteAddress->setVisible(false);
ui->newAddress->setVisible(false);
break;
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 27b4c182f9..88a35534c2 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -11,7 +11,6 @@
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <clientversion.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui
index 8876ea1337..0d280f2993 100644
--- a/src/qt/forms/receivecoinsdialog.ui
+++ b/src/qt/forms/receivecoinsdialog.ui
@@ -108,7 +108,7 @@
</size>
</property>
<property name="text">
- <string>&amp;Request payment</string>
+ <string>&amp;Create new receiving address</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index ba0a5abdf3..6e76555979 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -244,6 +244,11 @@ QList<QModelIndex> getEntryData(QAbstractItemView *view, int column)
return view->selectionModel()->selectedRows(column);
}
+QString getDefaultDataDirectory()
+{
+ return boostPathToQString(GetDefaultDataDir());
+}
+
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index cbec73a882..bea4a83494 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -79,6 +79,11 @@ namespace GUIUtil
void setClipboard(const QString& str);
+ /**
+ * Determine default data directory for operating system.
+ */
+ QString getDefaultDataDirectory();
+
/** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
when no suffix is provided by the user.
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index 499af9fa07..c595361934 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -168,7 +168,7 @@ QString Intro::getDataDirectory()
void Intro::setDataDirectory(const QString &dataDir)
{
ui->dataDirectory->setText(dataDir);
- if(dataDir == getDefaultDataDirectory())
+ if(dataDir == GUIUtil::getDefaultDataDirectory())
{
ui->dataDirDefault->setChecked(true);
ui->dataDirectory->setEnabled(false);
@@ -180,11 +180,6 @@ void Intro::setDataDirectory(const QString &dataDir)
}
}
-QString Intro::getDefaultDataDirectory()
-{
- return GUIUtil::boostPathToQString(GetDefaultDataDir());
-}
-
bool Intro::pickDataDirectory(interfaces::Node& node)
{
QSettings settings;
@@ -193,7 +188,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
if(!gArgs.GetArg("-datadir", "").empty())
return true;
/* 1) Default data directory for operating system */
- QString dataDir = getDefaultDataDirectory();
+ QString dataDir = GUIUtil::getDefaultDataDirectory();
/* 2) Allow QSettings to override default dir */
dataDir = settings.value("strDataDir", dataDir).toString();
@@ -239,7 +234,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
* override -datadir in the bitcoin.conf file in the default data directory
* (to be consistent with bitcoind behavior)
*/
- if(dataDir != getDefaultDataDirectory()) {
+ if(dataDir != GUIUtil::getDefaultDataDirectory()) {
node.softSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
}
return true;
@@ -293,7 +288,7 @@ void Intro::on_ellipsisButton_clicked()
void Intro::on_dataDirDefault_clicked()
{
- setDataDirectory(getDefaultDataDirectory());
+ setDataDirectory(GUIUtil::getDefaultDataDirectory());
}
void Intro::on_dataDirCustom_clicked()
diff --git a/src/qt/intro.h b/src/qt/intro.h
index b537c94f7d..c3b26808d4 100644
--- a/src/qt/intro.h
+++ b/src/qt/intro.h
@@ -48,11 +48,6 @@ public:
*/
static bool pickDataDirectory(interfaces::Node& node);
- /**
- * Determine default data directory for operating system.
- */
- static QString getDefaultDataDirectory();
-
Q_SIGNALS:
void requestCheck();
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 9094aeff56..40dc7bf400 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -154,6 +154,10 @@ void OptionsDialog::setModel(OptionsModel *_model)
if (_model->isRestartRequired())
showRestartWarning(true);
+ // Prune values are in GB to be consistent with intro.cpp
+ static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) + (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES) ? 1 : 0;
+ ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits<int>::max());
+
QString strLabel = _model->getOverriddenByCommandLine();
if (strLabel.isEmpty())
strLabel = tr("none");
@@ -164,10 +168,6 @@ void OptionsDialog::setModel(OptionsModel *_model)
mapper->toFirst();
updateDefaultProxyNets();
-
- // Prune values are in GB to be consistent with intro.cpp
- static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) + (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES) ? 1 : 0;
- ui->pruneSize->setRange(nMinDiskSpace, _model->node().getAssumedBlockchainSize());
}
/* warn when one of the following settings changes by user action (placed here so init via mapper doesn't trigger them) */
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 62496a57f4..5b4fb4cc18 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -17,7 +17,6 @@
#include <net.h>
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
-#include <qt/intro.h>
#include <QNetworkProxy>
#include <QSettings>
@@ -110,7 +109,7 @@ void OptionsModel::Init(bool resetSettings)
addOverriddenOption("-par");
if (!settings.contains("strDataDir"))
- settings.setValue("strDataDir", Intro::getDefaultDataDirectory());
+ settings.setValue("strDataDir", GUIUtil::getDefaultDataDirectory());
// Wallet
#ifdef ENABLE_WALLET
@@ -187,7 +186,7 @@ void OptionsModel::Reset()
BackupSettings(GetDataDir(true) / "guisettings.ini.bak", settings);
// Save the strDataDir setting
- QString dataDir = Intro::getDefaultDataDirectory();
+ QString dataDir = GUIUtil::getDefaultDataDirectory();
dataDir = settings.value("strDataDir", dataDir).toString();
// Remove all entries from our QSettings object
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index e33a9a4e1e..2ba1c2604c 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -1,6 +1,6 @@
#include <qt/test/addressbooktests.h>
#include <qt/test/util.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <interfaces/chain.h>
#include <interfaces/node.h>
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index f8a9c25303..b0bd89b290 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -12,7 +12,7 @@
#include <rpc/register.h>
#include <rpc/server.h>
#include <qt/rpcconsole.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <univalue.h>
#include <util/system.h>
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index bd1c6cf0f4..9e3518fd53 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -15,7 +15,7 @@
#include <qt/transactionview.h>
#include <qt/walletmodel.h>
#include <key_io.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <wallet/wallet.h>
#include <qt/overviewpage.h>
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 3db24080db..672fc69673 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -7,13 +7,14 @@
#include <amount.h>
#include <base58.h>
+#include <blockfilter.h>
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <coins.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <hash.h>
+#include <index/blockfilterindex.h>
#include <index/txindex.h>
#include <key_io.h>
#include <policy/feerate.h>
@@ -1011,7 +1012,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
// too low to be a block time (corresponds to timestamp from Sep 2001).
if (heightParam > 1000000000) {
// Add a 2 hour buffer to include blocks which might have had old timestamps
- CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW);
+ CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
}
@@ -1487,6 +1488,8 @@ static UniValue getchaintips(const JSONRPCRequest& request)
UniValue MempoolInfoToJSON(const CTxMemPool& pool)
{
+ // Make sure this call is atomic in the pool.
+ LOCK(pool.cs);
UniValue ret(UniValue::VOBJ);
ret.pushKV("size", (int64_t)pool.size());
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
@@ -2297,6 +2300,85 @@ UniValue scantxoutset(const JSONRPCRequest& request)
return result;
}
+static UniValue getblockfilter(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
+ throw std::runtime_error(
+ RPCHelpMan{"getblockfilter",
+ "\nRetrieve a BIP 157 content filter for a particular block.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"},
+ {"filtertype", RPCArg::Type::STR, /*default*/ "basic", "The type name of the filter"},
+ },
+ RPCResult{
+ "{\n"
+ " \"filter\" : (string) the hex-encoded filter data\n"
+ " \"header\" : (string) the hex-encoded filter header\n"
+ "}\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"")
+ }
+ }.ToString()
+ );
+ }
+
+ uint256 block_hash = ParseHashV(request.params[0], "blockhash");
+ std::string filtertype_name = "basic";
+ if (!request.params[1].isNull()) {
+ filtertype_name = request.params[1].get_str();
+ }
+
+ BlockFilterType filtertype;
+ if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
+ }
+
+ BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
+ if (!index) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name);
+ }
+
+ const CBlockIndex* block_index;
+ bool block_was_connected;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block_hash);
+ if (!block_index) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ block_was_connected = block_index->IsValid(BLOCK_VALID_SCRIPTS);
+ }
+
+ bool index_ready = index->BlockUntilSyncedToCurrentChain();
+
+ BlockFilter filter;
+ uint256 filter_header;
+ if (!index->LookupFilter(block_index, filter) ||
+ !index->LookupFilterHeader(block_index, filter_header)) {
+ int err_code;
+ std::string errmsg = "Filter not found.";
+
+ if (!block_was_connected) {
+ err_code = RPC_INVALID_ADDRESS_OR_KEY;
+ errmsg += " Block was not connected to active chain.";
+ } else if (!index_ready) {
+ err_code = RPC_MISC_ERROR;
+ errmsg += " Block filters are still in the process of being indexed.";
+ } else {
+ err_code = RPC_INTERNAL_ERROR;
+ errmsg += " This error is unexpected and indicates index corruption.";
+ }
+
+ throw JSONRPCError(err_code, errmsg);
+ }
+
+ UniValue ret(UniValue::VOBJ);
+ ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));
+ ret.pushKV("header", filter_header.GetHex());
+ return ret;
+}
+
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -2324,6 +2406,7 @@ static const CRPCCommand commands[] =
{ "blockchain", "preciousblock", &preciousblock, {"blockhash"} },
{ "blockchain", "scantxoutset", &scantxoutset, {"action", "scanobjects"} },
+ { "blockchain", "getblockfilter", &getblockfilter, {"blockhash", "filtertype"} },
/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, {"blockhash"} },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index c636102b20..4de738a756 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -16,11 +16,12 @@
#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
-#include <rpc/mining.h>
#include <rpc/server.h>
#include <rpc/util.h>
+#include <script/script.h>
#include <shutdown.h>
#include <txmempool.h>
+#include <univalue.h>
#include <util/fees.h>
#include <util/strencodings.h>
#include <util/system.h>
@@ -100,7 +101,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
}
-UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
+static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
static const int nInnerLoopCount = 0x10000;
int nHeightEnd = 0;
@@ -115,7 +116,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd && !ShutdownRequested())
{
- std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript));
+ std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbase_script));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
@@ -138,12 +139,6 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
-
- //mark script as important because it was used at least for one coinbase output if the script came from the wallet
- if (keepScript)
- {
- coinbaseScript->KeepScript();
- }
}
return blockHashes;
}
@@ -181,10 +176,9 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
}
- std::shared_ptr<CReserveScript> coinbaseScript = std::make_shared<CReserveScript>();
- coinbaseScript->reserveScript = GetScriptForDestination(destination);
+ CScript coinbase_script = GetScriptForDestination(destination);
- return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
+ return generateBlocks(coinbase_script, nGenerate, nMaxTries);
}
static UniValue getmininginfo(const JSONRPCRequest& request)
diff --git a/src/rpc/mining.h b/src/rpc/mining.h
deleted file mode 100644
index be9a973315..0000000000
--- a/src/rpc/mining.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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_RPC_MINING_H
-#define BITCOIN_RPC_MINING_H
-
-#include <script/script.h>
-
-#include <univalue.h>
-
-/** Generate blocks (mine) */
-UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript);
-
-#endif
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index f221847347..bfb559f0db 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -229,8 +229,8 @@ UniValue deriveaddresses(const JSONRPCRequest& request)
range_end = range.second;
}
- FlatSigningProvider provider;
- auto desc = Parse(desc_str, provider, /* require_checksum = */ true);
+ FlatSigningProvider key_provider;
+ auto desc = Parse(desc_str, key_provider, /* require_checksum = */ true);
if (!desc) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor"));
}
@@ -246,8 +246,9 @@ UniValue deriveaddresses(const JSONRPCRequest& request)
UniValue addresses(UniValue::VARR);
for (int i = range_begin; i <= range_end; ++i) {
+ FlatSigningProvider provider;
std::vector<CScript> scripts;
- if (!desc->Expand(i, provider, scripts, provider)) {
+ if (!desc->Expand(i, key_provider, scripts, provider)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
}
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 91331198e2..78d7bbc80c 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -15,6 +15,7 @@
#include <key_io.h>
#include <keystore.h>
#include <merkleblock.h>
+#include <node/coin.h>
#include <node/psbt.h>
#include <node/transaction.h>
#include <policy/policy.h>
@@ -770,7 +771,14 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
keystore.AddKey(key);
}
- return SignTransaction(*g_rpc_interfaces->chain, mtx, request.params[2], &keystore, true, request.params[3]);
+ // Fetch previous transactions (inputs):
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ FindCoins(coins);
+
+ return SignTransaction(mtx, request.params[2], &keystore, coins, true, request.params[3]);
}
static UniValue sendrawtransaction(const JSONRPCRequest& request)
@@ -818,15 +826,13 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
// TODO: temporary migration code for old clients. Remove in v0.20
if (request.params[1].isBool()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
- } else if (request.params[1].isNum()) {
+ } else if (!request.params[1].isNull()) {
size_t weight = GetTransactionWeight(*tx);
CFeeRate fr(AmountFromValue(request.params[1]));
// the +3/4 part rounds the value up, and is the same formula used when
// calculating the fee for a transaction
// (see GetVirtualTransactionSize)
max_raw_tx_fee = fr.GetFee((weight+3)/4);
- } else if (!request.params[1].isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "second argument (maxfeerate) must be numeric");
}
uint256 txid;
@@ -900,15 +906,13 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
// TODO: temporary migration code for old clients. Remove in v0.20
if (request.params[1].isBool()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
- } else if (request.params[1].isNum()) {
+ } else if (!request.params[1].isNull()) {
size_t weight = GetTransactionWeight(*tx);
CFeeRate fr(AmountFromValue(request.params[1]));
// the +3/4 part rounds the value up, and is the same formula used when
// calculating the fee for a transaction
// (see GetVirtualTransactionSize)
max_raw_tx_fee = fr.GetFee((weight+3)/4);
- } else if (!request.params[1].isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "second argument (maxfeerate) must be numeric");
}
UniValue result(UniValue::VARR);
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 728fc62e25..8af491977c 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -149,18 +149,8 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
vErrorsRet.push_back(entry);
}
-// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237):
-// The dependency on interfaces::Chain should be removed, so
-// signrawtransactionwithkey doesn't need access to a Chain instance.
-UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
+UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore* keystore, std::map<COutPoint, Coin>& coins, bool is_temp_keystore, const UniValue& hashType)
{
- // Fetch previous transactions (inputs):
- std::map<COutPoint, Coin> coins;
- for (const CTxIn& txin : mtx.vin) {
- coins[txin.prevout]; // Create empty map entry keyed by prevout.
- }
- chain.findCoins(coins);
-
// Add previous txouts given in the RPC call:
if (!prevTxsUnival.isNull()) {
UniValue prevTxs = prevTxsUnival.get_array();
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 5529dedbd4..c115d33a77 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -5,16 +5,26 @@
#ifndef BITCOIN_RPC_RAWTRANSACTION_UTIL_H
#define BITCOIN_RPC_RAWTRANSACTION_UTIL_H
+#include <map>
+
class CBasicKeyStore;
class UniValue;
struct CMutableTransaction;
+class Coin;
+class COutPoint;
-namespace interfaces {
-class Chain;
-} // namespace interfaces
-
-/** Sign a transaction with the given keystore and previous transactions */
-UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore *keystore, bool tempKeystore, const UniValue& hashType);
+/**
+ * Sign a transaction with the given keystore and previous transactions
+ *
+ * @param mtx The transaction to-be-signed
+ * @param prevTxs Array of previous txns outputs that tx depends on but may not yet be in the block chain
+ * @param keystore Temporary keystore containing signing keys
+ * @param coins Map of unspent outputs - coins in mempool and current chain UTXO set, may be extended by previous txns outputs after call
+ * @param tempKeystore Whether to use temporary keystore
+ * @param hashType The signature hash type
+ * @returns JSON object with details of signed transaction
+ */
+UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore* keystore, std::map<COutPoint, Coin>& coins, bool tempKeystore, const UniValue& hashType);
/** Create a transaction from univalue parameters */
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf);
diff --git a/src/script/ismine.h b/src/script/ismine.h
index 601e70f709..55e28e225a 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -9,6 +9,7 @@
#include <script/standard.h>
#include <stdint.h>
+#include <bitset>
class CKeyStore;
class CScript;
@@ -16,10 +17,11 @@ class CScript;
/** IsMine() return codes */
enum isminetype
{
- ISMINE_NO = 0,
- ISMINE_WATCH_ONLY = 1,
- ISMINE_SPENDABLE = 2,
- ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
+ ISMINE_NO = 0,
+ ISMINE_WATCH_ONLY = 1 << 0,
+ ISMINE_SPENDABLE = 1 << 1,
+ ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE,
+ ISMINE_ENUM_ELEMENTS,
};
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
@@ -27,4 +29,23 @@ typedef uint8_t isminefilter;
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
+/**
+ * Cachable amount subdivided into watchonly and spendable parts.
+ */
+struct CachableAmount
+{
+ // NO and ALL are never (supposed to be) cached
+ std::bitset<ISMINE_ENUM_ELEMENTS> m_cached;
+ CAmount m_value[ISMINE_ENUM_ELEMENTS];
+ inline void Reset()
+ {
+ m_cached.reset();
+ }
+ void Set(isminefilter filter, CAmount value)
+ {
+ m_cached.set(filter);
+ m_value[filter] = value;
+ }
+};
+
#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/script.h b/src/script/script.h
index 1d8ddba2f2..11e8661a5b 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -581,13 +581,4 @@ struct CScriptWitness
std::string ToString() const;
};
-class CReserveScript
-{
-public:
- CScript reserveScript;
- virtual void KeepScript() {}
- CReserveScript() {}
- virtual ~CReserveScript() {}
-};
-
#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/script/standard.h b/src/script/standard.h
index fc20fb6a08..f16068c413 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -153,8 +153,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
* multisig scripts, this populates the addressRet vector with the pubkey IDs
* and nRequiredRet with the n required to spend. For other destinations,
* addressRet is populated with a single value and nRequiredRet is set to 1.
- * Returns true if successful. Currently does not extract address from
- * pay-to-witness scripts.
+ * Returns true if successful.
*
* Note: this function confuses destinations (a subset of CScripts that are
* encodable as an address) with key identifiers (of keys involved in a
diff --git a/src/serialize.h b/src/serialize.h
index 2d0cfbbbf0..b001ee1324 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -89,6 +89,11 @@ template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
obj = htole32(obj);
s.write((char*)&obj, 4);
}
+template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
+{
+ obj = htobe32(obj);
+ s.write((char*)&obj, 4);
+}
template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
{
obj = htole64(obj);
@@ -118,6 +123,12 @@ template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
s.read((char*)&obj, 4);
return le32toh(obj);
}
+template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
+{
+ uint32_t obj;
+ s.read((char*)&obj, 4);
+ return be32toh(obj);
+}
template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
{
uint64_t obj;
diff --git a/src/test/README.md b/src/test/README.md
index f2a4cb1818..0017e3de26 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -42,7 +42,7 @@ unit tests as possible).
The build system is setup to compile an executable called `test_bitcoin`
that runs all of the unit tests. The main source file is called
-test_bitcoin.cpp. To add a new unit test file to our test suite you need
+setup_common.cpp. To add a new unit test file to our test suite you need
to add the file to `src/Makefile.test.include`. The pattern is to create
one test file for each class or source file for which you want to create
unit tests. The file naming convention is `<source_filename>_tests.cpp`
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 22347fbc57..eeb54b4cf0 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrman.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
index 9eded4f5b2..f255691704 100644
--- a/src/test/allocator_tests.cpp
+++ b/src/test/allocator_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/system.h>
#include <support/allocators/secure.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index 1ff040b077..378fe285d5 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <amount.h>
#include <policy/feerate.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index 77b6008fd0..809c627d27 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <arith_uint256.h>
#include <string>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup)
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 32af843bf6..b3bed2434c 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index f8f9b3c1a7..cb376cddb6 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/base58_encode_decode.json.h>
#include <base58.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/strencodings.h>
#include <univalue.h>
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index 0abbb682a7..9ffffb0b7d 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
index 6ecc9ac705..0ba492c24e 100644
--- a/src/test/bech32_tests.cpp
+++ b/src/test/bech32_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bech32.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index c9951f4b7e..0c0423c0db 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index b61152985f..13afcca375 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <rpc/blockchain.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
/* Equality between doubles is imprecise. Comparison should be done
* with a small threshold of tolerance, rather than exact equality.
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 607af8a32a..f57e1a0ebd 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <pow.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -386,6 +386,7 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) {
BOOST_CHECK(0);
} catch(std::ios_base::failure &) {
// deserialize should fail
+ BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
}
}
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
new file mode 100644
index 0000000000..db0b973463
--- /dev/null
+++ b/src/test/blockfilter_index_tests.cpp
@@ -0,0 +1,307 @@
+// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <blockfilter.h>
+#include <chainparams.h>
+#include <consensus/validation.h>
+#include <index/blockfilterindex.h>
+#include <miner.h>
+#include <pow.h>
+#include <test/setup_common.h>
+#include <script/standard.h>
+#include <validation.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(blockfilter_index_tests)
+
+static bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index,
+ BlockFilter& filter)
+{
+ CBlock block;
+ if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) {
+ return false;
+ }
+
+ CBlockUndo block_undo;
+ if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) {
+ return false;
+ }
+
+ filter = BlockFilter(filter_type, block, block_undo);
+ return true;
+}
+
+static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index,
+ uint256& last_header)
+{
+ BlockFilter expected_filter;
+ if (!ComputeFilter(filter_index.GetFilterType(), block_index, expected_filter)) {
+ BOOST_ERROR("ComputeFilter failed on block " << block_index->nHeight);
+ return false;
+ }
+
+ BlockFilter filter;
+ uint256 filter_header;
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ BOOST_CHECK(filter_index.LookupFilter(block_index, filter));
+ BOOST_CHECK(filter_index.LookupFilterHeader(block_index, filter_header));
+ BOOST_CHECK(filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
+ BOOST_CHECK(filter_index.LookupFilterHashRange(block_index->nHeight, block_index,
+ filter_hashes));
+
+ BOOST_CHECK_EQUAL(filters.size(), 1);
+ BOOST_CHECK_EQUAL(filter_hashes.size(), 1);
+
+ BOOST_CHECK_EQUAL(filter.GetHash(), expected_filter.GetHash());
+ BOOST_CHECK_EQUAL(filter_header, expected_filter.ComputeHeader(last_header));
+ BOOST_CHECK_EQUAL(filters[0].GetHash(), expected_filter.GetHash());
+ BOOST_CHECK_EQUAL(filter_hashes[0], expected_filter.GetHash());
+
+ filters.clear();
+ filter_hashes.clear();
+ last_header = filter_header;
+ return true;
+}
+
+static CBlock CreateBlock(const CBlockIndex* prev,
+ const std::vector<CMutableTransaction>& txns,
+ const CScript& scriptPubKey)
+{
+ const CChainParams& chainparams = Params();
+ std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
+ CBlock& block = pblocktemplate->block;
+ block.hashPrevBlock = prev->GetBlockHash();
+ block.nTime = prev->nTime + 1;
+
+ // Replace mempool-selected txns with just coinbase plus passed-in txns:
+ block.vtx.resize(1);
+ for (const CMutableTransaction& tx : txns) {
+ block.vtx.push_back(MakeTransactionRef(tx));
+ }
+ // IncrementExtraNonce creates a valid coinbase and merkleRoot
+ unsigned int extraNonce = 0;
+ IncrementExtraNonce(&block, prev, extraNonce);
+
+ while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
+
+ return block;
+}
+
+static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script_pub_key,
+ size_t length, std::vector<std::shared_ptr<CBlock>>& chain)
+{
+ std::vector<CMutableTransaction> no_txns;
+
+ chain.resize(length);
+ for (auto& block : chain) {
+ block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
+ CBlockHeader header = block->GetBlockHeader();
+
+ CValidationState state;
+ if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
+{
+ BlockFilterIndex filter_index(BlockFilterType::BASIC, 1 << 20, true);
+
+ uint256 last_header;
+
+ // Filter should not be found in the index before it is started.
+ {
+ LOCK(cs_main);
+
+ BlockFilter filter;
+ uint256 filter_header;
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ for (const CBlockIndex* block_index = chainActive.Genesis();
+ block_index != nullptr;
+ block_index = chainActive.Next(block_index)) {
+ BOOST_CHECK(!filter_index.LookupFilter(block_index, filter));
+ BOOST_CHECK(!filter_index.LookupFilterHeader(block_index, filter_header));
+ BOOST_CHECK(!filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
+ BOOST_CHECK(!filter_index.LookupFilterHashRange(block_index->nHeight, block_index,
+ filter_hashes));
+ }
+ }
+
+ // BlockUntilSyncedToCurrentChain should return false before index is started.
+ BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain());
+
+ filter_index.Start();
+
+ // Allow filter index to catch up with the block index.
+ constexpr int64_t timeout_ms = 10 * 1000;
+ int64_t time_start = GetTimeMillis();
+ while (!filter_index.BlockUntilSyncedToCurrentChain()) {
+ BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
+ MilliSleep(100);
+ }
+
+ // Check that filter index has all blocks that were in the chain before it started.
+ {
+ LOCK(cs_main);
+ const CBlockIndex* block_index;
+ for (block_index = chainActive.Genesis();
+ block_index != nullptr;
+ block_index = chainActive.Next(block_index)) {
+ CheckFilterLookups(filter_index, block_index, last_header);
+ }
+ }
+
+ // Create two forks.
+ const CBlockIndex* tip;
+ {
+ LOCK(cs_main);
+ tip = chainActive.Tip();
+ }
+ CScript coinbase_script_pub_key = GetScriptForDestination(coinbaseKey.GetPubKey().GetID());
+ std::vector<std::shared_ptr<CBlock>> chainA, chainB;
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA));
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB));
+
+ // Check that new blocks on chain A get indexed.
+ uint256 chainA_last_header = last_header;
+ for (size_t i = 0; i < 2; i++) {
+ const auto& block = chainA[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ }
+
+ // Reorg to chain B.
+ uint256 chainB_last_header = last_header;
+ for (size_t i = 0; i < 3; i++) {
+ const auto& block = chainB[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ }
+
+ // Check that filters for stale blocks on A can be retrieved.
+ chainA_last_header = last_header;
+ for (size_t i = 0; i < 2; i++) {
+ const auto& block = chainA[i];
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ }
+
+ // Reorg back to chain A.
+ for (size_t i = 2; i < 4; i++) {
+ const auto& block = chainA[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ }
+
+ // Check that chain A and B blocks can be retrieved.
+ chainA_last_header = last_header;
+ chainB_last_header = last_header;
+ for (size_t i = 0; i < 3; i++) {
+ const CBlockIndex* block_index;
+
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(chainA[i]->GetHash());
+ }
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(chainB[i]->GetHash());
+ }
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ }
+
+ // Test lookups for a range of filters/hashes.
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ {
+ LOCK(cs_main);
+ tip = chainActive.Tip();
+ }
+ BOOST_CHECK(filter_index.LookupFilterRange(0, tip, filters));
+ BOOST_CHECK(filter_index.LookupFilterHashRange(0, tip, filter_hashes));
+
+ BOOST_CHECK_EQUAL(filters.size(), tip->nHeight + 1);
+ BOOST_CHECK_EQUAL(filter_hashes.size(), tip->nHeight + 1);
+
+ filters.clear();
+ filter_hashes.clear();
+
+ filter_index.Interrupt();
+ filter_index.Stop();
+}
+
+BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup)
+{
+ SetDataDir("tempdir");
+
+ BlockFilterIndex* filter_index;
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+
+ BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index != nullptr);
+ BOOST_CHECK(filter_index->GetFilterType() == BlockFilterType::BASIC);
+
+ // Initialize returns false if index already exists.
+ BOOST_CHECK(!InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ int iter_count = 0;
+ ForEachBlockFilterIndex([&iter_count](BlockFilterIndex& _index) { iter_count++; });
+ BOOST_CHECK_EQUAL(iter_count, 1);
+
+ BOOST_CHECK(DestroyBlockFilterIndex(BlockFilterType::BASIC));
+
+ // Destroy returns false because index was already destroyed.
+ BOOST_CHECK(!DestroyBlockFilterIndex(BlockFilterType::BASIC));
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+
+ // Reinitialize index.
+ BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ DestroyAllBlockFilterIndexes();
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
index cd0c36d802..df0a041e0e 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/blockfilters.json.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <blockfilter.h>
#include <core_io.h>
@@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(gcsfilter_default_constructor)
BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
{
- CScript included_scripts[5], excluded_scripts[3];
+ CScript included_scripts[5], excluded_scripts[4];
// First two are outputs on a single transaction.
included_scripts[0] << std::vector<unsigned char>(0, 65) << OP_CHECKSIG;
@@ -73,14 +73,19 @@ BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
// This script is not related to the block at all.
excluded_scripts[1] << std::vector<unsigned char>(5, 33) << OP_CHECKSIG;
+ // OP_RETURN is non-standard since it's not followed by a data push, but is still excluded from
+ // filter.
+ excluded_scripts[2] << OP_RETURN << OP_4 << OP_ADD << OP_8 << OP_EQUAL;
+
CMutableTransaction tx_1;
tx_1.vout.emplace_back(100, included_scripts[0]);
tx_1.vout.emplace_back(200, included_scripts[1]);
+ tx_1.vout.emplace_back(0, excluded_scripts[0]);
CMutableTransaction tx_2;
tx_2.vout.emplace_back(300, included_scripts[2]);
- tx_2.vout.emplace_back(0, excluded_scripts[0]);
- tx_2.vout.emplace_back(400, excluded_scripts[2]); // Script is empty
+ tx_2.vout.emplace_back(0, excluded_scripts[2]);
+ tx_2.vout.emplace_back(400, excluded_scripts[3]); // Script is empty
CBlock block;
block.vtx.push_back(MakeTransactionRef(tx_1));
@@ -90,7 +95,7 @@ BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
block_undo.vtxundo.emplace_back();
block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(500, included_scripts[3]), 1000, true);
block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(600, included_scripts[4]), 10000, false);
- block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(700, excluded_scripts[2]), 100000, false);
+ block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(700, excluded_scripts[3]), 100000, false);
BlockFilter block_filter(BlockFilterType::BASIC, block, block_undo);
const GCSFilter& filter = block_filter.GetFilter();
@@ -174,4 +179,16 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
}
}
+BOOST_AUTO_TEST_CASE(blockfilter_type_names)
+{
+ BOOST_CHECK_EQUAL(BlockFilterTypeName(BlockFilterType::BASIC), "basic");
+ BOOST_CHECK_EQUAL(BlockFilterTypeName(static_cast<BlockFilterType>(255)), "");
+
+ BlockFilterType filter_type;
+ BOOST_CHECK(BlockFilterTypeByName("basic", filter_type));
+ BOOST_CHECK_EQUAL(filter_type, BlockFilterType::BASIC);
+
+ BOOST_CHECK(!BlockFilterTypeByName("unknown", filter_type));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index f58dd20efc..4421494007 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,7 +15,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
index 8572926193..8fd4e5d5d6 100644
--- a/src/test/bswap_tests.cpp
+++ b/src/test/bswap_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compat/byteswap.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 3469c6dfba..408a7fbda4 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <util/time.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <checkqueue.h>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
@@ -167,7 +167,6 @@ static void Correct_Queue_range(std::vector<size_t> range)
BOOST_REQUIRE(control.Wait());
if (FakeCheckCheckCompletion::n_calls != i) {
BOOST_REQUIRE_EQUAL(FakeCheckCheckCompletion::n_calls, i);
- BOOST_TEST_MESSAGE("Failure on trial " << i << " expected, got " << FakeCheckCheckCompletion::n_calls);
}
}
tg.interrupt_all();
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index f6b97a6868..232c077c68 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <coins.h>
#include <consensus/validation.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <uint256.h>
#include <undo.h>
#include <util/strencodings.h>
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index e686c05165..6cef8cd8a8 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compressor.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 2cc38a0679..8a219a8284 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,7 +13,7 @@
#include <crypto/hmac_sha512.h>
#include <random.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index d8286520ec..d38ede691a 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <boost/test/unit_test.hpp>
#include <cuckoocache.h>
#include <script/sigcache.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <random.h>
#include <thread>
diff --git a/src/test/data/blockfilters.json b/src/test/data/blockfilters.json
index 134b788eed..8945296a07 100644
--- a/src/test/data/blockfilters.json
+++ b/src/test/data/blockfilters.json
@@ -3,9 +3,11 @@
[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",[],"0000000000000000000000000000000000000000000000000000000000000000","019dfca8","21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750","Genesis block"],
[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000",[],"d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1","0174a170","186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0",""],
[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000",[],"186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0","016cf7a0","8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a",""],
+[15007,"0000000038c44c703bae0f98cdd6bf30922326340a5996cc692aaae8bacf47ad","0100000002394092aa378fe35d7e9ac79c869b975c4de4374cd75eb5484b0e1e00000000eb9b8670abd44ad6c55cee18e3020fb0c6519e7004b01a16e9164867531b67afc33bc94fffff001d123f10050101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e04c33bc94f0115062f503253482fffffffff0100f2052a01000000232103f268e9ae07e0f8cb2f6e901d87c510d650b97230c0365b021df8f467363cafb1ac00000000",[],"18b5c2b0146d2d09d24fb00ff5b52bd0742f36c9e65527abdb9de30c027a4748","013c3710","07384b01311867949e0c046607c66b7a766d338474bb67f66c8ae9dbd454b20e","Tx has non-standard OP_RETURN output followed by opcodes"],
[49291,"0000000018b07dca1b28b4b5a119f6d6e71698ce1ed96f143f54179ce177a19c","02000000abfaf47274223ca2fea22797e44498240e482cb4c2f2baea088962f800000000604b5b52c32305b15d7542071d8b04e750a547500005d4010727694b6e72a776e55d0d51ffff001d211806480201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038bc0000102062f503253482fffffffff01a078072a01000000232102971dd6034ed0cf52450b608d196c07d6345184fcb14deb277a6b82d526a6163dac0000000001000000081cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff000000009300493046022100866859c21f306538152e83f115bcfbf59ab4bb34887a88c03483a5dff9895f96022100a6dfd83caa609bf0516debc2bf65c3df91813a4842650a1858b3f61cfa8af249014730440220296d4b818bb037d0f83f9f7111665f49532dfdcbec1e6b784526e9ac4046eaa602204acf3a5cb2695e8404d80bf49ab04828bcbe6fc31d25a2844ced7a8d24afbdff01ffffffff1cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff020000009400483045022100e87899175991aa008176cb553c6f2badbb5b741f328c9845fcab89f8b18cae2302200acce689896dc82933015e7230e5230d5cff8a1ffe82d334d60162ac2c5b0c9601493046022100994ad29d1e7b03e41731a4316e5f4992f0d9b6e2efc40a1ccd2c949b461175c502210099b69fdc2db00fbba214f16e286f6a49e2d8a0d5ffc6409d87796add475478d601ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272010000009500493046022100a27400ba52fd842ce07398a1de102f710a10c5599545e6c95798934352c2e4df022100f6383b0b14c9f64b6718139f55b6b9494374755b86bae7d63f5d3e583b57255a01493046022100fdf543292f34e1eeb1703b264965339ec4a450ec47585009c606b3edbc5b617b022100a5fbb1c8de8aaaa582988cdb23622838e38de90bebcaab3928d949aa502a65d401ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272020000009400493046022100ac626ac3051f875145b4fe4cfe089ea895aac73f65ab837b1ac30f5d875874fa022100bc03e79fa4b7eb707fb735b95ff6613ca33adeaf3a0607cdcead4cfd3b51729801483045022100b720b04a5c5e2f61b7df0fcf334ab6fea167b7aaede5695d3f7c6973496adbf1022043328c4cc1cdc3e5db7bb895ccc37133e960b2fd3ece98350f774596badb387201ffffffff23a8733e349c97d6cd90f520fdd084ba15ce0a395aad03cd51370602bb9e5db3010000004a00483045022100e8556b72c5e9c0da7371913a45861a61c5df434dfd962de7b23848e1a28c86ca02205d41ceda00136267281be0974be132ac4cda1459fe2090ce455619d8b91045e901ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a6000000006a473044022040a1c631554b8b210fbdf2a73f191b2851afb51d5171fb53502a3a040a38d2c0022040d11cf6e7b41fe1b66c3d08f6ada1aee07a047cb77f242b8ecc63812c832c9a012102bcfad931b502761e452962a5976c79158a0f6d307ad31b739611dac6a297c256ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a601000000930048304502205b109df098f7e932fbf71a45869c3f80323974a826ee2770789eae178a21bfc8022100c0e75615e53ee4b6e32b9bb5faa36ac539e9c05fa2ae6b6de5d09c08455c8b9601483045022009fb7d27375c47bea23b24818634df6a54ecf72d52e0c1268fb2a2c84f1885de022100e0ed4f15d62e7f537da0d0f1863498f9c7c0c0a4e00e4679588c8d1a9eb20bb801ffffffffa563c3722b7b39481836d5edfc1461f97335d5d1e9a23ade13680d0e2c1c371f030000006c493046022100ecc38ae2b1565643dc3c0dad5e961a5f0ea09cab28d024f92fa05c922924157e022100ebc166edf6fbe4004c72bfe8cf40130263f98ddff728c8e67b113dbd621906a601210211a4ed241174708c07206601b44a4c1c29e5ad8b1f731c50ca7e1d4b2a06dc1fffffffff02d0223a00000000001976a91445db0b779c0b9fa207f12a8218c94fc77aff504588ac80f0fa02000000000000000000",["5221033423007d8f263819a2e42becaaf5b06f34cb09919e06304349d950668209eaed21021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","522102a7ae1e0971fc1689bd66d2a7296da3a1662fd21a53c9e38979e0f090a375c12d21022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","512103b9d1d0e2b4355ec3cdef7c11a5c0beff9e8b8d8372ab4b4e0aaf30e80173001951ae","76a9149144761ebaccd5b4bbdc2a35453585b5637b2f8588ac","522103f1848b40621c5d48471d9784c8174ca060555891ace6d2b03c58eece946b1a9121020ee5d32b54d429c152fdc7b1db84f2074b0564d35400d89d11870f9273ec140c52ae","76a914f4fa1cc7de742d135ea82c17adf0bb9cf5f4fb8388ac"],"ed47705334f4643892ca46396eb3f4196a5e30880589e4009ef38eae895d4a13","0afbc2920af1b027f31f87b592276eb4c32094bb4d3697021b4c6380","b6d98692cec5145f67585f3434ec3c2b3030182e1cb3ec58b855c5c164dfaaa3","Tx pays to empty output script"],
-[180480,"00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a","020000006058aa080a655aa991a444bd7d1f2defd9a3bbe68aabb69030cf3b4e00000000d2e826bfd7ef0beaa891a7eedbc92cd6a544a6cb61c7bdaa436762eb2123ef9790f5f552ffff001d0002c90f0501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0300c102024608062f503253482fffffffff01c0c6072a01000000232102e769e60137a4df6b0df8ebd387cca44c4c57ae74cc0114a8e8317c8f3bfd85e9ac00000000010000000381a0802911a01ffb025c4dea0bc77963e8c1bb46313b71164c53f72f37fe5248010000000151ffffffffc904b267833d215e2128bd9575242232ac2bc311550c7fc1f0ef6f264b40d14c010000000151ffffffffdf0915666649dba81886519c531649b7b02180b4af67d6885e871299e9d5f775000000000151ffffffff0180817dcb00000000232103bb52138972c48a132fc1f637858c5189607dd0f7fe40c4f20f6ad65f2d389ba4ac0000000001000000018da38b434fba82d66052af74fc5e4e94301b114d9bc03f819dc876398404c8b4010000006c493046022100fe738b7580dc5fb5168e51fc61b5aed211125eb71068031009a22d9bbad752c5022100be5086baa384d40bcab0fa586e4f728397388d86e18b66cc417dc4f7fa4f9878012103f233299455134caa2687bdf15cb0becdfb03bd0ff2ff38e65ec6b7834295c34fffffffff022ebc1400000000001976a9147779b7fba1c1e06b717069b80ca170e8b04458a488ac9879c40f000000001976a9142a0307cd925dbb66b534c4db33003dd18c57015788ac0000000001000000026139a62e3422a602de36c873a225c1d3ca5aeee598539ceecb9f0dc8d1ad0f83010000006b483045022100ad9f32b4a0a2ddc19b5a74eba78123e57616f1b3cfd72ce68c03ea35a3dda1f002200dbd22aa6da17213df5e70dfc3b2611d40f70c98ed9626aa5e2cde9d97461f0a012103ddb295d2f1e8319187738fb4b230fdd9aa29d0e01647f69f6d770b9ab24eea90ffffffff983c82c87cf020040d671956525014d5c2b28c6d948c85e1a522362c0059eeae010000006b4830450221009ca544274c786d30a5d5d25e17759201ea16d3aedddf0b9e9721246f7ef6b32e02202cfa5564b6e87dfd9fd98957820e4d4e6238baeb0f65fe305d91506bb13f5f4f012103c99113deac0d5d044e3ac0346abc02501542af8c8d3759f1382c72ff84e704f7ffffffff02c0c62d00000000001976a914ae19d27efe12f5a886dc79af37ad6805db6f922d88ac70ce2000000000001976a9143b8d051d37a07ea1042067e93efe63dbf73920b988ac000000000100000002be566e8cd9933f0c75c4a82c027f7d0c544d5c101d0607ef6ae5d07b98e7f1dc000000006b483045022036a8cdfd5ea7ebc06c2bfb6e4f942bbf9a1caeded41680d11a3a9f5d8284abad022100cacb92a5be3f39e8bc14db1710910ef7b395fa1e18f45d41c28d914fcdde33be012102bf59abf110b5131fae0a3ce1ec379329b4c896a6ae5d443edb68529cc2bc7816ffffffff96cf67645b76ceb23fe922874847456a15feee1655082ff32d25a6bf2c0dfc90000000006a47304402203471ca2001784a5ac0abab583581f2613523da47ec5f53df833c117b5abd81500220618a2847723d57324f2984678db556dbca1a72230fc7e39df04c2239942ba942012102925c9794fd7bb9f8b29e207d5fc491b1150135a21f505041858889fa4edf436fffffffff026c840f00000000001976a914797fb8777d7991d8284d88bfd421ce520f0f843188ac00ca9a3b000000001976a9146d10f3f592699265d10b106eda37c3ce793f7a8588ac00000000",["","","","76a9142903b138c24be9e070b3e73ec495d77a204615e788ac","76a91433a1941fd9a37b9821d376f5a51bd4b52fa50e2888ac","76a914e4374e8155d0865742ca12b8d4d14d41b57d682f88ac","76a914001fa7459a6cfc64bdc178ba7e7a21603bb2568f88ac","76a914f6039952bc2b307aeec5371bfb96b66078ec17f688ac"],"b109139671dbedc2b6fcd499a5480a7461ae458af8ff9411d819aa64ba6995d1","0db414c859a07e8205876354a210a75042d0463404913d61a8e068e58a3ae2aa080026","a0af77e0a7ed20ea78d2def3200cc24f08217dcd51755c7c7feb0e2ba8316c2d","Tx spends from empty output script"],
-[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"da49977ba1ee0d620a2c4f8f646b03cd0d230f5c6c994722e3ba884889f0be1a","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","4cd9dd007a325199102f1fc0b7d77ca25ee3c84d46018c4353ecfcb56c0d3e7a","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"],
-[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"e9d729b72d533c29abe5276d5cf6c152f3723f10efe000b1e0c9ca5265a8beb6","010c0b40","e6137ae5a8424c40da1e5023c16975cc97b09300b4c050e6b1c713add3836c40","Coinbase tx has unparseable output script"],
-[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"a4a4d6c6034da8aa06f01fe71f1fffbd79e032006b07f6c7a2c60a66aa310c01","0385acb4f0fe889ef0","3588f34fbbc11640f9ed40b2a66a4e096215d50389691309c1dac74d4268aa81","Includes witness data"]
+[180480,"00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a","020000006058aa080a655aa991a444bd7d1f2defd9a3bbe68aabb69030cf3b4e00000000d2e826bfd7ef0beaa891a7eedbc92cd6a544a6cb61c7bdaa436762eb2123ef9790f5f552ffff001d0002c90f0501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0300c102024608062f503253482fffffffff01c0c6072a01000000232102e769e60137a4df6b0df8ebd387cca44c4c57ae74cc0114a8e8317c8f3bfd85e9ac00000000010000000381a0802911a01ffb025c4dea0bc77963e8c1bb46313b71164c53f72f37fe5248010000000151ffffffffc904b267833d215e2128bd9575242232ac2bc311550c7fc1f0ef6f264b40d14c010000000151ffffffffdf0915666649dba81886519c531649b7b02180b4af67d6885e871299e9d5f775000000000151ffffffff0180817dcb00000000232103bb52138972c48a132fc1f637858c5189607dd0f7fe40c4f20f6ad65f2d389ba4ac0000000001000000018da38b434fba82d66052af74fc5e4e94301b114d9bc03f819dc876398404c8b4010000006c493046022100fe738b7580dc5fb5168e51fc61b5aed211125eb71068031009a22d9bbad752c5022100be5086baa384d40bcab0fa586e4f728397388d86e18b66cc417dc4f7fa4f9878012103f233299455134caa2687bdf15cb0becdfb03bd0ff2ff38e65ec6b7834295c34fffffffff022ebc1400000000001976a9147779b7fba1c1e06b717069b80ca170e8b04458a488ac9879c40f000000001976a9142a0307cd925dbb66b534c4db33003dd18c57015788ac0000000001000000026139a62e3422a602de36c873a225c1d3ca5aeee598539ceecb9f0dc8d1ad0f83010000006b483045022100ad9f32b4a0a2ddc19b5a74eba78123e57616f1b3cfd72ce68c03ea35a3dda1f002200dbd22aa6da17213df5e70dfc3b2611d40f70c98ed9626aa5e2cde9d97461f0a012103ddb295d2f1e8319187738fb4b230fdd9aa29d0e01647f69f6d770b9ab24eea90ffffffff983c82c87cf020040d671956525014d5c2b28c6d948c85e1a522362c0059eeae010000006b4830450221009ca544274c786d30a5d5d25e17759201ea16d3aedddf0b9e9721246f7ef6b32e02202cfa5564b6e87dfd9fd98957820e4d4e6238baeb0f65fe305d91506bb13f5f4f012103c99113deac0d5d044e3ac0346abc02501542af8c8d3759f1382c72ff84e704f7ffffffff02c0c62d00000000001976a914ae19d27efe12f5a886dc79af37ad6805db6f922d88ac70ce2000000000001976a9143b8d051d37a07ea1042067e93efe63dbf73920b988ac000000000100000002be566e8cd9933f0c75c4a82c027f7d0c544d5c101d0607ef6ae5d07b98e7f1dc000000006b483045022036a8cdfd5ea7ebc06c2bfb6e4f942bbf9a1caeded41680d11a3a9f5d8284abad022100cacb92a5be3f39e8bc14db1710910ef7b395fa1e18f45d41c28d914fcdde33be012102bf59abf110b5131fae0a3ce1ec379329b4c896a6ae5d443edb68529cc2bc7816ffffffff96cf67645b76ceb23fe922874847456a15feee1655082ff32d25a6bf2c0dfc90000000006a47304402203471ca2001784a5ac0abab583581f2613523da47ec5f53df833c117b5abd81500220618a2847723d57324f2984678db556dbca1a72230fc7e39df04c2239942ba942012102925c9794fd7bb9f8b29e207d5fc491b1150135a21f505041858889fa4edf436fffffffff026c840f00000000001976a914797fb8777d7991d8284d88bfd421ce520f0f843188ac00ca9a3b000000001976a9146d10f3f592699265d10b106eda37c3ce793f7a8588ac00000000",["","","","76a9142903b138c24be9e070b3e73ec495d77a204615e788ac","76a91433a1941fd9a37b9821d376f5a51bd4b52fa50e2888ac","76a914e4374e8155d0865742ca12b8d4d14d41b57d682f88ac","76a914001fa7459a6cfc64bdc178ba7e7a21603bb2568f88ac","76a914f6039952bc2b307aeec5371bfb96b66078ec17f688ac"],"d34ef98386f413769502808d4bac5f20f8dfd5bffc9eedafaa71de0eb1f01489","0db414c859a07e8205876354a210a75042d0463404913d61a8e068e58a3ae2aa080026","c582d51c0ca365e3fcf36c51cb646d7f83a67e867cb4743fd2128e3e022b700c","Tx spends from empty output script"],
+[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"8f13b9a9c85611635b47906c3053ac53cfcec7211455d4cb0d63dc9acc13d472","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","546c574a0472144bcaf9b6aeabf26372ad87c7af7d1ee0dbfae5e099abeae49c","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"],
+[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"fe4d230dbb0f4fec9bed23a5283e08baf996e3f32b93f52c7de1f641ddfd04ad","010c0b40","0965a544743bbfa36f254446e75630c09404b3d164a261892372977538928ed5","Coinbase tx has unparseable output script"],
+[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"31d66d516a9eda7de865df29f6ef6cb8e4bf9309e5dac899968a9a62a5df61e3","0385acb4f0fe889ef0","4e6d564c2a2452065c205dd7eb2791124e0c4e0dbb064c410c24968572589dec","Includes witness data"],
+[1414221,"0000000000000027b2b3b3381f114f674f481544ff2be37ae3788d7e078383b1","000000204ea88307a7959d8207968f152bedca5a93aefab253f1fb2cfb032a400000000070cebb14ec6dbc27a9dfd066d9849a4d3bac5f674665f73a5fe1de01a022a0c851fda85bf05f4c19a779d1450102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff18034d94154d696e6572476174653030310d000000f238f401ffffffff01c817a804000000000000000000",[],"5e5e12d90693c8e936f01847859404c67482439681928353ca1296982042864e","00","021e8882ef5a0ed932edeebbecfeda1d7ce528ec7b3daa27641acf1189d7b5dc","Empty data"]
]
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index 94e8c95345..0bde92c18d 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <dbwrapper.h>
#include <uint256.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index e5d62a3ab2..bcb9a7c181 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,7 +15,7 @@
#include <util/system.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 826615cb51..f5bda7d5e6 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <string>
#include <script/sign.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <script/descriptor.h>
#include <util/strencodings.h>
diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp
index 079a09f8f9..1db2f8054c 100644
--- a/src/test/flatfile_tests.cpp
+++ b/src/test/flatfile_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <flatfile.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
index 93aee10bb7..6bd6bb1be3 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <fs.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 859fba0bdc..97d7633715 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 8048238028..8a42344642 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/strencodings.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index e8e5040855..325b7002f2 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <crypto/siphash.h>
#include <hash.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index bf295042de..e924f27d1b 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <key_io.h>
#include <script/script.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp
index c564b4eab8..8b508ed7f7 100644
--- a/src/test/key_properties.cpp
+++ b/src/test/key_properties.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key.h>
@@ -8,7 +8,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index a768b4bcbd..e816546e62 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <uint256.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
index 0788f75b04..00b36f51fb 100644
--- a/src/test/limitedmap_tests.cpp
+++ b/src/test/limitedmap_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <limitedmap.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 23ca9d89ae..0f74b379c0 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <txmempool.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <list>
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 4cdf0f003e..1684258c9f 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/merkle.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp
index 4978593285..eac43471c7 100644
--- a/src/test/merkleblock_tests.cpp
+++ b/src/test/merkleblock_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <merkleblock.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 5ba1df2ec2..6ed4359059 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,7 +18,7 @@
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 8afe4b8a59..682f1bee26 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <script/sign.h>
#include <script/ismine.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index b4ae8e9765..54d18c0a1c 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrman.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <boost/test/unit_test.hpp>
#include <hash.h>
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 0d557cff13..dd5e3eb6d5 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <netbase.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/strencodings.h>
#include <string>
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 5020192804..c5513ae9fa 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <uint256.h>
#include <arith_uint256.h>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 7b274a1658..149094fc00 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <uint256.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 26cdc9bc5c..653433bfce 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <pow.h>
#include <random.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 7341389208..141be50f50 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <serialize.h>
#include <streams.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp
index bdb411d53f..2b01acf7fa 100644
--- a/src/test/raii_event_tests.cpp
+++ b/src/test/raii_event_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <support/events.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index 8194070aba..e6fbe2355d 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index 91c76fda88..69db9dcf4e 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <reverselock.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 9bb2bf551b..07d1326bcb 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <key_io.h>
#include <netbase.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.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 8085a21928..891aa8e5c3 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compat/sanity.h>
#include <key.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index 100d65b779..42242b962b 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <random.h>
#include <scheduler.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index 400c89726f..0ce5f09e42 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,7 +13,7 @@
#include <policy/settings.h>
#include <script/sign.h>
#include <script/ismine.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index bde82018c7..36a2b1bee5 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <script/script.h>
#include <script/script_error.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index b964c6e479..588ae55a69 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <script/sign.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <rpc/util.h>
#if defined(HAVE_CONSENSUS_LIB)
diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp
index f9b407ce3e..e7916f5000 100644
--- a/src/test/scriptnum_tests.cpp
+++ b/src/test/scriptnum_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/scriptnum10.h>
#include <script/script.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.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 002f61f6a2..2fab309aa4 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <serialize.h>
#include <streams.h>
#include <hash.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
diff --git a/src/test/test_bitcoin.cpp b/src/test/setup_common.cpp
index b72f156646..29633cc7bf 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/setup_common.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <banman.h>
#include <chainparams.h>
@@ -33,7 +33,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
}
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
- : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
+ : m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
{
SHA256AutoDetect();
ECC_Start();
@@ -42,11 +42,12 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
InitSignatureCache();
InitScriptExecutionCache();
fCheckBlockIndex = true;
- // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
- // TODO: fix the code to support SegWit blocks.
- gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
SelectParams(chainName);
- noui_connect();
+ static bool noui_connected = false;
+ if (!noui_connected) {
+ noui_connect();
+ noui_connected = true;
+ }
}
BasicTestingSetup::~BasicTestingSetup()
@@ -115,6 +116,11 @@ TestingSetup::~TestingSetup()
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
+ // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
+ // TODO: fix the code to support SegWit blocks.
+ gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
+ SelectParams(CBaseChainParams::REGTEST);
+
// Generate a 100-block chain:
coinbaseKey.MakeNewKey(true);
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
diff --git a/src/test/test_bitcoin.h b/src/test/setup_common.h
index 38c6d85a8d..893eca216d 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/setup_common.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_TEST_TEST_BITCOIN_H
-#define BITCOIN_TEST_TEST_BITCOIN_H
+#ifndef BITCOIN_TEST_SETUP_COMMON_H
+#define BITCOIN_TEST_SETUP_COMMON_H
#include <chainparamsbase.h>
#include <fs.h>
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 07f4337221..15f8db899b 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <script/script.h>
#include <serialize.h>
#include <streams.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <version.h>
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 6a0349cd4e..4efa023fbb 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <script/script.h>
#include <script/standard.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 5c46976ace..3d39dfdb75 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
// Pick a random element in vBlocksMain.
int r = InsecureRandRange(vBlocksMain.size());
int64_t test_time = vBlocksMain[r].nTime;
- CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
+ CBlockIndex* ret = chain.FindEarliestAtLeast(test_time, 0);
BOOST_CHECK(ret->nTimeMax >= test_time);
BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time);
BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
@@ -158,22 +158,34 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
CChain chain;
chain.SetTip(&blocks.back());
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6);
- BOOST_CHECK(!chain.FindEarliestAtLeast(350));
-
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
-
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
- BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
- BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
- BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1));
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150, 0)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200, 0)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250, 0)->nHeight, 6);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300, 0)->nHeight, 6);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(350, 0));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1, 0)->nHeight, 0);
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min(), 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1, 0)->nHeight, 0);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max(), 0));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max(), 0));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1, 0));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, -1)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 3)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 8)->nHeight, 8);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(0, 9));
+
+ CBlockIndex* ret1 = chain.FindEarliestAtLeast(100, 2);
+ BOOST_CHECK(ret1->nTimeMax >= 100 && ret1->nHeight == 2);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(300, 9));
+ CBlockIndex* ret2 = chain.FindEarliestAtLeast(200, 4);
+ BOOST_CHECK(ret2->nTimeMax >= 200 && ret2->nHeight == 4);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index a1940eb80e..4e37199c63 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <streams.h>
#include <support/allocators/zeroafterfree.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp
index df0380546e..c1399d2dbe 100644
--- a/src/test/sync_tests.cpp
+++ b/src/test/sync_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <sync.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
index 474a67497f..b4c0e6a0f4 100644
--- a/src/test/timedata_tests.cpp
+++ b/src/test/timedata_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <timedata.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp
index c7ceb2f1e9..6d8459f5b1 100644
--- a/src/test/torcontrol_tests.cpp
+++ b/src/test/torcontrol_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <torcontrol.h>
#include <boost/test/unit_test.hpp>
@@ -20,7 +20,6 @@ BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
{
- BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")");
auto ret = SplitTorReplyLine(input);
BOOST_CHECK_EQUAL(ret.first, command);
BOOST_CHECK_EQUAL(ret.second, args);
@@ -61,7 +60,6 @@ BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
{
- BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")");
auto ret = ParseTorReplyMapping(input);
BOOST_CHECK_EQUAL(ret.size(), expected.size());
auto r_it = ret.begin();
@@ -173,7 +171,6 @@ BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
// Special handling for null case
// (needed because string comparison reads the null as end-of-string)
- BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")"));
auto ret = ParseTorReplyMapping("Null=\"\\0\"");
BOOST_CHECK_EQUAL(ret.size(), 1U);
auto r_it = ret.begin();
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index ed77b7f52b..6242fdabd1 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/tx_invalid.json.h>
#include <test/data/tx_valid.json.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <clientversion.h>
#include <checkqueue.h>
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index d667c26c3c..9d62b471c1 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
#include <index/txindex.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/system.h>
#include <util/time.h>
#include <validation.h>
diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
index c2777cd6d1..331c340b74 100644
--- a/src/test/txvalidation_tests.cpp
+++ b/src/test/txvalidation_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <consensus/validation.h>
#include <primitives/transaction.h>
#include <script/script.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 4d04aae7e9..01018043b1 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <random.h>
#include <script/standard.h>
#include <script/sign.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/time.h>
#include <core_io.h>
#include <keystore.h>
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index cca5e20296..c1749fb856 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <arith_uint256.h>
#include <uint256.h>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <stdint.h>
diff --git a/src/test/util.cpp b/src/test/util.cpp
new file mode 100644
index 0000000000..05d3a97a59
--- /dev/null
+++ b/src/test/util.cpp
@@ -0,0 +1,91 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/util.h>
+
+#include <chainparams.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <key_io.h>
+#include <miner.h>
+#include <outputtype.h>
+#include <pow.h>
+#include <scheduler.h>
+#include <script/standard.h>
+#include <txdb.h>
+#include <validation.h>
+#include <validationinterface.h>
+#ifdef ENABLE_WALLET
+#include <wallet/wallet.h>
+#endif
+
+#include <boost/thread.hpp>
+
+const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj";
+
+#ifdef ENABLE_WALLET
+std::string getnewaddress(CWallet& w)
+{
+ constexpr auto output_type = OutputType::BECH32;
+
+ CPubKey new_key;
+ if (!w.GetKeyFromPool(new_key)) assert(false);
+
+ w.LearnRelatedScripts(new_key, output_type);
+ const auto dest = GetDestinationForKey(new_key, output_type);
+
+ w.SetAddressBook(dest, /* label */ "", "receive");
+
+ return EncodeDestination(dest);
+}
+
+void importaddress(CWallet& wallet, const std::string& address)
+{
+ LOCK(wallet.cs_wallet);
+ const auto dest = DecodeDestination(address);
+ assert(IsValidDestination(dest));
+ const auto script = GetScriptForDestination(dest);
+ wallet.MarkDirty();
+ assert(!wallet.HaveWatchOnly(script));
+ if (!wallet.AddWatchOnly(script, 0 /* nCreateTime */)) assert(false);
+ wallet.SetAddressBook(dest, /* label */ "", "receive");
+}
+#endif // ENABLE_WALLET
+
+CTxIn generatetoaddress(const std::string& address)
+{
+ const auto dest = DecodeDestination(address);
+ assert(IsValidDestination(dest));
+ const auto coinbase_script = GetScriptForDestination(dest);
+
+ return MineBlock(coinbase_script);
+}
+
+CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = PrepareBlock(coinbase_scriptPubKey);
+
+ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
+ ++block->nNonce;
+ assert(block->nNonce);
+ }
+
+ bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ assert(processed);
+
+ return CTxIn{block->vtx[0]->GetHash(), 0};
+}
+
+std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = std::make_shared<CBlock>(
+ BlockAssembler{Params()}
+ .CreateNewBlock(coinbase_scriptPubKey)
+ ->block);
+
+ block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
+ block->hashMerkleRoot = BlockMerkleRoot(*block);
+
+ return block;
+}
diff --git a/src/test/util.h b/src/test/util.h
new file mode 100644
index 0000000000..8ba647ec3f
--- /dev/null
+++ b/src/test/util.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_UTIL_H
+#define BITCOIN_TEST_UTIL_H
+
+#include <memory>
+#include <string>
+
+class CBlock;
+class CScript;
+class CTxIn;
+class CWallet;
+
+// Constants //
+
+extern const std::string ADDRESS_BCRT1_UNSPENDABLE;
+
+// Lower-level utils //
+
+/** Returns the generated coin */
+CTxIn MineBlock(const CScript& coinbase_scriptPubKey);
+/** Prepare a block to be mined */
+std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey);
+
+
+// RPC-like //
+
+/** Import the address to the wallet */
+void importaddress(CWallet& wallet, const std::string& address);
+/** Returns a new address from the wallet */
+std::string getnewaddress(CWallet& w);
+/** Returns the generated coin */
+CTxIn generatetoaddress(const std::string& address);
+
+
+#endif // BITCOIN_TEST_UTIL_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index e106bdeb65..6795308e83 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <sync.h>
#include <util/strencodings.h>
#include <util/moneystr.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
#include <vector>
@@ -36,8 +36,10 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
do {
TRY_LOCK(cs, lockTest);
- if (lockTest)
+ if (lockTest) {
+ BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
break;
+ }
BOOST_ERROR("break was swallowed!");
} while(0);
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 44432cd0a1..4d54aa9b2c 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <miner.h>
#include <pow.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <validationinterface.h>
diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp
index 8d06ecd3a9..101025d31e 100644
--- a/src/test/validation_tests.cpp
+++ b/src/test/validation_tests.cpp
@@ -6,7 +6,7 @@
#include <net.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/signals2/signal.hpp>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index ca3196454a..38d91b6647 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <versionbits.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <chainparams.h>
#include <validation.h>
#include <consensus/params.h>
diff --git a/src/txdb.h b/src/txdb.h
index d5a4bfaeb1..c4ece11503 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -37,6 +37,8 @@ static const int64_t nMaxBlockDBCache = 2;
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
static const int64_t nMaxTxIndexCache = 1024;
+//! Max memory allocated to all block filter index caches combined in MiB.
+static const int64_t max_filter_index_cache = 1024;
//! Max memory allocated to coin DB specific cache (MiB)
static const int64_t nMaxCoinsDBCache = 8;
diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp
index c084c4e0e2..31a95486d7 100644
--- a/src/ui_interface.cpp
+++ b/src/ui_interface.cpp
@@ -28,10 +28,6 @@ struct UISignals {
boost::signals2::connection CClientUIInterface::signal_name##_connect(std::function<signal_name##Sig> fn) \
{ \
return g_ui_signals.signal_name.connect(fn); \
- } \
- void CClientUIInterface::signal_name##_disconnect(std::function<signal_name##Sig> fn) \
- { \
- return g_ui_signals.signal_name.disconnect(&fn); \
}
ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeMessageBox);
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 60d85bc142..d408f6f889 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -81,8 +81,7 @@ public:
#define ADD_SIGNALS_DECL_WRAPPER(signal_name, rtype, ...) \
rtype signal_name(__VA_ARGS__); \
using signal_name##Sig = rtype(__VA_ARGS__); \
- boost::signals2::connection signal_name##_connect(std::function<signal_name##Sig> fn); \
- void signal_name##_disconnect(std::function<signal_name##Sig> fn);
+ boost::signals2::connection signal_name##_connect(std::function<signal_name##Sig> fn);
/** Show message box. */
ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, bool, const std::string& message, const std::string& caption, unsigned int style);
diff --git a/src/validation.cpp b/src/validation.cpp
index b8f3ee464e..c0b3243c8d 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -8,7 +8,6 @@
#include <arith_uint256.h>
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <checkqueue.h>
#include <consensus/consensus.h>
#include <consensus/merkle.h>
@@ -37,6 +36,7 @@
#include <txdb.h>
#include <txmempool.h>
#include <ui_interface.h>
+#include <uint256.h>
#include <undo.h>
#include <util/moneystr.h>
#include <util/rbf.h>
@@ -561,6 +561,13 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, txdata);
}
+/**
+ * @param[out] coins_to_uncache Return any outpoints which were not previously present in the
+ * coins cache, but were added as a result of validating the tx
+ * for mempool acceptance. This allows the caller to optionally
+ * remove the cache additions if the associated transaction ends
+ * up being rejected by the mempool.
+ */
static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -656,6 +663,10 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
+
+ // Note: this call may add txin.prevout to the coins cache
+ // (pcoinsTip.cacheCoins) by way of FetchCoin(). It should be removed
+ // later (via coins_to_uncache) if this tx turns out to be invalid.
if (!view.HaveCoin(txin.prevout)) {
// Are inputs missing because we already have the tx?
for (size_t out = 0; out < tx.vout.size(); out++) {
@@ -977,6 +988,11 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
std::vector<COutPoint> coins_to_uncache;
bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, pfMissingInputs, nAcceptTime, plTxnReplaced, bypass_limits, nAbsurdFee, coins_to_uncache, test_accept);
if (!res) {
+ // Remove coins that were not present in the coins cache before calling ATMPW;
+ // this is to prevent memory DoS in case we receive a large number of
+ // invalid transactions that attempt to overrun the in-memory coins cache
+ // (`CCoinsViewCache::cacheCoins`).
+
for (const COutPoint& hashTx : coins_to_uncache)
pcoinsTip->Uncache(hashTx);
}
@@ -3187,6 +3203,22 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
return commitment;
}
+//! Returns last CBlockIndex* that is a checkpoint
+static CBlockIndex* GetLastCheckpoint(const CCheckpointData& data)
+{
+ const MapCheckpoints& checkpoints = data.mapCheckpoints;
+
+ for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
+ {
+ const uint256& hash = i.second;
+ CBlockIndex* pindex = LookupBlockIndex(hash);
+ if (pindex) {
+ return pindex;
+ }
+ }
+ return nullptr;
+}
+
/** 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().
@@ -3211,7 +3243,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
// Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
// MapBlockIndex.
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(params.Checkpoints());
+ CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
}
diff --git a/src/validation.h b/src/validation.h
index fecff5bb80..ef8fff19ac 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -110,6 +110,7 @@ static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
+static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
/** Default for -persistmempool */
static const bool DEFAULT_PERSIST_MEMPOOL = true;
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 78f3026a80..ea1b2e7e76 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -18,7 +18,6 @@ class CBlockIndex;
struct CBlockLocator;
class CBlockIndex;
class CConnman;
-class CReserveScript;
class CValidationInterface;
class CValidationState;
class uint256;
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index 48a924abfb..9257b272bc 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -36,6 +36,8 @@ public:
bool m_avoid_partial_spends;
//! Fee estimation mode to control arguments to estimateSmartFee
FeeEstimateMode m_fee_mode;
+ //! Minimum chain depth value for coin availability
+ int m_min_depth{0};
CCoinControl()
{
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 7ffea3867d..78db4df5e5 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -75,9 +75,11 @@ bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
return res == feebumper::Result::OK;
}
-Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
- CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
+Result CreateTotalBumpTransaction(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)
{
+ new_fee = total_fee;
+
auto locked_chain = wallet->chain().lock();
LOCK(wallet->cs_wallet);
errors.clear();
@@ -121,7 +123,6 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// calculate the old fee and fee-rate
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
// fee that our node may not be aware of.
@@ -131,34 +132,17 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
walletIncrementalRelayFee = nodeIncrementalRelayFee;
}
- if (total_fee > 0) {
- CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize);
- 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(nodeIncrementalRelayFee.GetFee(maxNewTxSize))));
- return Result::INVALID_PARAMETER;
- }
- CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
- if (total_fee < requiredFee) {
- errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
- FormatMoney(requiredFee)));
- return Result::INVALID_PARAMETER;
- }
- new_fee = total_fee;
- nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
- } else {
- new_fee = GetMinimumFee(*wallet, maxNewTxSize, coin_control, 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
- // in that unit (fee per kb).
- // However, nOldFeeRate is a calculated value from the tx fee/size, so
- // 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());
- new_fee = nNewFeeRate.GetFee(maxNewTxSize);
- }
+ CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize);
+ 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(nodeIncrementalRelayFee.GetFee(maxNewTxSize))));
+ return Result::INVALID_PARAMETER;
+ }
+ CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
+ if (total_fee < requiredFee) {
+ errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
+ FormatMoney(requiredFee)));
+ return Result::INVALID_PARAMETER;
}
// Check that in all cases the new fee doesn't violate maxTxFee
@@ -175,14 +159,14 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// 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 total_fee to make an adjustment.
CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
+ CFeeRate nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
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",
+ "the totalFee value should be at least %s to add transaction",
FormatMoney(nNewFeeRate.GetFeePerK()),
FormatMoney(minMempoolFeeRate.GetFeePerK()),
- FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)),
- FormatMoney(minMempoolFeeRate.GetFeePerK())));
+ FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize))));
return Result::WALLET_ERROR;
}
@@ -212,6 +196,109 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
}
}
+ return Result::OK;
+}
+
+
+Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors,
+ CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
+{
+ // We are going to modify coin control later, copy to re-use
+ CCoinControl new_coin_control(coin_control);
+
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
+ 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;
+
+ Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors);
+ if (result != Result::OK) {
+ return result;
+ }
+
+ // Fill in recipients(and preserve a single change key if there is one)
+ std::vector<CRecipient> recipients;
+ for (const auto& output : wtx.tx->vout) {
+ if (!wallet->IsChange(output)) {
+ CRecipient recipient = {output.scriptPubKey, output.nValue, false};
+ recipients.push_back(recipient);
+ } else {
+ CTxDestination change_dest;
+ ExtractDestination(output.scriptPubKey, change_dest);
+ new_coin_control.destChange = change_dest;
+ }
+ }
+
+ // Get the fee rate of the original transaction. This is calculated from
+ // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
+ // result.
+ old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
+ int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
+ // Feerate of thing we are bumping
+ CFeeRate feerate(old_fee, txSize);
+ feerate += CFeeRate(1);
+
+ // The node has a configurable incremental relay fee. Increment the fee by
+ // the minimum of that and the wallet's conservative
+ // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
+ // network wide policy for incremental relay fee that our node may not be
+ // aware of. This ensures we're over the over the required relay fee rate
+ // (BIP 125 rule 4). The replacement tx will be at least as large as the
+ // original tx, so the total fee will be greater (BIP 125 rule 3)
+ CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee();
+ CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
+ feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
+
+ // Fee rate must also be at least the wallet's GetMinimumFeeRate
+ CFeeRate min_feerate(GetMinimumFeeRate(*wallet, new_coin_control, /* feeCalc */ nullptr));
+
+ // Set the required fee rate for the replacement transaction in coin control.
+ new_coin_control.m_feerate = std::max(feerate, min_feerate);
+
+ // Fill in required inputs we are double-spending(all of them)
+ // N.B.: bip125 doesn't require all the inputs in the replaced transaction to be
+ // used in the replacement transaction, but it's very important for wallets to make
+ // sure that happens. If not, it would be possible to bump a transaction A twice to
+ // A2 and A3 where A2 and A3 don't conflict (or alternatively bump A to A2 and A2
+ // to A3 where A and A3 don't conflict). If both later get confirmed then the sender
+ // has accidentally double paid.
+ for (const auto& inputs : wtx.tx->vin) {
+ new_coin_control.Select(COutPoint(inputs.prevout));
+ }
+ new_coin_control.fAllowOtherInputs = true;
+
+ // We cannot source new unconfirmed inputs(bip125 rule 2)
+ new_coin_control.m_min_depth = 1;
+
+ CTransactionRef tx_new = MakeTransactionRef();
+ CReserveKey reservekey(wallet);
+ CAmount fee_ret;
+ int change_pos_in_out = -1; // No requested location for change
+ std::string fail_reason;
+ if (!wallet->CreateTransaction(*locked_chain, recipients, tx_new, reservekey, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
+ errors.push_back("Unable to create transaction: " + fail_reason);
+ return Result::WALLET_ERROR;
+ }
+
+ // If change key hasn't been ReturnKey'ed by this point, we take it out of keypool
+ reservekey.KeepKey();
+
+ // Write back new fee if successful
+ new_fee = fee_ret;
+
+ // Write back transaction
+ mtx = CMutableTransaction(*tx_new);
+ // Mark new tx not replaceable, if requested.
+ if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
+ for (auto& input : mtx.vin) {
+ if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
+ }
+ }
return Result::OK;
}
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index a1eb5d0e0d..f9cbfc5f68 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -28,8 +28,8 @@ enum class Result
//! Return whether transaction can be bumped.
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid);
-//! Create bumpfee transaction.
-Result CreateTransaction(const CWallet* wallet,
+//! Create bumpfee transaction based on total amount.
+Result CreateTotalBumpTransaction(const CWallet* wallet,
const uint256& txid,
const CCoinControl& coin_control,
CAmount total_fee,
@@ -38,6 +38,15 @@ Result CreateTransaction(const CWallet* wallet,
CAmount& new_fee,
CMutableTransaction& mtx);
+//! Create bumpfee transaction based on feerate estimates.
+Result CreateRateBumpTransaction(CWallet* wallet,
+ const uint256& txid,
+ const CCoinControl& coin_control,
+ 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)
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index cb6f7637ad..5a22508c4b 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3150,7 +3150,14 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
- return SignTransaction(pwallet->chain(), mtx, request.params[1], pwallet, false, request.params[2]);
+ // Fetch previous transactions (inputs):
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ pwallet->chain().findCoins(coins);
+
+ return SignTransaction(mtx, request.params[1], pwallet, coins, false, request.params[2]);
}
static UniValue bumpfee(const JSONRPCRequest& request)
@@ -3167,9 +3174,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
RPCHelpMan{"bumpfee",
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
"An opt-in RBF transaction with the given txid must be in the wallet.\n"
- "The command will pay the additional fee by decreasing (or perhaps removing) its change output.\n"
- "If the change output is not big enough to cover the increased fee, the command will currently fail\n"
- "instead of adding new inputs to compensate. (A future implementation could improve this.)\n"
+ "The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n"
+ "If `totalFee` is given, adding inputs is not supported, so there must be a single change output that is big enough or it will fail.\n"
+ "All inputs in the original transaction will be included in the replacement transaction.\n"
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
"By default, the new fee will be calculated automatically using estimatesmartfee.\n"
"The user can specify a confirmation target for estimatesmartfee.\n"
@@ -3266,7 +3273,14 @@ static UniValue bumpfee(const JSONRPCRequest& request)
CAmount old_fee;
CAmount new_fee;
CMutableTransaction mtx;
- feebumper::Result res = feebumper::CreateTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
+ feebumper::Result res;
+ if (totalFee > 0) {
+ // Targeting total fee bump. Requires a change output of sufficient size.
+ res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
+ } else {
+ // Targeting feerate bump.
+ res = feebumper::CreateRateBumpTransaction(pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
+ }
if (res != feebumper::Result::OK) {
switch(res) {
case feebumper::Result::INVALID_ADDRESS_OR_KEY:
@@ -3408,7 +3422,7 @@ class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
public:
CWallet * const pwallet;
- void ProcessSubScript(const CScript& subscript, UniValue& obj, bool include_addresses = false) const
+ void ProcessSubScript(const CScript& subscript, UniValue& obj) const
{
// Always present: script type and redeemscript
std::vector<std::vector<unsigned char>> solutions_data;
@@ -3417,7 +3431,6 @@ public:
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
CTxDestination embedded;
- UniValue a(UniValue::VARR);
if (ExtractDestination(subscript, embedded)) {
// Only when the script corresponds to an address.
UniValue subobj(UniValue::VOBJ);
@@ -3430,7 +3443,6 @@ public:
// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
obj.pushKV("embedded", std::move(subobj));
- if (include_addresses) a.push_back(EncodeDestination(embedded));
} else if (which_type == TX_MULTISIG) {
// Also report some information on multisig scripts (which do not have a corresponding address).
// TODO: abstract out the common functionality between this logic and ExtractDestinations.
@@ -3438,17 +3450,10 @@ public:
UniValue pubkeys(UniValue::VARR);
for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
- if (include_addresses) a.push_back(EncodeDestination(key.GetID()));
pubkeys.push_back(HexStr(key.begin(), key.end()));
}
obj.pushKV("pubkeys", std::move(pubkeys));
}
-
- // The "addresses" field is confusing because it refers to public keys using their P2PKH address.
- // For that reason, only add the 'addresses' field when needed for backward compatibility. New applications
- // can use the 'embedded'->'address' field for P2SH or P2WSH wrapped addresses, and 'pubkeys' for
- // inspecting multisig participants.
- if (include_addresses) obj.pushKV("addresses", std::move(a));
}
explicit DescribeWalletAddressVisitor(CWallet* _pwallet) : pwallet(_pwallet) {}
@@ -3471,7 +3476,7 @@ public:
UniValue obj(UniValue::VOBJ);
CScript subscript;
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
- ProcessSubScript(subscript, obj, pwallet->chain().rpcEnableDeprecated("validateaddress"));
+ ProcessSubScript(subscript, obj);
}
return obj;
}
@@ -3685,9 +3690,20 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
+ std::set<std::string> addresses;
for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
if (item.second.name == label) {
- ret.pushKV(EncodeDestination(item.first), AddressBookDataToJSON(item.second, false));
+ std::string address = EncodeDestination(item.first);
+ // CWallet::mapAddressBook is not expected to contain duplicate
+ // address strings, but build a separate set as a precaution just in
+ // case it does.
+ bool unique = addresses.emplace(address).second;
+ assert(unique);
+ // UniValue::pushKV checks if the key exists in O(N)
+ // and since duplicate addresses are unexpected (checked with
+ // std::set in O(log(N))), UniValue::__pushKV is used instead,
+ // which currently is O(1).
+ ret.__pushKV(address, AddressBookDataToJSON(item.second, false));
}
}
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 6c2003e274..34b9770e8b 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -8,7 +8,7 @@
#include <amount.h>
#include <primitives/transaction.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/test/wallet_test_fixture.h>
#include <boost/test/unit_test.hpp>
@@ -69,8 +69,7 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
std::unique_ptr<CWalletTx> wtx = MakeUnique<CWalletTx>(&testWallet, MakeTransactionRef(std::move(tx)));
if (fIsFromMe)
{
- wtx->fDebitCached = true;
- wtx->nDebitCached = 1;
+ wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1);
}
COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
vCoins.push_back(output);
@@ -115,7 +114,7 @@ inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& coins)
{
static std::vector<OutputGroup> static_groups;
static_groups.clear();
- for (auto& coin : coins) static_groups.emplace_back(coin.GetInputCoin(), coin.nDepth, coin.tx->fDebitCached && coin.tx->nDebitCached == 1 /* HACK: we can't figure out the is_me flag so we use the conditions defined above; perhaps set safe to false for !fIsFromMe in add_coin() */, 0, 0);
+ for (auto& coin : coins) static_groups.emplace_back(coin.GetInputCoin(), coin.nDepth, coin.tx->m_amounts[CWalletTx::DEBIT].m_cached[ISMINE_SPENDABLE] && coin.tx->m_amounts[CWalletTx::DEBIT].m_value[ISMINE_SPENDABLE] == 1 /* HACK: we can't figure out the is_me flag so we use the conditions defined above; perhaps set safe to false for !fIsFromMe in add_coin() */, 0, 0);
return static_groups;
}
@@ -135,7 +134,6 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
/////////////////////////
// Known Outcome tests //
/////////////////////////
- BOOST_TEST_MESSAGE("Testing known outcomes");
// Empty utxo pool
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 1 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index 2a64749379..d9b07af329 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -7,7 +7,7 @@
#include <boost/test/unit_test.hpp>
#include <fs.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/db.h>
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index cd47b31da1..0f2d9fbd3d 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -6,7 +6,7 @@
#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
#include <interfaces/chain.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
struct InitWalletDirTestingSetup: public BasicTestingSetup {
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
index 5852d3ef84..e1c53c83e2 100644
--- a/src/wallet/test/init_tests.cpp
+++ b/src/wallet/test/init_tests.cpp
@@ -4,7 +4,7 @@
#include <boost/test/unit_test.hpp>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/test/init_test_fixture.h>
#include <init.h>
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 789e86e21b..f774cb4ad1 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -12,7 +12,7 @@
#include <univalue.h>
#include <boost/test/unit_test.hpp>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/test/wallet_test_fixture.h>
BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup)
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index ae7092fa89..acc61c984f 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <util/strencodings.h>
#include <wallet/crypter.h>
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 7b82994539..6526e69eea 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -8,12 +8,13 @@
#include <wallet/db.h>
#include <wallet/rpcwallet.h>
-WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
- TestingSetup(chainName), m_wallet(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock())
+WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
+ : TestingSetup(chainName),
+ m_wallet(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- m_wallet.m_chain_notifications_handler = m_chain->handleNotifications(m_wallet);
+ m_wallet.handleNotifications();
m_chain_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index dcfbc55f94..1017e61700 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
#define BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <interfaces/chain.h>
#include <interfaces/wallet.h>
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 54e12f36ed..3cdbde33c3 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -13,7 +13,7 @@
#include <consensus/validation.h>
#include <interfaces/chain.h>
#include <rpc/server.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/test/wallet_test_fixture.h>
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8a1cb83e74..8bbb47c093 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1,13 +1,11 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/wallet.h>
-#include <checkpoints.h>
#include <chain.h>
-#include <wallet/coincontrol.h>
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <fs.h>
@@ -16,7 +14,6 @@
#include <key.h>
#include <key_io.h>
#include <keystore.h>
-#include <validation.h>
#include <net.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -34,6 +31,8 @@
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/validation.h>
+#include <validation.h>
+#include <wallet/coincontrol.h>
#include <wallet/fees.h>
#include <algorithm>
@@ -1729,7 +1728,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
uint256 start_block;
{
auto locked_chain = chain().lock();
- const Optional<int> start_height = locked_chain->findFirstBlockWithTime(startTime - TIMESTAMP_WINDOW, &start_block);
+ const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
const Optional<int> tip_height = locked_chain->getHeight();
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
}
@@ -1932,33 +1931,26 @@ std::set<uint256> CWalletTx::GetConflicts() const
return result;
}
+CAmount CWalletTx::GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate) const
+{
+ auto& amount = m_amounts[type];
+ if (recalculate || !amount.m_cached[filter]) {
+ amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) : pwallet->GetCredit(*tx, filter));
+ }
+ return amount.m_value[filter];
+}
+
CAmount CWalletTx::GetDebit(const isminefilter& filter) const
{
if (tx->vin.empty())
return 0;
CAmount debit = 0;
- if(filter & ISMINE_SPENDABLE)
- {
- if (fDebitCached)
- debit += nDebitCached;
- else
- {
- nDebitCached = pwallet->GetDebit(*tx, ISMINE_SPENDABLE);
- fDebitCached = true;
- debit += nDebitCached;
- }
+ if (filter & ISMINE_SPENDABLE) {
+ debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
}
- if(filter & ISMINE_WATCH_ONLY)
- {
- if(fWatchDebitCached)
- debit += nWatchDebitCached;
- else
- {
- nWatchDebitCached = pwallet->GetDebit(*tx, ISMINE_WATCH_ONLY);
- fWatchDebitCached = true;
- debit += nWatchDebitCached;
- }
+ if (filter & ISMINE_WATCH_ONLY) {
+ debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
}
return debit;
}
@@ -1970,28 +1962,12 @@ CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const ismine
return 0;
CAmount credit = 0;
- if (filter & ISMINE_SPENDABLE)
- {
+ if (filter & ISMINE_SPENDABLE) {
// GetBalance can assume transactions in mapWallet won't change
- if (fCreditCached)
- credit += nCreditCached;
- else
- {
- nCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE);
- fCreditCached = true;
- credit += nCreditCached;
- }
+ credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE);
}
- if (filter & ISMINE_WATCH_ONLY)
- {
- if (fWatchCreditCached)
- credit += nWatchCreditCached;
- else
- {
- nWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY);
- fWatchCreditCached = true;
- credit += nWatchCreditCached;
- }
+ if (filter & ISMINE_WATCH_ONLY) {
+ credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY);
}
return credit;
}
@@ -1999,11 +1975,7 @@ CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const ismine
CAmount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache) const
{
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
- if (fUseCache && fImmatureCreditCached)
- return nImmatureCreditCached;
- nImmatureCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE);
- fImmatureCreditCached = true;
- return nImmatureCreditCached;
+ return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
}
return 0;
@@ -2014,23 +1986,15 @@ CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, boo
if (pwallet == nullptr)
return 0;
+ // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
+ bool allow_cache = filter == ISMINE_SPENDABLE || filter == ISMINE_WATCH_ONLY;
+
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsImmatureCoinBase(locked_chain))
return 0;
- CAmount* cache = nullptr;
- bool* cache_used = nullptr;
-
- if (filter == ISMINE_SPENDABLE) {
- cache = &nAvailableCreditCached;
- cache_used = &fAvailableCreditCached;
- } else if (filter == ISMINE_WATCH_ONLY) {
- cache = &nAvailableWatchCreditCached;
- cache_used = &fAvailableWatchCreditCached;
- }
-
- if (fUseCache && cache_used && *cache_used) {
- return *cache;
+ if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
+ return m_amounts[AVAILABLE_CREDIT].m_value[filter];
}
CAmount nCredit = 0;
@@ -2046,22 +2010,17 @@ CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, boo
}
}
- if (cache) {
- *cache = nCredit;
- assert(cache_used);
- *cache_used = true;
+ if (allow_cache) {
+ m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
}
+
return nCredit;
}
CAmount CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache) const
{
if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
- if (fUseCache && fImmatureWatchCreditCached)
- return nImmatureWatchCreditCached;
- nImmatureWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY);
- fImmatureWatchCreditCached = true;
- return nImmatureWatchCreditCached;
+ return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
}
return 0;
@@ -2736,7 +2695,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
LOCK(cs_wallet);
{
std::vector<COutput> vAvailableCoins;
- AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control);
+ AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0, coin_control.m_min_depth);
CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
// Create change script that will be used if we need change
@@ -4281,7 +4240,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability)
if (walletInstance->nTimeFirstKey) {
- if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height)) {
+ if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
rescan_height = *first_block;
}
}
@@ -4326,7 +4285,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
chain.loadWallet(interfaces::MakeWallet(walletInstance));
// Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
- walletInstance->m_chain_notifications_handler = chain.handleNotifications(*walletInstance);
+ walletInstance->handleNotifications();
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
@@ -4339,6 +4298,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
return walletInstance;
}
+void CWallet::handleNotifications()
+{
+ m_chain_notifications_handler = m_chain->handleNotifications(*this);
+}
+
void CWallet::postInitProcess()
{
auto locked_chain = chain().lock();
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 008765bccc..900af75f4f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -11,16 +11,16 @@
#include <interfaces/handler.h>
#include <outputtype.h>
#include <policy/feerate.h>
+#include <script/ismine.h>
+#include <script/sign.h>
#include <streams.h>
#include <tinyformat.h>
#include <ui_interface.h>
#include <util/strencodings.h>
-#include <validationinterface.h>
-#include <script/ismine.h>
-#include <script/sign.h>
#include <util/system.h>
-#include <wallet/crypter.h>
+#include <validationinterface.h>
#include <wallet/coinselection.h>
+#include <wallet/crypter.h>
#include <wallet/walletdb.h>
#include <wallet/walletutil.h>
@@ -375,24 +375,11 @@ public:
std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
// memory only
- mutable bool fDebitCached;
- mutable bool fCreditCached;
- mutable bool fImmatureCreditCached;
- mutable bool fAvailableCreditCached;
- mutable bool fWatchDebitCached;
- mutable bool fWatchCreditCached;
- mutable bool fImmatureWatchCreditCached;
- mutable bool fAvailableWatchCreditCached;
+ enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
+ CAmount GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate = false) const;
+ mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
mutable bool fChangeCached;
mutable bool fInMempool;
- mutable CAmount nDebitCached;
- mutable CAmount nCreditCached;
- mutable CAmount nImmatureCreditCached;
- mutable CAmount nAvailableCreditCached;
- mutable CAmount nWatchDebitCached;
- mutable CAmount nWatchCreditCached;
- mutable CAmount nImmatureWatchCreditCached;
- mutable CAmount nAvailableWatchCreditCached;
mutable CAmount nChangeCached;
CWalletTx(const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))
@@ -409,24 +396,8 @@ public:
nTimeReceived = 0;
nTimeSmart = 0;
fFromMe = false;
- fDebitCached = false;
- fCreditCached = false;
- fImmatureCreditCached = false;
- fAvailableCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
fChangeCached = false;
fInMempool = false;
- nDebitCached = 0;
- nCreditCached = 0;
- nImmatureCreditCached = 0;
- nAvailableCreditCached = 0;
- nWatchDebitCached = 0;
- nWatchCreditCached = 0;
- nAvailableWatchCreditCached = 0;
- nImmatureWatchCreditCached = 0;
nChangeCached = 0;
nOrderPos = -1;
}
@@ -470,14 +441,10 @@ public:
//! make sure balances are recalculated
void MarkDirty()
{
- fCreditCached = false;
- fAvailableCreditCached = false;
- fImmatureCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fDebitCached = false;
+ m_amounts[DEBIT].Reset();
+ m_amounts[CREDIT].Reset();
+ m_amounts[IMMATURE_CREDIT].Reset();
+ m_amounts[AVAILABLE_CREDIT].Reset();
fChangeCached = false;
}
@@ -773,7 +740,10 @@ public:
unsigned int nMasterKeyMaxID = 0;
/** Construct wallet with specified name and database implementation. */
- CWallet(interfaces::Chain* chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database) : m_chain(chain), m_location(location), database(std::move(database))
+ CWallet(interfaces::Chain* chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database)
+ : m_chain(chain),
+ m_location(location),
+ database(std::move(database))
{
}
@@ -800,6 +770,9 @@ public:
/** Registered interfaces::Chain::Notifications handler. */
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
+ /** Register the wallet for chain notifications */
+ void handleNotifications();
+
/** Interface for accessing chain state. */
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
@@ -1216,8 +1189,6 @@ public:
/** Add a KeyOriginInfo to the wallet */
bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info);
-
- friend struct WalletTestingSetup;
};
/**
@@ -1227,7 +1198,7 @@ public:
void MaybeResendWalletTxs();
/** A key allocated from the key pool. */
-class CReserveKey final : public CReserveScript
+class CReserveKey
{
protected:
CWallet* pwallet;
@@ -1252,7 +1223,6 @@ public:
void ReturnKey();
bool GetReservedKey(CPubKey &pubkey, bool internal = false);
void KeepKey();
- void KeepScript() override { KeepKey(); }
};
/** RAII object to check and reserve a wallet rescan */