diff options
Diffstat (limited to 'src/test/util')
-rw-r--r-- | src/test/util/blockfilter.cpp | 9 | ||||
-rw-r--r-- | src/test/util/blockfilter.h | 6 | ||||
-rw-r--r-- | src/test/util/chainstate.h | 2 | ||||
-rw-r--r-- | src/test/util/mining.cpp | 48 | ||||
-rw-r--r-- | src/test/util/mining.h | 12 | ||||
-rw-r--r-- | src/test/util/net.cpp | 3 | ||||
-rw-r--r-- | src/test/util/poolresourcetester.h | 129 | ||||
-rw-r--r-- | src/test/util/setup_common.cpp | 66 | ||||
-rw-r--r-- | src/test/util/setup_common.h | 44 | ||||
-rw-r--r-- | src/test/util/txmempool.cpp | 4 |
10 files changed, 275 insertions, 48 deletions
diff --git a/src/test/util/blockfilter.cpp b/src/test/util/blockfilter.cpp index ec703c6a7b..a806844e34 100644 --- a/src/test/util/blockfilter.cpp +++ b/src/test/util/blockfilter.cpp @@ -8,20 +8,19 @@ #include <node/blockstorage.h> #include <validation.h> -using node::ReadBlockFromDisk; -using node::UndoReadFromDisk; +using node::BlockManager; -bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter) +bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const BlockManager& blockman) { LOCK(::cs_main); CBlock block; - if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) { + if (!blockman.ReadBlockFromDisk(block, block_index.GetBlockPos())) { return false; } CBlockUndo block_undo; - if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) { + if (block_index.nHeight > 0 && !blockman.UndoReadFromDisk(block_undo, block_index)) { return false; } diff --git a/src/test/util/blockfilter.h b/src/test/util/blockfilter.h index 79d11dcad8..789ce5d3aa 100644 --- a/src/test/util/blockfilter.h +++ b/src/test/util/blockfilter.h @@ -6,8 +6,12 @@ #define BITCOIN_TEST_UTIL_BLOCKFILTER_H #include <blockfilter.h> + class CBlockIndex; +namespace node { +class BlockManager; +} -bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter); +bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const node::BlockManager& blockman); #endif // BITCOIN_TEST_UTIL_BLOCKFILTER_H diff --git a/src/test/util/chainstate.h b/src/test/util/chainstate.h index e664435e03..bf8f8b5819 100644 --- a/src/test/util/chainstate.h +++ b/src/test/util/chainstate.h @@ -6,12 +6,12 @@ #define BITCOIN_TEST_UTIL_CHAINSTATE_H #include <clientversion.h> -#include <fs.h> #include <logging.h> #include <node/context.h> #include <node/utxo_snapshot.h> #include <rpc/blockchain.h> #include <test/util/setup_common.h> +#include <util/fs.h> #include <validation.h> #include <univalue.h> diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp index 0df1db84c4..51f4b89512 100644 --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -6,19 +6,22 @@ #include <chainparams.h> #include <consensus/merkle.h> +#include <consensus/validation.h> #include <key_io.h> #include <node/context.h> #include <pow.h> +#include <primitives/transaction.h> #include <script/standard.h> #include <test/util/script.h> #include <util/check.h> #include <validation.h> +#include <validationinterface.h> #include <versionbits.h> using node::BlockAssembler; using node::NodeContext; -CTxIn generatetoaddress(const NodeContext& node, const std::string& address) +COutPoint generatetoaddress(const NodeContext& node, const std::string& address) { const auto dest = DecodeDestination(address); assert(IsValidDestination(dest)); @@ -58,19 +61,52 @@ std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const return ret; } -CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) +COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) { auto block = PrepareBlock(node, coinbase_scriptPubKey); + auto valid = MineBlock(node, block); + assert(!valid.IsNull()); + return valid; +} + +struct BlockValidationStateCatcher : public CValidationInterface { + const uint256 m_hash; + std::optional<BlockValidationState> m_state; + BlockValidationStateCatcher(const uint256& hash) + : m_hash{hash}, + m_state{} {} + +protected: + void BlockChecked(const CBlock& block, const BlockValidationState& state) override + { + if (block.GetHash() != m_hash) return; + m_state = state; + } +}; + +COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block) +{ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { ++block->nNonce; assert(block->nNonce); } - bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, true, nullptr)}; - assert(processed); - - return CTxIn{block->vtx[0]->GetHash(), 0}; + auto& chainman{*Assert(node.chainman)}; + const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()); + bool new_block; + BlockValidationStateCatcher bvsc{block->GetHash()}; + RegisterValidationInterface(&bvsc); + const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)}; + const bool duplicate{!new_block && processed}; + assert(!duplicate); + UnregisterValidationInterface(&bvsc); + SyncWithValidationInterfaceQueue(); + const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; + assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight())); + + if (was_valid) return {block->vtx[0]->GetHash(), 0}; + return {}; } std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey, diff --git a/src/test/util/mining.h b/src/test/util/mining.h index 70b1f7b3fb..3f071257f1 100644 --- a/src/test/util/mining.h +++ b/src/test/util/mining.h @@ -13,8 +13,8 @@ class CBlock; class CChainParams; +class COutPoint; class CScript; -class CTxIn; namespace node { struct NodeContext; } // namespace node @@ -23,7 +23,13 @@ struct NodeContext; std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params); /** Returns the generated coin */ -CTxIn MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey); +COutPoint MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey); + +/** + * Returns the generated coin (or Null if the block was invalid). + * It is recommended to call RegenerateCommitments before mining the block to avoid merkle tree mismatches. + **/ +COutPoint MineBlock(const node::NodeContext&, std::shared_ptr<CBlock>& block); /** Prepare a block to be mined */ std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey); @@ -31,6 +37,6 @@ std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext& node, const CScrip const node::BlockAssembler::Options& assembler_options); /** RPC-like helper function, returns the generated coin */ -CTxIn generatetoaddress(const node::NodeContext&, const std::string& address); +COutPoint generatetoaddress(const node::NodeContext&, const std::string& address); #endif // BITCOIN_TEST_UTIL_MINING_H diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 070a6a1c50..3f72384b3b 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -66,7 +66,7 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_by { assert(node.ReceiveMsgBytes(msg_bytes, complete)); if (complete) { - node.MarkReceivedMsgsForProcessing(nReceiveFloodSize); + node.MarkReceivedMsgsForProcessing(); } } @@ -84,6 +84,7 @@ bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) con std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context) { std::vector<NodeEvictionCandidate> candidates; + candidates.reserve(n_candidates); for (int id = 0; id < n_candidates; ++id) { candidates.push_back({ /*id=*/id, diff --git a/src/test/util/poolresourcetester.h b/src/test/util/poolresourcetester.h new file mode 100644 index 0000000000..93f62eb2a9 --- /dev/null +++ b/src/test/util/poolresourcetester.h @@ -0,0 +1,129 @@ +// Copyright (c) 2022 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_POOLRESOURCETESTER_H +#define BITCOIN_TEST_UTIL_POOLRESOURCETESTER_H + +#include <support/allocators/pool.h> + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <vector> + +/** + * Helper to get access to private parts of PoolResource. Used in unit tests and in the fuzzer + */ +class PoolResourceTester +{ + struct PtrAndBytes { + uintptr_t ptr; + std::size_t size; + + PtrAndBytes(const void* p, std::size_t s) + : ptr(reinterpret_cast<uintptr_t>(p)), size(s) + { + } + + /** + * defines a sort ordering by the pointer value + */ + friend bool operator<(PtrAndBytes const& a, PtrAndBytes const& b) + { + return a.ptr < b.ptr; + } + }; + +public: + /** + * Extracts the number of elements per freelist + */ + template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES> + static std::vector<std::size_t> FreeListSizes(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource) + { + auto sizes = std::vector<std::size_t>(); + for (const auto* ptr : resource.m_free_lists) { + size_t size = 0; + while (ptr != nullptr) { + ++size; + ptr = ptr->m_next; + } + sizes.push_back(size); + } + return sizes; + } + + /** + * How many bytes are still available from the last allocated chunk + */ + template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES> + static std::size_t AvailableMemoryFromChunk(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource) + { + return resource.m_available_memory_end - resource.m_available_memory_it; + } + + /** + * Once all blocks are given back to the resource, tests that the freelists are consistent: + * + * * All data in the freelists must come from the chunks + * * Memory doesn't overlap + * * Each byte in the chunks can be accounted for in either the freelist or as available bytes. + */ + template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES> + static void CheckAllDataAccountedFor(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource) + { + // collect all free blocks by iterating all freelists + std::vector<PtrAndBytes> free_blocks; + for (std::size_t freelist_idx = 0; freelist_idx < resource.m_free_lists.size(); ++freelist_idx) { + std::size_t bytes = freelist_idx * resource.ELEM_ALIGN_BYTES; + auto* ptr = resource.m_free_lists[freelist_idx]; + while (ptr != nullptr) { + free_blocks.emplace_back(ptr, bytes); + ptr = ptr->m_next; + } + } + // also add whatever has not yet been used for blocks + auto num_available_bytes = resource.m_available_memory_end - resource.m_available_memory_it; + if (num_available_bytes > 0) { + free_blocks.emplace_back(resource.m_available_memory_it, num_available_bytes); + } + + // collect all chunks + std::vector<PtrAndBytes> chunks; + for (const std::byte* ptr : resource.m_allocated_chunks) { + chunks.emplace_back(ptr, resource.ChunkSizeBytes()); + } + + // now we have all the data from all freelists on the one hand side, and all chunks on the other hand side. + // To check if all of them match, sort by address and iterate. + std::sort(free_blocks.begin(), free_blocks.end()); + std::sort(chunks.begin(), chunks.end()); + + auto chunk_it = chunks.begin(); + auto chunk_ptr_remaining = chunk_it->ptr; + auto chunk_size_remaining = chunk_it->size; + for (const auto& free_block : free_blocks) { + if (chunk_size_remaining == 0) { + assert(chunk_it != chunks.end()); + ++chunk_it; + assert(chunk_it != chunks.end()); + chunk_ptr_remaining = chunk_it->ptr; + chunk_size_remaining = chunk_it->size; + } + assert(free_block.ptr == chunk_ptr_remaining); // ensure addresses match + assert(free_block.size <= chunk_size_remaining); // ensure no overflow + assert((free_block.ptr & (resource.ELEM_ALIGN_BYTES - 1)) == 0); // ensure correct alignment + chunk_ptr_remaining += free_block.size; + chunk_size_remaining -= free_block.size; + } + // ensure we are at the end of the chunks + assert(chunk_ptr_remaining == chunk_it->ptr + chunk_it->size); + ++chunk_it; + assert(chunk_it == chunks.end()); + assert(chunk_size_remaining == 0); + } +}; + +#endif // BITCOIN_TEST_UTIL_POOLRESOURCETESTER_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 58593c9d5b..93a60db832 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -9,6 +9,7 @@ #include <addrman.h> #include <banman.h> #include <chainparams.h> +#include <common/system.h> #include <common/url.h> #include <consensus/consensus.h> #include <consensus/params.h> @@ -23,6 +24,7 @@ #include <node/blockstorage.h> #include <node/chainstate.h> #include <node/context.h> +#include <node/kernel_notifications.h> #include <node/mempool_args.h> #include <node/miner.h> #include <node/validation_cache_args.h> @@ -42,6 +44,7 @@ #include <timedata.h> #include <txdb.h> #include <txmempool.h> +#include <util/chaintype.h> #include <util/strencodings.h> #include <util/string.h> #include <util/thread.h> @@ -60,7 +63,9 @@ using kernel::ValidationCacheSizes; using node::ApplyArgsManOptions; using node::BlockAssembler; +using node::BlockManager; using node::CalculateCacheSizes; +using node::KernelNotifications; using node::LoadChainstate; using node::RegenerateCommitments; using node::VerifyLoadedChainstate; @@ -97,7 +102,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) return os; } -BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args) +BasicTestingSetup::BasicTestingSetup(const ChainType chainType, const std::vector<const char*>& extra_args) : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / g_insecure_rand_ctx_temp_path.rand256().ToString()}, m_args{} { @@ -131,7 +136,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve throw std::runtime_error{error}; } } - SelectParams(chainName); + SelectParams(chainType); SeedInsecureRand(); if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN); InitLogging(*m_node.args); @@ -152,6 +157,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve noui_connect(); noui_connected = true; } + node::g_indexes_ready_to_sync = true; } BasicTestingSetup::~BasicTestingSetup() @@ -162,8 +168,8 @@ BasicTestingSetup::~BasicTestingSetup() gArgs.ClearArgs(); } -ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args) - : BasicTestingSetup(chainName, extra_args) +ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vector<const char*>& extra_args) + : BasicTestingSetup(chainType, extra_args) { const CChainParams& chainparams = Params(); @@ -173,18 +179,25 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); }); GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler); - m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args)); + m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES); m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node)); m_cache_sizes = CalculateCacheSizes(m_args); + m_node.notifications = std::make_unique<KernelNotifications>(); + const ChainstateManager::Options chainman_opts{ .chainparams = chainparams, .datadir = m_args.GetDataDirNet(), .adjusted_time_callback = GetAdjustedTime, .check_block_index = true, + .notifications = *m_node.notifications, + }; + const BlockManager::Options blockman_opts{ + .chainparams = chainman_opts.chainparams, + .blocks_dir = m_args.GetBlocksDirPath(), }; - m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, node::BlockManager::Options{}); + m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, blockman_opts); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(DBParams{ .path = m_args.GetDataDirNet() / "blocks" / "index", .cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db), @@ -210,7 +223,7 @@ ChainTestingSetup::~ChainTestingSetup() m_node.chainman.reset(); } -void TestingSetup::LoadVerifyActivateChainstate() +void ChainTestingSetup::LoadVerifyActivateChainstate() { auto& chainman{*Assert(m_node.chainman)}; node::ChainstateLoadOptions options; @@ -236,14 +249,14 @@ void TestingSetup::LoadVerifyActivateChainstate() } TestingSetup::TestingSetup( - const std::string& chainName, + const ChainType chainType, const std::vector<const char*>& extra_args, const bool coins_db_in_memory, const bool block_tree_db_in_memory) - : ChainTestingSetup(chainName, extra_args), - m_coins_db_in_memory(coins_db_in_memory), - m_block_tree_db_in_memory(block_tree_db_in_memory) + : ChainTestingSetup(chainType, extra_args) { + m_coins_db_in_memory = coins_db_in_memory; + m_block_tree_db_in_memory = block_tree_db_in_memory; // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); @@ -267,11 +280,11 @@ TestingSetup::TestingSetup( } TestChain100Setup::TestChain100Setup( - const std::string& chain_name, + const ChainType chain_type, const std::vector<const char*>& extra_args, const bool coins_db_in_memory, const bool block_tree_db_in_memory) - : TestingSetup{CBaseChainParams::REGTEST, extra_args, coins_db_in_memory, block_tree_db_in_memory} + : TestingSetup{ChainType::REGTEST, extra_args, coins_db_in_memory, block_tree_db_in_memory} { SetMockTime(1598887952); constexpr std::array<unsigned char, 32> vchKey = { @@ -432,6 +445,33 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex return mempool_transactions; } +void TestChain100Setup::MockMempoolMinFee(const CFeeRate& target_feerate) +{ + LOCK2(cs_main, m_node.mempool->cs); + // Transactions in the mempool will affect the new minimum feerate. + assert(m_node.mempool->size() == 0); + // The target feerate cannot be too low... + // ...otherwise the transaction's feerate will need to be negative. + assert(target_feerate > m_node.mempool->m_incremental_relay_feerate); + // ...otherwise this is not meaningful. The feerate policy uses the maximum of both feerates. + assert(target_feerate > m_node.mempool->m_min_relay_feerate); + + // Manually create an invalid transaction. Manually set the fee in the CTxMemPoolEntry to + // achieve the exact target feerate. + CMutableTransaction mtx = CMutableTransaction(); + mtx.vin.push_back(CTxIn{COutPoint{g_insecure_rand_ctx.rand256(), 0}}); + mtx.vout.push_back(CTxOut(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE)))); + const auto tx{MakeTransactionRef(mtx)}; + LockPoints lp; + // The new mempool min feerate is equal to the removed package's feerate + incremental feerate. + const auto tx_fee = target_feerate.GetFee(GetVirtualTransactionSize(*tx)) - + m_node.mempool->m_incremental_relay_feerate.GetFee(GetVirtualTransactionSize(*tx)); + m_node.mempool->addUnchecked(CTxMemPoolEntry(tx, /*fee=*/tx_fee, + /*time=*/0, /*entry_height=*/1, + /*spends_coinbase=*/true, /*sigops_cost=*/1, lp)); + m_node.mempool->TrimToSize(0); + assert(m_node.mempool->GetMinFee() == target_feerate); +} /** * @returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) * with 9 txs. diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 8874db7e75..b7429df02c 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -5,24 +5,25 @@ #ifndef BITCOIN_TEST_UTIL_SETUP_COMMON_H #define BITCOIN_TEST_UTIL_SETUP_COMMON_H -#include <chainparamsbase.h> -#include <fs.h> +#include <common/args.h> #include <key.h> #include <node/caches.h> -#include <node/context.h> +#include <node/context.h> // IWYU pragma: export #include <primitives/transaction.h> #include <pubkey.h> #include <random.h> #include <stdexcept> +#include <util/chaintype.h> #include <util/check.h> +#include <util/fs.h> #include <util/string.h> -#include <util/system.h> #include <util/vector.h> #include <functional> #include <type_traits> #include <vector> +class CFeeRate; class Chainstate; /** This is connected to the logger. Can be used to redirect logs to any other log */ @@ -79,7 +80,7 @@ static constexpr CAmount CENT{1000000}; struct BasicTestingSetup { node::NodeContext m_node; // keep as first member to be destructed last - explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {}); + explicit BasicTestingSetup(const ChainType chainType = ChainType::MAIN, const std::vector<const char*>& extra_args = {}); ~BasicTestingSetup(); const fs::path m_path_root; @@ -92,21 +93,21 @@ struct BasicTestingSetup { */ struct ChainTestingSetup : public BasicTestingSetup { node::CacheSizes m_cache_sizes{}; + bool m_coins_db_in_memory{true}; + bool m_block_tree_db_in_memory{true}; - explicit ChainTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {}); + explicit ChainTestingSetup(const ChainType chainType = ChainType::MAIN, const std::vector<const char*>& extra_args = {}); ~ChainTestingSetup(); + + // Supplies a chainstate, if one is needed + void LoadVerifyActivateChainstate(); }; /** 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(); - explicit TestingSetup( - const std::string& chainName = CBaseChainParams::MAIN, + const ChainType chainType = ChainType::MAIN, const std::vector<const char*>& extra_args = {}, const bool coins_db_in_memory = true, const bool block_tree_db_in_memory = true); @@ -115,7 +116,7 @@ struct TestingSetup : public ChainTestingSetup { /** Identical to TestingSetup, but chain set to regtest */ struct RegTestingSetup : public TestingSetup { RegTestingSetup() - : TestingSetup{CBaseChainParams::REGTEST} {} + : TestingSetup{ChainType::REGTEST} {} }; class CBlock; @@ -127,7 +128,7 @@ class CScript; */ struct TestChain100Setup : public TestingSetup { TestChain100Setup( - const std::string& chain_name = CBaseChainParams::REGTEST, + const ChainType chain_type = ChainType::REGTEST, const std::vector<const char*>& extra_args = {}, const bool coins_db_in_memory = true, const bool block_tree_db_in_memory = true); @@ -185,6 +186,17 @@ struct TestChain100Setup : public TestingSetup { */ std::vector<CTransactionRef> PopulateMempool(FastRandomContext& det_rand, size_t num_transactions, bool submit); + /** Mock the mempool minimum feerate by adding a transaction and calling TrimToSize(0), + * simulating the mempool "reaching capacity" and evicting by descendant feerate. Note that + * this clears the mempool, and the new minimum feerate will depend on the maximum feerate of + * transactions removed, so this must be called while the mempool is empty. + * + * @param target_feerate The new mempool minimum feerate after this function returns. + * Must be above max(incremental feerate, min relay feerate), + * or 1sat/vB with default settings. + */ + void MockMempoolMinFee(const CFeeRate& target_feerate); + std::vector<CTransactionRef> m_coinbase_txns; // For convenience, coinbase transactions CKey coinbaseKey; // private/public key needed to spend coinbase transactions }; @@ -194,7 +206,7 @@ struct TestChain100Setup : public TestingSetup { * 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 = {}) +std::unique_ptr<T> MakeNoLogFileContext(const ChainType chain_type = ChainType::REGTEST, const std::vector<const char*>& extra_args = {}) { const std::vector<const char*> arguments = Cat( { @@ -203,7 +215,7 @@ std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseCha }, extra_args); - return std::make_unique<T>(chain_name, arguments); + return std::make_unique<T>(chain_type, arguments); } CBlock getBlock13b8a(); diff --git a/src/test/util/txmempool.cpp b/src/test/util/txmempool.cpp index 1873cf5ec8..4797d9c310 100644 --- a/src/test/util/txmempool.cpp +++ b/src/test/util/txmempool.cpp @@ -22,8 +22,8 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node) // chainparams.DefaultConsistencyChecks for tests .check_ratio = 1, }; - const auto err{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)}; - Assert(!err); + const auto result{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)}; + Assert(result); return mempool_opts; } |