diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 4c097961a..3c319d6df 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -1,63 +1,56 @@
 // Copyright (c) 2011-2017 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <bench/bench.h>
 #include <config.h>
 #include <consensus/validation.h>
 #include <script/standard.h>
 #include <test/util/mining.h>
 #include <test/util/setup_common.h>
 #include <test/util/wallet.h>
 #include <txmempool.h>
 #include <validation.h>
 
 #include <vector>
 
 static void AssembleBlock(benchmark::Bench &bench) {
     const Config &config = GetConfig();
-    TestingSetup test_setup{
-        CBaseChainParams::REGTEST,
-        /* extra_args */
-        {
-            "-nodebuglogfile",
-            "-nodebug",
-        },
-    };
+    const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
 
     const CScript redeemScript = CScript() << OP_DROP << OP_TRUE;
     const CScript SCRIPT_PUB =
         CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript))
                   << OP_EQUAL;
 
     const CScript scriptSig = CScript() << std::vector<uint8_t>(100, 0xff)
                                         << ToByteVector(redeemScript);
 
     // Collect some loose transactions that spend the coinbases of our mined
     // blocks
     constexpr size_t NUM_BLOCKS{200};
     std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
     for (size_t b = 0; b < NUM_BLOCKS; ++b) {
         CMutableTransaction tx;
-        tx.vin.push_back(MineBlock(config, test_setup.m_node, SCRIPT_PUB));
+        tx.vin.push_back(MineBlock(config, test_setup->m_node, SCRIPT_PUB));
         tx.vin.back().scriptSig = scriptSig;
         tx.vout.emplace_back(1337 * SATOSHI, SCRIPT_PUB);
         if (NUM_BLOCKS - b >= COINBASE_MATURITY) {
             txs.at(b) = MakeTransactionRef(tx);
         }
     }
 
     {
         LOCK(::cs_main);
 
         for (const auto &txr : txs) {
             const MempoolAcceptResult res =
-                test_setup.m_node.chainman->ProcessTransaction(txr);
+                test_setup->m_node.chainman->ProcessTransaction(txr);
             assert(res.m_result_type == MempoolAcceptResult::ResultType::VALID);
         }
     }
 
-    bench.run([&] { PrepareBlock(config, test_setup.m_node, SCRIPT_PUB); });
+    bench.run([&] { PrepareBlock(config, test_setup->m_node, SCRIPT_PUB); });
 }
 
 BENCHMARK(AssembleBlock);
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index 74cab476b..2d88b359e 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -1,79 +1,73 @@
 // 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 <chain.h>
 #include <chainparams.h>
 #include <config.h>
 #include <consensus/amount.h>
 #include <consensus/merkle.h>
 #include <consensus/validation.h>
 #include <pow/pow.h>
 #include <random.h>
 #include <script/scriptcache.h>
 #include <test/util/setup_common.h>
 #include <txmempool.h>
 #include <validation.h>
 
 static void DuplicateInputs(benchmark::Bench &bench) {
-    TestingSetup test_setup{
-        CBaseChainParams::REGTEST,
-        /* extra_args */
-        {
-            "-nodebuglogfile",
-            "-nodebug",
-        },
-    };
+    const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
 
     const CScript SCRIPT_PUB{CScript(OP_TRUE)};
 
     const CChainParams &chainParams = Params();
     const Consensus::Params &consensusParams = chainParams.GetConsensus();
 
     CBlock block{};
     CMutableTransaction coinbaseTx{};
     CMutableTransaction naughtyTx{};
 
     LOCK(cs_main);
-    CBlockIndex *pindexPrev = test_setup.m_node.chainman->ActiveChain().Tip();
+    CBlockIndex *pindexPrev =
+        testing_setup->m_node.chainman->ActiveChain().Tip();
     assert(pindexPrev != nullptr);
     block.nBits = GetNextWorkRequired(pindexPrev, &block, chainParams);
     block.nNonce = 0;
     auto nHeight = pindexPrev->nHeight + 1;
 
     // Make a coinbase TX
     coinbaseTx.vin.resize(1);
     coinbaseTx.vin[0].prevout = COutPoint();
     coinbaseTx.vout.resize(1);
     coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB;
     coinbaseTx.vout[0].nValue = GetBlockSubsidy(nHeight, consensusParams);
     coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
 
     naughtyTx.vout.resize(1);
     naughtyTx.vout[0].nValue = Amount::zero();
     naughtyTx.vout[0].scriptPubKey = SCRIPT_PUB;
 
     uint64_t n_inputs =
         ((MAX_TX_SIZE - CTransaction(naughtyTx).GetTotalSize()) / 41) - 100;
     for (uint64_t x = 0; x < (n_inputs - 1); ++x) {
         naughtyTx.vin.emplace_back(TxId(GetRandHash()), 0, CScript(), 0);
     }
     naughtyTx.vin.emplace_back(naughtyTx.vin.back());
 
     block.vtx.push_back(MakeTransactionRef(std::move(coinbaseTx)));
     block.vtx.push_back(MakeTransactionRef(std::move(naughtyTx)));
 
     block.hashMerkleRoot = BlockMerkleRoot(block);
 
     bench.run([&] {
         BlockValidationState cvstate{};
         assert(!CheckBlock(block, cvstate, consensusParams,
                            BlockValidationOptions(GetConfig())
                                .withCheckPoW(false)
                                .withCheckMerkleRoot(false)));
         assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
     });
 }
 
 BENCHMARK(DuplicateInputs);
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 94fb28b0c..d5660aaf3 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -1,129 +1,122 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <bench/bench.h>
 #include <consensus/amount.h>
 #include <policy/policy.h>
 #include <test/util/setup_common.h>
 #include <txmempool.h>
 
 static void AddTx(const CTransactionRef &tx, const Amount &nFee,
                   CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) {
     int64_t nTime = 0;
     unsigned int nHeight = 1;
     bool spendsCoinbase = false;
     unsigned int nSigChecks = 1;
     LockPoints lp;
     pool.addUnchecked(CTxMemPoolEntryRef::make(tx, nFee, nTime, nHeight,
                                                spendsCoinbase, nSigChecks, lp));
 }
 
 // Right now this is only testing eviction performance in an extremely small
 // mempool. Code needs to be written to generate a much wider variety of
 // unique transactions for a more meaningful performance measurement.
 static void MempoolEviction(benchmark::Bench &bench) {
-    TestingSetup test_setup{
-        CBaseChainParams::REGTEST,
-        /* extra_args */
-        {
-            "-nodebuglogfile",
-            "-nodebug",
-        },
-    };
+    const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
 
     CMutableTransaction tx1 = CMutableTransaction();
     tx1.vin.resize(1);
     tx1.vin[0].scriptSig = CScript() << OP_1;
     tx1.vout.resize(1);
     tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
     tx1.vout[0].nValue = 10 * COIN;
 
     CMutableTransaction tx2 = CMutableTransaction();
     tx2.vin.resize(1);
     tx2.vin[0].scriptSig = CScript() << OP_2;
     tx2.vout.resize(1);
     tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
     tx2.vout[0].nValue = 10 * COIN;
 
     CMutableTransaction tx3 = CMutableTransaction();
     tx3.vin.resize(1);
     tx3.vin[0].prevout = COutPoint(tx2.GetId(), 0);
     tx3.vin[0].scriptSig = CScript() << OP_2;
     tx3.vout.resize(1);
     tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
     tx3.vout[0].nValue = 10 * COIN;
 
     CMutableTransaction tx4 = CMutableTransaction();
     tx4.vin.resize(2);
     tx4.vin[0].prevout = COutPoint();
     tx4.vin[0].scriptSig = CScript() << OP_4;
     tx4.vin[1].prevout = COutPoint();
     tx4.vin[1].scriptSig = CScript() << OP_4;
     tx4.vout.resize(2);
     tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
     tx4.vout[0].nValue = 10 * COIN;
     tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
     tx4.vout[1].nValue = 10 * COIN;
 
     CMutableTransaction tx5 = CMutableTransaction();
     tx5.vin.resize(2);
     tx5.vin[0].prevout = COutPoint(tx4.GetId(), 0);
     tx5.vin[0].scriptSig = CScript() << OP_4;
     tx5.vin[1].prevout = COutPoint();
     tx5.vin[1].scriptSig = CScript() << OP_5;
     tx5.vout.resize(2);
     tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
     tx5.vout[0].nValue = 10 * COIN;
     tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
     tx5.vout[1].nValue = 10 * COIN;
 
     CMutableTransaction tx6 = CMutableTransaction();
     tx6.vin.resize(2);
     tx6.vin[0].prevout = COutPoint(tx4.GetId(), 1);
     tx6.vin[0].scriptSig = CScript() << OP_4;
     tx6.vin[1].prevout = COutPoint();
     tx6.vin[1].scriptSig = CScript() << OP_6;
     tx6.vout.resize(2);
     tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
     tx6.vout[0].nValue = 10 * COIN;
     tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
     tx6.vout[1].nValue = 10 * COIN;
 
     CMutableTransaction tx7 = CMutableTransaction();
     tx7.vin.resize(2);
     tx7.vin[0].prevout = COutPoint(tx5.GetId(), 0);
     tx7.vin[0].scriptSig = CScript() << OP_5;
     tx7.vin[1].prevout = COutPoint(tx6.GetId(), 0);
     tx7.vin[1].scriptSig = CScript() << OP_6;
     tx7.vout.resize(2);
     tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
     tx7.vout[0].nValue = 10 * COIN;
     tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
     tx7.vout[1].nValue = 10 * COIN;
 
-    CTxMemPool &pool = *Assert(test_setup.m_node.mempool);
+    CTxMemPool &pool = *Assert(testing_setup->m_node.mempool);
     LOCK2(cs_main, pool.cs);
     // Create transaction references outside the "hot loop"
     const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
     const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
     const CTransactionRef tx3_r{MakeTransactionRef(tx3)};
     const CTransactionRef tx4_r{MakeTransactionRef(tx4)};
     const CTransactionRef tx5_r{MakeTransactionRef(tx5)};
     const CTransactionRef tx6_r{MakeTransactionRef(tx6)};
     const CTransactionRef tx7_r{MakeTransactionRef(tx7)};
 
     bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
         AddTx(tx1_r, 10000 * SATOSHI, pool);
         AddTx(tx2_r, 5000 * SATOSHI, pool);
         AddTx(tx3_r, 20000 * SATOSHI, pool);
         AddTx(tx4_r, 7000 * SATOSHI, pool);
         AddTx(tx5_r, 1000 * SATOSHI, pool);
         AddTx(tx6_r, 1100 * SATOSHI, pool);
         AddTx(tx7_r, 9000 * SATOSHI, pool);
         pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
         pool.TrimToSize(GetSerializeSize(*tx1_r, PROTOCOL_VERSION));
     });
 }
 
 BENCHMARK(MempoolEviction);
diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp
index aa300311c..1c5934cdc 100644
--- a/src/bench/mempool_stress.cpp
+++ b/src/bench/mempool_stress.cpp
@@ -1,131 +1,131 @@
 // 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 <policy/policy.h>
 #include <random.h>
 #include <test/util/setup_common.h>
 #include <txmempool.h>
 #include <validation.h>
 
 #include <vector>
 
 static void AddTx(const CTransactionRef &tx, CTxMemPool &pool)
     EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) {
     int64_t nTime = 0;
     unsigned int nHeight = 1;
     bool spendsCoinbase = false;
     unsigned int sigChecks = 1;
     LockPoints lp;
     pool.addUnchecked(CTxMemPoolEntryRef::make(
         tx, 1000 * SATOSHI, nTime, nHeight, spendsCoinbase, sigChecks, lp));
 }
 
 struct Available {
     CTransactionRef ref;
     size_t vin_left{0};
     size_t tx_count;
     Available(CTransactionRef &_ref, size_t _tx_count)
         : ref(_ref), tx_count(_tx_count) {}
 };
 
 static std::vector<CTransactionRef>
 CreateOrderedCoins(FastRandomContext &det_rand, int childTxs,
                    int min_ancestors) {
     std::vector<Available> available_coins;
     std::vector<CTransactionRef> ordered_coins;
     // Create some base transactions
     size_t tx_counter = 1;
     for (auto x = 0; x < 100; ++x) {
         CMutableTransaction tx = CMutableTransaction();
         tx.vin.resize(1);
         tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter);
         tx.vout.resize(det_rand.randrange(10) + 2);
         for (auto &out : tx.vout) {
             out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL;
             out.nValue = 10 * COIN;
         }
         ordered_coins.emplace_back(MakeTransactionRef(tx));
         available_coins.emplace_back(ordered_coins.back(), tx_counter++);
     }
     for (auto x = 0; x < childTxs && !available_coins.empty(); ++x) {
         CMutableTransaction tx = CMutableTransaction();
         size_t n_ancestors = det_rand.randrange(10) + 1;
         for (size_t ancestor = 0;
              ancestor < n_ancestors && !available_coins.empty(); ++ancestor) {
             size_t idx = det_rand.randrange(available_coins.size());
             Available coin = available_coins[idx];
             TxId txid = coin.ref->GetId();
             // biased towards taking min_ancestors parents, but maybe more
             size_t n_to_take =
                 det_rand.randrange(2) == 0
                     ? min_ancestors
                     : min_ancestors + det_rand.randrange(coin.ref->vout.size() -
                                                          coin.vin_left);
             for (size_t i = 0; i < n_to_take; ++i) {
                 tx.vin.emplace_back();
                 tx.vin.back().prevout = COutPoint(txid, coin.vin_left++);
                 tx.vin.back().scriptSig = CScript() << coin.tx_count;
             }
             if (coin.vin_left == coin.ref->vin.size()) {
                 coin = available_coins.back();
                 available_coins.pop_back();
             }
             tx.vout.resize(det_rand.randrange(10) + 2);
             for (auto &out : tx.vout) {
                 out.scriptPubKey = CScript()
                                    << CScriptNum(tx_counter) << OP_EQUAL;
                 out.nValue = 10 * COIN;
             }
         }
         ordered_coins.emplace_back(MakeTransactionRef(tx));
         available_coins.emplace_back(ordered_coins.back(), tx_counter++);
     }
     return ordered_coins;
 }
 
 static void ComplexMemPool(benchmark::Bench &bench) {
     FastRandomContext det_rand{true};
     int childTxs = 800;
     if (bench.complexityN() > 1) {
         childTxs = static_cast<int>(bench.complexityN());
     }
     std::vector<CTransactionRef> ordered_coins =
         CreateOrderedCoins(det_rand, childTxs, /* min_ancestors */ 1);
-    TestingSetup test_setup;
-
+    const auto testing_setup =
+        MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN);
     CTxMemPool pool;
     LOCK2(cs_main, pool.cs);
     bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
         for (auto &tx : ordered_coins) {
             AddTx(tx, pool);
         }
         pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
         pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front()));
     });
 }
 
 static void MempoolCheck(benchmark::Bench &bench) {
     FastRandomContext det_rand{true};
     const int childTxs =
         bench.complexityN() > 1 ? static_cast<int>(bench.complexityN()) : 2000;
     const std::vector<CTransactionRef> ordered_coins =
         CreateOrderedCoins(det_rand, childTxs, /* min_ancestors */ 5);
     const auto testing_setup =
         TestingSetup(CBaseChainParams::MAIN, {"-checkmempool=1"});
     CTxMemPool pool;
     LOCK2(cs_main, pool.cs);
     const CCoinsViewCache &coins_tip =
         testing_setup.m_node.chainman->ActiveChainstate().CoinsTip();
     for (auto &tx : ordered_coins) {
         AddTx(tx, pool);
     }
 
     bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
         pool.check(coins_tip, /* spendheight */ 2);
     });
 }
 
 BENCHMARK(ComplexMemPool);
 BENCHMARK(MempoolCheck);
diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp
index 58601fe5d..bca3fc944 100644
--- a/src/bench/rpc_blockchain.cpp
+++ b/src/bench/rpc_blockchain.cpp
@@ -1,64 +1,65 @@
 // 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 <bench/bench.h>
 #include <bench/data.h>
 
 #include <rpc/blockchain.h>
 #include <streams.h>
 #include <validation.h>
 
 #include <test/util/setup_common.h>
 
 #include <univalue.h>
 
 namespace {
 
 struct TestBlockAndIndex {
-    TestingSetup test_setup{};
+    const std::unique_ptr<const TestingSetup> testing_setup{
+        MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN)};
     CBlock block{};
     BlockHash blockHash{};
     CBlockIndex blockindex{};
 
     TestBlockAndIndex() {
         CDataStream stream(benchmark::data::block413567, SER_NETWORK,
                            PROTOCOL_VERSION);
         char a = '\0';
         // Prevent compaction
         stream.write(&a, 1);
 
         stream >> block;
 
         blockHash = block.GetHash();
         blockindex.phashBlock = &blockHash;
         blockindex.nBits = 403014710;
     }
 };
 
 } // namespace
 
 static void BlockToJsonVerbose(benchmark::Bench &bench) {
     TestBlockAndIndex data;
     bench.run([&] {
-        auto univalue =
-            blockToJSON(data.test_setup.m_node.chainman->m_blockman, data.block,
-                        &data.blockindex, &data.blockindex, /*txDetails=*/true);
+        auto univalue = blockToJSON(
+            data.testing_setup->m_node.chainman->m_blockman, data.block,
+            &data.blockindex, &data.blockindex, /*txDetails=*/true);
         ankerl::nanobench::doNotOptimizeAway(univalue);
     });
 }
 
 BENCHMARK(BlockToJsonVerbose);
 
 static void BlockToJsonVerboseWrite(benchmark::Bench &bench) {
     TestBlockAndIndex data;
-    auto univalue = blockToJSON(data.test_setup.m_node.chainman->m_blockman,
+    auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman,
                                 data.block, &data.blockindex, &data.blockindex,
                                 /*txDetails=*/true);
     bench.run([&] {
         auto str = univalue.write();
         ankerl::nanobench::doNotOptimizeAway(str);
     });
 }
 
 BENCHMARK(BlockToJsonVerboseWrite);
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index dcf43a374..4ff45f676 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -1,99 +1,92 @@
 // 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 <config.h>
 #include <consensus/amount.h>
 #include <interfaces/chain.h>
 #include <node/context.h>
 #include <validationinterface.h>
 #include <wallet/receive.h>
 #include <wallet/wallet.h>
 
 #include <test/util/mining.h>
 #include <test/util/setup_common.h>
 #include <test/util/wallet.h>
 
 #include <optional>
 
 static void WalletBalance(benchmark::Bench &bench, const bool set_dirty,
                           const bool add_watchonly, const bool add_mine) {
-    TestingSetup test_setup{
-        CBaseChainParams::REGTEST,
-        /* extra_args */
-        {
-            "-nodebuglogfile",
-            "-nodebug",
-        },
-    };
+    const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
 
     const auto &ADDRESS_WATCHONLY = ADDRESS_ECREG_UNSPENDABLE;
 
     const Config &config = GetConfig();
 
-    CWallet wallet{test_setup.m_node.chain.get(), "",
+    CWallet wallet{test_setup->m_node.chain.get(), "",
                    CreateMockWalletDatabase()};
     {
         wallet.SetupLegacyScriptPubKeyMan();
         bool first_run;
         if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) {
             assert(false);
         }
     }
 
-    auto handler = test_setup.m_node.chain->handleNotifications(
+    auto handler = test_setup->m_node.chain->handleNotifications(
         {&wallet, [](CWallet *) {}});
 
     const std::optional<std::string> address_mine{
         add_mine ? std::optional<std::string>{getnewaddress(config, wallet)}
                  : std::nullopt};
     if (add_watchonly) {
         importaddress(wallet, ADDRESS_WATCHONLY);
     }
 
     for (int i = 0; i < 100; ++i) {
-        generatetoaddress(config, test_setup.m_node,
+        generatetoaddress(config, test_setup->m_node,
                           address_mine.value_or(ADDRESS_WATCHONLY));
-        generatetoaddress(config, test_setup.m_node, ADDRESS_WATCHONLY);
+        generatetoaddress(config, test_setup->m_node, ADDRESS_WATCHONLY);
     }
     SyncWithValidationInterfaceQueue();
 
     // Cache
     auto bal = GetBalance(wallet);
 
     bench.run([&] {
         if (set_dirty) {
             wallet.MarkDirty();
         }
         bal = GetBalance(wallet);
         if (add_mine) {
             assert(bal.m_mine_trusted > Amount::zero());
         }
         if (add_watchonly) {
             assert(bal.m_watchonly_trusted > Amount::zero());
         }
     });
 }
 
 static void WalletBalanceDirty(benchmark::Bench &bench) {
     WalletBalance(bench, /* set_dirty */ true, /* add_watchonly */ true,
                   /* add_mine */ true);
 }
 static void WalletBalanceClean(benchmark::Bench &bench) {
     WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ true,
                   /* add_mine */ true);
 }
 static void WalletBalanceMine(benchmark::Bench &bench) {
     WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ false,
                   /* add_mine */ true);
 }
 static void WalletBalanceWatch(benchmark::Bench &bench) {
     WalletBalance(bench, /* set_dirty */ false, /* add_watchonly */ true,
                   /* add_mine */ false);
 }
 
 BENCHMARK(WalletBalanceDirty);
 BENCHMARK(WalletBalanceClean);
 BENCHMARK(WalletBalanceMine);
 BENCHMARK(WalletBalanceWatch);
diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp
index f41a08d91..f1e772729 100644
--- a/src/test/fuzz/banman.cpp
+++ b/src/test/fuzz/banman.cpp
@@ -1,73 +1,74 @@
 // Copyright (c) 2020 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 <banman.h>
 #include <config.h>
 #include <fs.h>
 #include <netaddress.h>
 #include <util/system.h>
 
 #include <test/fuzz/FuzzedDataProvider.h>
 #include <test/fuzz/fuzz.h>
 #include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
 
 #include <cstdint>
 #include <limits>
 #include <string>
 #include <vector>
 
 namespace {
 int64_t
 ConsumeBanTimeOffset(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     // Avoid signed integer overflow by capping to int32_t max:
     // banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 +
     // 9223372036854775807 cannot be represented in type 'long'
     return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(
         std::numeric_limits<int64_t>::min(),
         std::numeric_limits<int32_t>::max());
 }
 } // namespace
 
 void initialize_banman() {
     static const auto testing_setup = MakeNoLogFileContext<>();
 }
 
 FUZZ_TARGET_INIT(banman, initialize_banman) {
     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     const fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist.dat";
     fs::remove(banlist_file);
     const CChainParams &chainparams = GetConfig().GetChainParams();
     {
         BanMan ban_man{banlist_file, chainparams, nullptr,
                        ConsumeBanTimeOffset(fuzzed_data_provider)};
         while (fuzzed_data_provider.ConsumeBool()) {
             CallOneOf(
                 fuzzed_data_provider,
                 [&] {
                     ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider),
                                 ConsumeBanTimeOffset(fuzzed_data_provider),
                                 fuzzed_data_provider.ConsumeBool());
                 },
                 [&] {
                     ban_man.Ban(ConsumeSubNet(fuzzed_data_provider),
                                 ConsumeBanTimeOffset(fuzzed_data_provider),
                                 fuzzed_data_provider.ConsumeBool());
                 },
                 [&] { ban_man.ClearBanned(); }, [] {},
                 [&] { ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider)); },
                 [&] { ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider)); },
                 [&] { ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider)); },
                 [&] { ban_man.Unban(ConsumeSubNet(fuzzed_data_provider)); },
                 [&] {
                     banmap_t banmap;
                     ban_man.GetBanned(banmap);
                 },
                 [&] { ban_man.DumpBanlist(); }, [] {},
                 [&] {
                     ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
                 });
         }
     }
     fs::remove(fs::PathToString(banlist_file));
 }
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index 931a6d224..71482f655 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -1,286 +1,287 @@
 // Copyright (c) 2020 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 <chainparamsbase.h>
 #include <coins.h>
 #include <consensus/amount.h>
 #include <consensus/tx_verify.h>
 #include <consensus/validation.h>
 #include <key.h>
 #include <policy/policy.h>
 #include <primitives/blockhash.h>
 #include <primitives/transaction.h>
 #include <pubkey.h>
 #include <validation.h>
 
 #include <test/fuzz/FuzzedDataProvider.h>
 #include <test/fuzz/fuzz.h>
 #include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
 
 #include <cstdint>
 #include <limits>
 #include <optional>
 #include <string>
 #include <vector>
 
 namespace {
 const TestingSetup *g_setup;
 const Coin EMPTY_COIN{};
 
 bool operator==(const Coin &a, const Coin &b) {
     if (a.IsSpent() && b.IsSpent()) {
         return true;
     }
     return a.IsCoinBase() == b.IsCoinBase() && a.GetHeight() == b.GetHeight() &&
            a.GetTxOut() == b.GetTxOut();
 }
 } // namespace
 
 void initialize_coins_view() {
     static const auto testing_setup =
         MakeNoLogFileContext<const TestingSetup>();
     g_setup = testing_setup.get();
 }
 
 FUZZ_TARGET_INIT(coins_view, initialize_coins_view) {
     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     CCoinsView backend_coins_view;
     CCoinsViewCache coins_view_cache{&backend_coins_view};
     COutPoint random_out_point;
     Coin random_coin;
     CMutableTransaction random_mutable_transaction;
     while (fuzzed_data_provider.ConsumeBool()) {
         CallOneOf(
             fuzzed_data_provider,
             [&] {
                 if (random_coin.IsSpent()) {
                     return;
                 }
                 Coin coin = random_coin;
                 bool expected_code_path = false;
                 const bool possible_overwrite =
                     fuzzed_data_provider.ConsumeBool();
                 try {
                     coins_view_cache.AddCoin(random_out_point, std::move(coin),
                                              possible_overwrite);
                     expected_code_path = true;
                 } catch (const std::logic_error &e) {
                     if (e.what() ==
                         std::string{"Attempted to overwrite an unspent coin "
                                     "(when possible_overwrite is false)"}) {
                         assert(!possible_overwrite);
                         expected_code_path = true;
                     }
                 }
                 assert(expected_code_path);
             },
             [&] { (void)coins_view_cache.Flush(); },
             [&] {
                 coins_view_cache.SetBestBlock(
                     BlockHash{ConsumeUInt256(fuzzed_data_provider)});
             },
             [&] {
                 Coin move_to;
                 (void)coins_view_cache.SpendCoin(
                     random_out_point,
                     fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
             },
             [&] { coins_view_cache.Uncache(random_out_point); },
             [&] {
                 if (fuzzed_data_provider.ConsumeBool()) {
                     backend_coins_view = CCoinsView{};
                 }
                 coins_view_cache.SetBackend(backend_coins_view);
             },
             [&] {
                 const std::optional<COutPoint> opt_out_point =
                     ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
                 if (!opt_out_point) {
                     return;
                 }
                 random_out_point = *opt_out_point;
             },
             [&] {
                 const std::optional<Coin> opt_coin =
                     ConsumeDeserializable<Coin>(fuzzed_data_provider);
                 if (!opt_coin) {
                     return;
                 }
                 random_coin = *opt_coin;
             },
             [&] {
                 const std::optional<CMutableTransaction>
                     opt_mutable_transaction =
                         ConsumeDeserializable<CMutableTransaction>(
                             fuzzed_data_provider);
                 if (!opt_mutable_transaction) {
                     return;
                 }
                 random_mutable_transaction = *opt_mutable_transaction;
             },
             [&] {
                 CCoinsMap coins_map;
                 while (fuzzed_data_provider.ConsumeBool()) {
                     CCoinsCacheEntry coins_cache_entry;
                     coins_cache_entry.flags =
                         fuzzed_data_provider.ConsumeIntegral<uint8_t>();
                     if (fuzzed_data_provider.ConsumeBool()) {
                         coins_cache_entry.coin = random_coin;
                     } else {
                         const std::optional<Coin> opt_coin =
                             ConsumeDeserializable<Coin>(fuzzed_data_provider);
                         if (!opt_coin) {
                             return;
                         }
                         coins_cache_entry.coin = *opt_coin;
                     }
                     coins_map.emplace(random_out_point,
                                       std::move(coins_cache_entry));
                 }
                 bool expected_code_path = false;
                 try {
                     coins_view_cache.BatchWrite(
                         coins_map,
                         fuzzed_data_provider.ConsumeBool()
                             ? BlockHash{ConsumeUInt256(fuzzed_data_provider)}
                             : coins_view_cache.GetBestBlock());
                     expected_code_path = true;
                 } catch (const std::logic_error &e) {
                     if (e.what() ==
                         std::string{"FRESH flag misapplied to coin that exists "
                                     "in parent cache"}) {
                         expected_code_path = true;
                     }
                 }
                 assert(expected_code_path);
             });
     }
 
     {
         const Coin &coin_using_access_coin =
             coins_view_cache.AccessCoin(random_out_point);
         const bool exists_using_access_coin =
             !(coin_using_access_coin == EMPTY_COIN);
         const bool exists_using_have_coin =
             coins_view_cache.HaveCoin(random_out_point);
         const bool exists_using_have_coin_in_cache =
             coins_view_cache.HaveCoinInCache(random_out_point);
         Coin coin_using_get_coin;
         const bool exists_using_get_coin =
             coins_view_cache.GetCoin(random_out_point, coin_using_get_coin);
         if (exists_using_get_coin) {
             assert(coin_using_get_coin == coin_using_access_coin);
         }
         assert((exists_using_access_coin && exists_using_have_coin_in_cache &&
                 exists_using_have_coin && exists_using_get_coin) ||
                (!exists_using_access_coin && !exists_using_have_coin_in_cache &&
                 !exists_using_have_coin && !exists_using_get_coin));
         const bool exists_using_have_coin_in_backend =
             backend_coins_view.HaveCoin(random_out_point);
         if (exists_using_have_coin_in_backend) {
             assert(exists_using_have_coin);
         }
         Coin coin_using_backend_get_coin;
         if (backend_coins_view.GetCoin(random_out_point,
                                        coin_using_backend_get_coin)) {
             assert(exists_using_have_coin_in_backend);
             assert(coin_using_get_coin == coin_using_backend_get_coin);
         } else {
             assert(!exists_using_have_coin_in_backend);
         }
     }
 
     {
         bool expected_code_path = false;
         try {
             (void)coins_view_cache.Cursor();
         } catch (const std::logic_error &) {
             expected_code_path = true;
         }
         assert(expected_code_path);
         (void)coins_view_cache.DynamicMemoryUsage();
         (void)coins_view_cache.EstimateSize();
         (void)coins_view_cache.GetBestBlock();
         (void)coins_view_cache.GetCacheSize();
         (void)coins_view_cache.GetHeadBlocks();
         (void)coins_view_cache.HaveInputs(
             CTransaction{random_mutable_transaction});
     }
 
     {
         const CCoinsViewCursor *coins_view_cursor = backend_coins_view.Cursor();
         assert(coins_view_cursor == nullptr);
         (void)backend_coins_view.EstimateSize();
         (void)backend_coins_view.GetBestBlock();
         (void)backend_coins_view.GetHeadBlocks();
     }
 
     if (fuzzed_data_provider.ConsumeBool()) {
         CallOneOf(
             fuzzed_data_provider,
             [&] {
                 const CTransaction transaction{random_mutable_transaction};
                 bool is_spent = false;
                 for (const CTxOut &tx_out : transaction.vout) {
                     if (Coin{tx_out, 0, transaction.IsCoinBase()}.IsSpent()) {
                         is_spent = true;
                     }
                 }
                 if (is_spent) {
                     // Avoid:
                     // coins.cpp:69: void CCoinsViewCache::AddCoin(const
                     // COutPoint &, Coin &&, bool): Assertion `!coin.IsSpent()'
                     // failed.
                     return;
                 }
                 bool expected_code_path = false;
                 const int height{
                     int(fuzzed_data_provider.ConsumeIntegral<uint32_t>() >> 1)};
                 const bool possible_overwrite =
                     fuzzed_data_provider.ConsumeBool();
                 try {
                     AddCoins(coins_view_cache, transaction, height,
                              possible_overwrite);
                     expected_code_path = true;
                 } catch (const std::logic_error &e) {
                     if (e.what() ==
                         std::string{"Attempted to overwrite an unspent coin "
                                     "(when possible_overwrite is false)"}) {
                         assert(!possible_overwrite);
                         expected_code_path = true;
                     }
                 }
                 assert(expected_code_path);
             },
             [&] {
                 uint32_t flags =
                     fuzzed_data_provider.ConsumeIntegral<uint32_t>();
                 (void)AreInputsStandard(
                     CTransaction{random_mutable_transaction}, coins_view_cache,
                     flags);
             },
             [&] {
                 TxValidationState state;
                 Amount tx_fee_out;
                 const CTransaction transaction{random_mutable_transaction};
                 if (ContainsSpentInput(transaction, coins_view_cache)) {
                     // Avoid:
                     // consensus/tx_verify.cpp:171: bool
                     // Consensus::CheckTxInputs(const CTransaction &,
                     // TxValidationState &, const CCoinsViewCache &, int,
                     // CAmount &): Assertion `!coin.IsSpent()' failed.
                 }
                 try {
                     (void)Consensus::CheckTxInputs(
                         transaction, state, coins_view_cache,
                         fuzzed_data_provider.ConsumeIntegralInRange<int>(
                             0, std::numeric_limits<int>::max()),
                         tx_fee_out);
                     assert(MoneyRange(tx_fee_out));
                 } catch (const std::runtime_error &) {
                 }
             });
     }
 }
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index 9d40a6f29..789384e16 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -1,126 +1,127 @@
 // Copyright (c) 2020 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 <config.h>
 #include <net.h>
 #include <netaddress.h>
 #include <protocol.h>
 #include <test/fuzz/FuzzedDataProvider.h>
 #include <test/fuzz/fuzz.h>
 #include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
 
 #include <cstdint>
 #include <vector>
 
 namespace {
 const TestingSetup *g_setup;
 } // namespace
 
 void initialize_connman() {
     static const auto testing_setup =
         MakeNoLogFileContext<const TestingSetup>();
     g_setup = testing_setup.get();
 }
 
 FUZZ_TARGET_INIT(connman, initialize_connman) {
     const Config &config = GetConfig();
     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
     CConnman connman{config, fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
                      fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
                      *g_setup->m_node.addrman,
                      fuzzed_data_provider.ConsumeBool()};
     CNetAddr random_netaddr;
     CNode random_node = ConsumeNode(fuzzed_data_provider);
     CSubNet random_subnet;
     std::string random_string;
     while (fuzzed_data_provider.ConsumeBool()) {
         CallOneOf(
             fuzzed_data_provider,
             [&] { random_netaddr = ConsumeNetAddr(fuzzed_data_provider); },
             [&] { random_subnet = ConsumeSubNet(fuzzed_data_provider); },
             [&] {
                 random_string =
                     fuzzed_data_provider.ConsumeRandomLengthString(64);
             },
             [&] { connman.AddNode(random_string); },
             [&] {
                 connman.CheckIncomingNonce(
                     fuzzed_data_provider.ConsumeIntegral<uint64_t>());
             },
             [&] {
                 connman.DisconnectNode(
                     fuzzed_data_provider.ConsumeIntegral<NodeId>());
             },
             [&] { connman.DisconnectNode(random_netaddr); },
             [&] { connman.DisconnectNode(random_string); },
             [&] { connman.DisconnectNode(random_subnet); },
             [&] { connman.ForEachNode([](auto) {}); },
             [&] {
                 (void)connman.ForNode(
                     fuzzed_data_provider.ConsumeIntegral<NodeId>(),
                     [&](auto) { return fuzzed_data_provider.ConsumeBool(); });
             },
             [&] {
                 (void)connman.GetAddresses(
                     fuzzed_data_provider.ConsumeIntegral<size_t>(),
                     fuzzed_data_provider.ConsumeIntegral<size_t>(),
                     std::nullopt);
             },
             [&] {
                 (void)connman.GetAddresses(
                     random_node, fuzzed_data_provider.ConsumeIntegral<size_t>(),
                     fuzzed_data_provider.ConsumeIntegral<size_t>());
             },
             [&] {
                 (void)connman.GetDeterministicRandomizer(
                     fuzzed_data_provider.ConsumeIntegral<uint64_t>());
             },
             [&] {
                 (void)connman.GetNodeCount(
                     fuzzed_data_provider.PickValueInArray(
                         {CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN,
                          CConnman::CONNECTIONS_OUT,
                          CConnman::CONNECTIONS_ALL}));
             },
             [&] {
                 (void)connman.OutboundTargetReached(
                     fuzzed_data_provider.ConsumeBool());
             },
             [&] {
                 CSerializedNetMsg serialized_net_msg;
                 serialized_net_msg.m_type =
                     fuzzed_data_provider.ConsumeRandomLengthString(
                         CMessageHeader::COMMAND_SIZE);
                 serialized_net_msg.data =
                     ConsumeRandomLengthByteVector(fuzzed_data_provider);
                 connman.PushMessage(&random_node,
                                     std::move(serialized_net_msg));
             },
             [&] { connman.RemoveAddedNode(random_string); },
             [&] {
                 connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
             },
             [&] {
                 connman.SetTryNewOutboundPeer(
                     fuzzed_data_provider.ConsumeBool());
                 connman.SetTryNewOutboundPeer(
                     fuzzed_data_provider.ConsumeBool());
             });
     }
     (void)connman.GetAddedNodeInfo();
     (void)connman.GetExtraFullOutboundCount();
     (void)connman.GetLocalServices();
     (void)connman.GetMaxOutboundTarget();
     (void)connman.GetMaxOutboundTimeframe();
     (void)connman.GetMaxOutboundTimeLeftInCycle();
     (void)connman.GetNetworkActive();
     std::vector<CNodeStats> stats;
     connman.GetNodeStats(stats);
     (void)connman.GetOutboundTargetBytesLeft();
     (void)connman.GetReceiveFloodSize();
     (void)connman.GetTotalBytesRecv();
     (void)connman.GetTotalBytesSent();
     (void)connman.GetTryNewOutboundPeer();
     (void)connman.GetUseAddrmanOutgoing();
 }
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index a7dfc7e4e..b639d882f 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -1,521 +1,506 @@
 // 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.
 
 #ifndef BITCOIN_TEST_FUZZ_UTIL_H
 #define BITCOIN_TEST_FUZZ_UTIL_H
 
 #include <arith_uint256.h>
 #include <chainparamsbase.h>
 #include <coins.h>
 #include <consensus/amount.h>
 #include <net.h>
 #include <netbase.h>
 #include <script/script.h>
 #include <script/standard.h>
 #include <serialize.h>
 #include <streams.h>
 #include <uint256.h>
 #include <util/vector.h>
 #include <version.h>
 
 #include <test/fuzz/FuzzedDataProvider.h>
 #include <test/fuzz/fuzz.h>
-#include <test/util/setup_common.h>
 
 #include <algorithm>
 #include <cstdint>
 #include <cstdio>
 #include <optional>
 #include <string>
-#include <vector>
 
 namespace fuzzer {
 // FIXME find a better way to avoid duplicating the MAX_MONEY definition
 constexpr int64_t MAX_MONEY_AS_INT = int64_t(21000000) * int64_t(100000000);
 } // end namespace fuzzer
 
 using namespace fuzzer;
 
 template <typename... Callables>
 void CallOneOf(FuzzedDataProvider &fuzzed_data_provider,
                Callables... callables) {
     constexpr size_t call_size{sizeof...(callables)};
     static_assert(call_size >= 1);
     const size_t call_index{
         fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, call_size - 1)};
 
     size_t i{0};
     return ((i++ == call_index ? callables() : void()), ...);
 }
 
 [[nodiscard]] inline std::vector<uint8_t>
 ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider,
                               const size_t max_length = 4096) noexcept {
     const std::string s =
         fuzzed_data_provider.ConsumeRandomLengthString(max_length);
     return {s.begin(), s.end()};
 }
 
 [[nodiscard]] inline CDataStream
 ConsumeDataStream(FuzzedDataProvider &fuzzed_data_provider,
                   const size_t max_length = 4096) noexcept {
     return CDataStream{
         ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length),
         SER_NETWORK, INIT_PROTO_VERSION};
 }
 
 [[nodiscard]] inline std::vector<std::string>
 ConsumeRandomLengthStringVector(FuzzedDataProvider &fuzzed_data_provider,
                                 const size_t max_vector_size = 16,
                                 const size_t max_string_length = 16) noexcept {
     const size_t n_elements =
         fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
     std::vector<std::string> r;
     for (size_t i = 0; i < n_elements; ++i) {
         r.push_back(
             fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));
     }
     return r;
 }
 
 template <typename T>
 [[nodiscard]] inline std::vector<T>
 ConsumeRandomLengthIntegralVector(FuzzedDataProvider &fuzzed_data_provider,
                                   const size_t max_vector_size = 16) noexcept {
     const size_t n_elements =
         fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
     std::vector<T> r;
     for (size_t i = 0; i < n_elements; ++i) {
         r.push_back(fuzzed_data_provider.ConsumeIntegral<T>());
     }
     return r;
 }
 
 template <typename T>
 [[nodiscard]] inline std::optional<T>
 ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider,
                       const size_t max_length = 4096) noexcept {
     const std::vector<uint8_t> buffer =
         ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);
     CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
     T obj;
     try {
         ds >> obj;
     } catch (const std::ios_base::failure &) {
         return std::nullopt;
     }
     return obj;
 }
 
 [[nodiscard]] inline opcodetype
 ConsumeOpcodeType(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return static_cast<opcodetype>(
         fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE));
 }
 
 [[nodiscard]] inline Amount
 ConsumeMoney(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(
                0, MAX_MONEY_AS_INT) *
            SATOSHI;
 }
 
 [[nodiscard]] inline CScript
 ConsumeScript(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     const std::vector<uint8_t> b =
         ConsumeRandomLengthByteVector(fuzzed_data_provider);
     return {b.begin(), b.end()};
 }
 
 [[nodiscard]] inline CScriptNum
 ConsumeScriptNum(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
 }
 
 [[nodiscard]] inline uint160
 ConsumeUInt160(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     const std::vector<uint8_t> v160 =
         fuzzed_data_provider.ConsumeBytes<uint8_t>(160 / 8);
     if (v160.size() != 160 / 8) {
         return {};
     }
     return uint160{v160};
 }
 
 [[nodiscard]] inline uint256
 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     const std::vector<uint8_t> v256 =
         fuzzed_data_provider.ConsumeBytes<uint8_t>(256 / 8);
     if (v256.size() != 256 / 8) {
         return {};
     }
     return uint256{v256};
 }
 
 [[nodiscard]] inline arith_uint256
 ConsumeArithUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return UintToArith256(ConsumeUInt256(fuzzed_data_provider));
 }
 
 [[nodiscard]] inline CTxDestination
 ConsumeTxDestination(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     CTxDestination tx_destination;
     CallOneOf(
         fuzzed_data_provider, [&] { tx_destination = CNoDestination{}; },
         [&] { tx_destination = PKHash{ConsumeUInt160(fuzzed_data_provider)}; },
         [&] {
             tx_destination = ScriptHash{ConsumeUInt160(fuzzed_data_provider)};
         });
     return tx_destination;
 }
 
 template <typename T>
 [[nodiscard]] bool MultiplicationOverflow(const T i, const T j) noexcept {
     static_assert(std::is_integral<T>::value, "Integral required.");
     if (std::numeric_limits<T>::is_signed) {
         if (i > 0) {
             if (j > 0) {
                 return i > (std::numeric_limits<T>::max() / j);
             } else {
                 return j < (std::numeric_limits<T>::min() / i);
             }
         } else {
             if (j > 0) {
                 return i < (std::numeric_limits<T>::min() / j);
             } else {
                 return i != 0 && (j < (std::numeric_limits<T>::max() / i));
             }
         }
     } else {
         return j != 0 && i > std::numeric_limits<T>::max() / j;
     }
 }
 
 template <class T>
 [[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept {
     static_assert(std::is_integral<T>::value, "Integral required.");
     if (std::numeric_limits<T>::is_signed) {
         return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
                (i < 0 && j < std::numeric_limits<T>::min() - i);
     }
     return std::numeric_limits<T>::max() - i < j;
 }
 
 [[nodiscard]] inline bool
 ContainsSpentInput(const CTransaction &tx,
                    const CCoinsViewCache &inputs) noexcept {
     for (const CTxIn &tx_in : tx.vin) {
         const Coin &coin = inputs.AccessCoin(tx_in.prevout);
         if (coin.IsSpent()) {
             return true;
         }
     }
     return false;
 }
 
 /**
  * Returns a byte vector of specified size regardless of the number of remaining
  * bytes available from the fuzzer. Pads with zero value bytes if needed to
  * achieve the specified size.
  */
 [[nodiscard]] inline std::vector<uint8_t>
 ConsumeFixedLengthByteVector(FuzzedDataProvider &fuzzed_data_provider,
                              const size_t length) noexcept {
     std::vector<uint8_t> result(length);
     const std::vector<uint8_t> random_bytes =
         fuzzed_data_provider.ConsumeBytes<uint8_t>(length);
     if (!random_bytes.empty()) {
         std::memcpy(result.data(), random_bytes.data(), random_bytes.size());
     }
     return result;
 }
 
 inline CNetAddr
 ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     const Network network = fuzzed_data_provider.PickValueInArray(
         {Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL,
          Network::NET_ONION});
     CNetAddr net_addr;
     if (network == Network::NET_IPV4) {
         const in_addr v4_addr = {
             .s_addr = fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
         net_addr = CNetAddr{v4_addr};
     } else if (network == Network::NET_IPV6) {
         if (fuzzed_data_provider.remaining_bytes() >= 16) {
             in6_addr v6_addr = {};
             memcpy(v6_addr.s6_addr,
                    fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data(), 16);
             net_addr = CNetAddr{
                 v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
         }
     } else if (network == Network::NET_INTERNAL) {
         net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
     } else if (network == Network::NET_ONION) {
         net_addr.SetSpecial(fuzzed_data_provider.ConsumeBytesAsString(32));
     }
     return net_addr;
 }
 
 inline CSubNet
 ConsumeSubNet(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return {ConsumeNetAddr(fuzzed_data_provider),
             fuzzed_data_provider.ConsumeIntegral<uint8_t>()};
 }
 
 inline CService
 ConsumeService(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return {ConsumeNetAddr(fuzzed_data_provider),
             fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
 }
 
 inline CAddress
 ConsumeAddress(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return {ConsumeService(fuzzed_data_provider),
             static_cast<ServiceFlags>(
                 fuzzed_data_provider.ConsumeIntegral<uint64_t>()),
             NodeSeconds{std::chrono::seconds{
                 fuzzed_data_provider.ConsumeIntegral<uint32_t>()}}};
 }
 
 inline CNode ConsumeNode(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     const NodeId node_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
     const SOCKET socket = INVALID_SOCKET;
     const CAddress address = ConsumeAddress(fuzzed_data_provider);
     const uint64_t keyed_net_group =
         fuzzed_data_provider.ConsumeIntegral<uint64_t>();
     const uint64_t local_host_nonce =
         fuzzed_data_provider.ConsumeIntegral<uint64_t>();
     const uint64_t local_extra_entropy =
         fuzzed_data_provider.ConsumeIntegral<uint64_t>();
     const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
     const std::string addr_name =
         fuzzed_data_provider.ConsumeRandomLengthString(64);
     const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(
         {ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY,
          ConnectionType::MANUAL, ConnectionType::FEELER,
          ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH});
     const bool inbound_onion = fuzzed_data_provider.ConsumeBool();
     return {node_id,         socket,           address,
             keyed_net_group, local_host_nonce, local_extra_entropy,
             addr_bind,       addr_name,        conn_type,
             inbound_onion};
 }
 
-template <class T = const BasicTestingSetup>
-std::unique_ptr<T>
-MakeNoLogFileContext(const std::string &chain_name = CBaseChainParams::REGTEST,
-                     const std::vector<const char *> &extra_args = {}) {
-    // Prepend default arguments for fuzzing
-    const std::vector<const char *> arguments = Cat(
-        {
-            "-nodebuglogfile",
-        },
-        extra_args);
-
-    return std::make_unique<T>(chain_name, arguments);
-}
 
 class FuzzedFileProvider {
     FuzzedDataProvider &m_fuzzed_data_provider;
     int64_t m_offset = 0;
 
 public:
     FuzzedFileProvider(FuzzedDataProvider &fuzzed_data_provider)
         : m_fuzzed_data_provider{fuzzed_data_provider} {}
 
     FILE *open() {
         if (m_fuzzed_data_provider.ConsumeBool()) {
             return nullptr;
         }
         std::string mode;
         // clang-format off
         CallOneOf(
             m_fuzzed_data_provider,
             [&] { mode = "r"; },
             [&] { mode = "r+"; },
             [&] { mode = "w"; },
             [&] { mode = "w+"; },
             [&] { mode = "a"; },
             [&] { mode = "a+"; }
         );
         // clang-format on
 #ifdef _GNU_SOURCE
         const cookie_io_functions_t io_hooks = {
             FuzzedFileProvider::read,
             FuzzedFileProvider::write,
             FuzzedFileProvider::seek,
             FuzzedFileProvider::close,
         };
         return fopencookie(this, mode.c_str(), io_hooks);
 #else
         (void)mode;
         return nullptr;
 #endif
     }
 
     static ssize_t read(void *cookie, char *buf, size_t size) {
         FuzzedFileProvider *fuzzed_file = (FuzzedFileProvider *)cookie;
         if (buf == nullptr || size == 0 ||
             fuzzed_file->m_fuzzed_data_provider.ConsumeBool()) {
             return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
         }
         const std::vector<uint8_t> random_bytes =
             fuzzed_file->m_fuzzed_data_provider.ConsumeBytes<uint8_t>(size);
         if (random_bytes.empty()) {
             return 0;
         }
         std::memcpy(buf, random_bytes.data(), random_bytes.size());
         if (AdditionOverflow(fuzzed_file->m_offset,
                              int64_t(random_bytes.size()))) {
             return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
         }
         fuzzed_file->m_offset += random_bytes.size();
         return random_bytes.size();
     }
 
     static ssize_t write(void *cookie, const char *buf, size_t size) {
         FuzzedFileProvider *fuzzed_file = (FuzzedFileProvider *)cookie;
         const ssize_t n =
             fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(
                 0, size);
         if (AdditionOverflow(fuzzed_file->m_offset, int64_t(n))) {
             return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
         }
         fuzzed_file->m_offset += n;
         return n;
     }
 
     static int seek(void *cookie, int64_t *offset, int whence) {
         // SEEK_END not implemented yet.
         assert(whence == SEEK_SET || whence == SEEK_CUR);
         FuzzedFileProvider *fuzzed_file = (FuzzedFileProvider *)cookie;
         int64_t new_offset = 0;
         if (whence == SEEK_SET) {
             new_offset = *offset;
         } else if (whence == SEEK_CUR) {
             if (AdditionOverflow(fuzzed_file->m_offset, *offset)) {
                 return -1;
             }
             new_offset = fuzzed_file->m_offset + *offset;
         }
         if (new_offset < 0) {
             return -1;
         }
         fuzzed_file->m_offset = new_offset;
         *offset = new_offset;
         return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(
             -1, 0);
     }
 
     static int close(void *cookie) {
         FuzzedFileProvider *fuzzed_file = (FuzzedFileProvider *)cookie;
         return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(
             -1, 0);
     }
 };
 
 [[nodiscard]] inline FuzzedFileProvider
 ConsumeFile(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return {fuzzed_data_provider};
 }
 
 class FuzzedAutoFileProvider {
     FuzzedFileProvider m_fuzzed_file_provider;
 
 public:
     FuzzedAutoFileProvider(FuzzedDataProvider &fuzzed_data_provider)
         : m_fuzzed_file_provider{fuzzed_data_provider} {}
 
     AutoFile open() { return AutoFile{m_fuzzed_file_provider.open()}; }
 };
 
 [[nodiscard]] inline FuzzedAutoFileProvider
 ConsumeAutoFile(FuzzedDataProvider &fuzzed_data_provider) noexcept {
     return {fuzzed_data_provider};
 }
 
 #define WRITE_TO_STREAM_CASE(type, consume)                                    \
     [&] {                                                                      \
         type o = consume;                                                      \
         stream << o;                                                           \
     }
 template <typename Stream>
 void WriteToStream(FuzzedDataProvider &fuzzed_data_provider,
                    Stream &stream) noexcept {
     while (fuzzed_data_provider.ConsumeBool()) {
         try {
             CallOneOf(
                 fuzzed_data_provider,
                 WRITE_TO_STREAM_CASE(bool, fuzzed_data_provider.ConsumeBool()),
                 WRITE_TO_STREAM_CASE(
                     char, fuzzed_data_provider.ConsumeIntegral<char>()),
                 WRITE_TO_STREAM_CASE(
                     int8_t, fuzzed_data_provider.ConsumeIntegral<int8_t>()),
                 WRITE_TO_STREAM_CASE(
                     uint8_t, fuzzed_data_provider.ConsumeIntegral<uint8_t>()),
                 WRITE_TO_STREAM_CASE(
                     int16_t, fuzzed_data_provider.ConsumeIntegral<int16_t>()),
                 WRITE_TO_STREAM_CASE(
                     uint16_t, fuzzed_data_provider.ConsumeIntegral<uint16_t>()),
                 WRITE_TO_STREAM_CASE(
                     int32_t, fuzzed_data_provider.ConsumeIntegral<int32_t>()),
                 WRITE_TO_STREAM_CASE(
                     uint32_t, fuzzed_data_provider.ConsumeIntegral<uint32_t>()),
                 WRITE_TO_STREAM_CASE(
                     int64_t, fuzzed_data_provider.ConsumeIntegral<int64_t>()),
                 WRITE_TO_STREAM_CASE(
                     uint64_t, fuzzed_data_provider.ConsumeIntegral<uint64_t>()),
                 WRITE_TO_STREAM_CASE(
                     float, fuzzed_data_provider.ConsumeFloatingPoint<float>()),
                 WRITE_TO_STREAM_CASE(
                     double,
                     fuzzed_data_provider.ConsumeFloatingPoint<double>()),
                 WRITE_TO_STREAM_CASE(
                     std::string,
                     fuzzed_data_provider.ConsumeRandomLengthString(32)),
                 WRITE_TO_STREAM_CASE(std::vector<char>,
                                      ConsumeRandomLengthIntegralVector<char>(
                                          fuzzed_data_provider)));
         } catch (const std::ios_base::failure &) {
             break;
         }
     }
 }
 
 #define READ_FROM_STREAM_CASE(type)                                            \
     [&] {                                                                      \
         type o;                                                                \
         stream >> o;                                                           \
     }
 template <typename Stream>
 void ReadFromStream(FuzzedDataProvider &fuzzed_data_provider,
                     Stream &stream) noexcept {
     while (fuzzed_data_provider.ConsumeBool()) {
         try {
             // clang-format off
             CallOneOf(
                 fuzzed_data_provider,
                 READ_FROM_STREAM_CASE(bool),
                 READ_FROM_STREAM_CASE(char),
                 READ_FROM_STREAM_CASE(int8_t),
                 READ_FROM_STREAM_CASE(uint8_t),
                 READ_FROM_STREAM_CASE(int16_t),
                 READ_FROM_STREAM_CASE(uint16_t),
                 READ_FROM_STREAM_CASE(int32_t),
                 READ_FROM_STREAM_CASE(uint32_t),
                 READ_FROM_STREAM_CASE(int64_t),
                 READ_FROM_STREAM_CASE(uint64_t),
                 READ_FROM_STREAM_CASE(float),
                 READ_FROM_STREAM_CASE(double),
                 READ_FROM_STREAM_CASE(std::string),
                 READ_FROM_STREAM_CASE(std::vector<char>)
             );
             // clang-format on
         } catch (const std::ios_base::failure &) {
             break;
         }
     }
 }
 
 #endif // BITCOIN_TEST_FUZZ_UTIL_H
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index ab0f97574..495aedce4 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -1,269 +1,288 @@
 // 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_UTIL_SETUP_COMMON_H
 #define BITCOIN_TEST_UTIL_SETUP_COMMON_H
 
 #include <blockindex.h>
 #include <chainparamsbase.h>
 #include <consensus/amount.h>
 #include <fs.h>
 #include <key.h>
 #include <node/caches.h>
 #include <node/context.h>
 #include <primitives/transaction.h>
 #include <pubkey.h>
 #include <random.h>
 #include <stdexcept>
 #include <txmempool.h>
 #include <util/check.h>
 #include <util/string.h>
 #include <util/system.h>
+#include <util/vector.h>
 
 #include <type_traits>
 #include <vector>
 
 class Config;
 
 // Enable BOOST_CHECK_EQUAL for enum class types
 template <typename T>
 std::ostream &operator<<(
     typename std::enable_if<std::is_enum<T>::value, std::ostream>::type &stream,
     const T &e) {
     return stream << static_cast<typename std::underlying_type<T>::type>(e);
 }
 
 /**
  * This global and the helpers that use it are not thread-safe.
  *
  * If thread-safety is needed, the global could be made thread_local (given
  * that thread_local is supported on all architectures we support) or a
  * per-thread instance could be used in the multi-threaded test.
  */
 extern FastRandomContext g_insecure_rand_ctx;
 
 /**
  * Flag to make GetRand in random.h return the same number
  */
 extern bool g_mock_deterministic_tests;
 
 enum class SeedRand {
     ZEROS, //!< Seed with a compile time constant of zeros
     SEED,  //!< Call the Seed() helper
 };
 
 /**
  * Seed the given random ctx or use the seed passed in via an
  * environment var
  */
 void Seed(FastRandomContext &ctx);
 
 static inline void SeedInsecureRand(SeedRand seed = SeedRand::SEED) {
     if (seed == SeedRand::ZEROS) {
         g_insecure_rand_ctx = FastRandomContext(/* deterministic */ true);
     } else {
         Seed(g_insecure_rand_ctx);
     }
 }
 
 static inline uint32_t InsecureRand32() {
     return g_insecure_rand_ctx.rand32();
 }
 static inline uint160 InsecureRand160() {
     return g_insecure_rand_ctx.rand160();
 }
 static inline uint256 InsecureRand256() {
     return g_insecure_rand_ctx.rand256();
 }
 static inline uint64_t InsecureRandBits(int bits) {
     return g_insecure_rand_ctx.randbits(bits);
 }
 static inline uint64_t InsecureRandRange(uint64_t range) {
     return g_insecure_rand_ctx.randrange(range);
 }
 static inline bool InsecureRandBool() {
     return g_insecure_rand_ctx.randbool();
 }
 
 static constexpr Amount CENT(COIN / 100);
 
 extern std::vector<const char *> fixture_extra_args;
 
 /**
  * Basic testing setup.
  * This just configures logging, data dir and chain parameters.
  */
 struct BasicTestingSetup {
     ECCVerifyHandle globalVerifyHandle;
     node::NodeContext m_node;
 
     explicit BasicTestingSetup(
         const std::string &chainName = CBaseChainParams::MAIN,
         const std::vector<const char *> &extra_args = {});
     ~BasicTestingSetup();
 
     const fs::path m_path_root;
     ArgsManager m_args;
 };
 
 /**
  * Testing setup that performs all steps up until right before
  * ChainstateManager gets initialized. Meant for testing ChainstateManager
  * initialization behaviour.
  */
 struct ChainTestingSetup : public BasicTestingSetup {
     node::CacheSizes m_cache_sizes{};
 
     explicit ChainTestingSetup(
         const std::string &chainName = CBaseChainParams::MAIN,
         const std::vector<const char *> &extra_args = {});
     ~ChainTestingSetup();
 };
 
 /**
  * Testing setup that configures a complete environment.
  */
 struct TestingSetup : public ChainTestingSetup {
     bool m_coins_db_in_memory{true};
     bool m_block_tree_db_in_memory{true};
 
     void LoadVerifyActivateChainstate(const Config &config);
 
     explicit TestingSetup(const std::string &chainName = CBaseChainParams::MAIN,
                           const std::vector<const char *> &extra_args = {},
                           const bool coins_db_in_memory = true,
                           const bool block_tree_db_in_memory = true);
 };
 
 /** Identical to TestingSetup, but chain set to regtest */
 struct RegTestingSetup : public TestingSetup {
     RegTestingSetup() : TestingSetup{CBaseChainParams::REGTEST} {}
 };
 
 class CBlock;
 class Chainstate;
 class CMutableTransaction;
 class CScript;
 
 /**
  * Testing fixture that pre-creates a 100-block REGTEST-mode block chain
  */
 struct TestChain100Setup : public TestingSetup {
     TestChain100Setup(const std::string &chain_name = CBaseChainParams::REGTEST,
                       const std::vector<const char *> &extra_args = {},
                       const bool coins_db_in_memory = true,
                       const bool block_tree_db_in_memory = true);
 
     /**
      * Create a new block with just given transactions, coinbase paying to
      * scriptPubKey, and try to add it to the current chain.
      * If no chainstate is specified, default to the active.
      */
     CBlock CreateAndProcessBlock(const std::vector<CMutableTransaction> &txns,
                                  const CScript &scriptPubKey,
                                  Chainstate *chainstate = nullptr);
 
     /**
      * Create a new block with just given transactions, coinbase paying to
      * scriptPubKey.
      */
     CBlock CreateBlock(const std::vector<CMutableTransaction> &txns,
                        const CScript &scriptPubKey, Chainstate &chainstate);
 
     //! Mine a series of new blocks on the active chain.
     void mineBlocks(int num_blocks);
 
     /**
      * Create a transaction and submit to the mempool.
      *
      * @param input_transaction  The transaction to spend
      * @param input_vout         The vout to spend from the input_transaction
      * @param input_height       The height of the block that included the
      *                           input_transaction
      * @param input_signing_key  The key to spend the input_transaction
      * @param output_destination Where to send the output
      * @param output_amount      How much to send
      * @param submit             Whether or not to submit to mempool
      */
     CMutableTransaction CreateValidMempoolTransaction(
         CTransactionRef input_transaction, int input_vout, int input_height,
         CKey input_signing_key, CScript output_destination,
         Amount output_amount = COIN, bool submit = true);
 
     ~TestChain100Setup();
 
     // For convenience, coinbase transactions.
     std::vector<CTransactionRef> m_coinbase_txns;
     // private/public key needed to spend coinbase transactions.
     CKey coinbaseKey;
 };
 
+/**
+ * Make a test setup that has disk access to the debug.log file disabled. Can
+ * be used in "hot loops", for example fuzzing or benchmarking.
+ */
+template <class T = const BasicTestingSetup>
+std::unique_ptr<T>
+MakeNoLogFileContext(const std::string &chain_name = CBaseChainParams::REGTEST,
+                     const std::vector<const char *> &extra_args = {}) {
+    const std::vector<const char *> arguments = Cat(
+        {
+            "-nodebuglogfile",
+            "-nodebug",
+        },
+        extra_args);
+
+    return std::make_unique<T>(chain_name, arguments);
+}
+
 struct TestMemPoolEntryHelper {
     // Default values
     Amount nFee;
     int64_t nTime;
     unsigned int nHeight;
     bool spendsCoinbase;
     unsigned int nSigChecks;
     uint64_t entryId = 0;
 
     TestMemPoolEntryHelper()
         : nFee(), nTime(0), nHeight(1), spendsCoinbase(false), nSigChecks(1) {}
 
     CTxMemPoolEntryRef FromTx(const CMutableTransaction &tx) const;
     CTxMemPoolEntryRef FromTx(const CTransactionRef &tx) const;
 
     // Change the default value
     TestMemPoolEntryHelper &Fee(Amount _fee) {
         nFee = _fee;
         return *this;
     }
     TestMemPoolEntryHelper &Time(int64_t _time) {
         nTime = _time;
         return *this;
     }
     TestMemPoolEntryHelper &Height(unsigned int _height) {
         nHeight = _height;
         return *this;
     }
     TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) {
         spendsCoinbase = _flag;
         return *this;
     }
     TestMemPoolEntryHelper &SigChecks(unsigned int _nSigChecks) {
         nSigChecks = _nSigChecks;
         return *this;
     }
     TestMemPoolEntryHelper &EntryId(uint64_t _entryId) {
         entryId = _entryId;
         return *this;
     }
 };
 
 enum class ScriptError;
 
 // define implicit conversions here so that these types may be used in
 // BOOST_*_EQUAL
 std::ostream &operator<<(std::ostream &os, const uint256 &num);
 std::ostream &operator<<(std::ostream &os, const ScriptError &err);
 
 CBlock getBlock13b8a();
 
 /**
  * BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
  * Use as
  * BOOST_CHECK_EXCEPTION(code that throws, exception type, HasReason("foo"));
  */
 class HasReason {
 public:
     explicit HasReason(const std::string &reason) : m_reason(reason) {}
     bool operator()(const std::exception &e) const {
         return std::string(e.what()).find(m_reason) != std::string::npos;
     };
 
 private:
     const std::string m_reason;
 };
 
 #endif // BITCOIN_TEST_UTIL_SETUP_COMMON_H