#ifndef BITCOIN_TEST_UTIL_SETUP_COMMON_H
#define BITCOIN_TEST_UTIL_SETUP_COMMON_H
#include <common/args.h>
#include <kernel/caches.h>
#include <kernel/context.h>
#include <key.h>
#include <node/caches.h>
#include <node/context.h>
#include <optional>
#include <ostream>
#include <primitives/transaction.h>
#include <pubkey.h>
#include <stdexcept>
#include <test/util/random.h>
#include <util/chaintype.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/signalinterrupt.h>
#include <util/string.h>
#include <util/vector.h>
#include <functional>
#include <type_traits>
#include <vector>
class arith_uint256;
class CFeeRate;
class Chainstate;
class FastRandomContext;
class uint160;
class uint256;
extern const std::function<void(const std::string&)> G_TEST_LOG_FUN;
extern const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS;
extern const std::function<std::string()> G_TEST_GET_FULL_NAME;
static constexpr CAmount CENT{1000000};
void SetupCommonTestArgs(ArgsManager& argsman);
struct TestOpts {
std::vector<const char*> extra_args{};
bool coins_db_in_memory{true};
bool block_tree_db_in_memory{true};
bool setup_net{true};
bool setup_validation_interface{true};
bool min_validation_cache{false}; };
struct BasicTestingSetup {
util::SignalInterrupt m_interrupt;
node::NodeContext m_node;
FastRandomContext m_rng;
void SeedRandomForTest(SeedRand seed)
{
SeedRandomStateForTest(seed);
m_rng.Reseed(GetRandHash());
}
explicit BasicTestingSetup(const ChainType chainType = ChainType::MAIN, TestOpts = {});
~BasicTestingSetup();
fs::path m_path_root;
fs::path m_path_lock;
bool m_has_custom_datadir{false};
ArgsManager m_args;
};
struct ChainTestingSetup : public BasicTestingSetup {
kernel::CacheSizes m_kernel_cache_sizes{node::CalculateCacheSizes(m_args).kernel};
bool m_coins_db_in_memory{true};
bool m_block_tree_db_in_memory{true};
std::function<void()> m_make_chainman{};
explicit ChainTestingSetup(const ChainType chainType = ChainType::MAIN, TestOpts = {});
~ChainTestingSetup();
void LoadVerifyActivateChainstate();
};
struct TestingSetup : public ChainTestingSetup {
explicit TestingSetup(
const ChainType chainType = ChainType::MAIN,
TestOpts = {});
};
struct RegTestingSetup : public TestingSetup {
RegTestingSetup()
: TestingSetup{ChainType::REGTEST} {}
};
struct Testnet4Setup : public TestingSetup {
Testnet4Setup()
: TestingSetup{ChainType::TESTNET4} {}
};
class CBlock;
struct CMutableTransaction;
class CScript;
struct TestChain100Setup : public TestingSetup {
TestChain100Setup(
const ChainType chain_type = ChainType::REGTEST,
TestOpts = {});
CBlock CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
Chainstate* chainstate = nullptr);
CBlock CreateBlock(
const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
Chainstate& chainstate);
void mineBlocks(int num_blocks);
std::pair<CMutableTransaction, CAmount> CreateValidTransaction(const std::vector<CTransactionRef>& input_transactions,
const std::vector<COutPoint>& inputs,
int input_height,
const std::vector<CKey>& input_signing_keys,
const std::vector<CTxOut>& outputs,
const std::optional<CFeeRate>& feerate,
const std::optional<uint32_t>& fee_output);
CMutableTransaction CreateValidMempoolTransaction(const std::vector<CTransactionRef>& input_transactions,
const std::vector<COutPoint>& inputs,
int input_height,
const std::vector<CKey>& input_signing_keys,
const std::vector<CTxOut>& outputs,
bool submit = true);
CMutableTransaction CreateValidMempoolTransaction(CTransactionRef input_transaction,
uint32_t input_vout,
int input_height,
CKey input_signing_key,
CScript output_destination,
CAmount output_amount = CAmount(1 * COIN),
bool submit = true);
std::vector<CTransactionRef> PopulateMempool(FastRandomContext& det_rand, size_t num_transactions, bool submit);
void MockMempoolMinFee(const CFeeRate& target_feerate);
std::vector<CTransactionRef> m_coinbase_txns; CKey coinbaseKey; };
template <class T = const BasicTestingSetup>
std::unique_ptr<T> MakeNoLogFileContext(const ChainType chain_type = ChainType::REGTEST, TestOpts opts = {})
{
opts.extra_args = Cat(
{
"-nodebuglogfile",
"-nodebug",
},
opts.extra_args);
return std::make_unique<T>(chain_type, opts);
}
CBlock getBlock13b8a();
namespace std {
template <typename T> requires std::is_enum_v<T>
inline std::ostream& operator<<(std::ostream& os, const T& e)
{
return os << static_cast<std::underlying_type_t<T>>(e);
}
template <typename T>
inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& v)
{
return v ? os << *v
: os << "std::nullopt";
}
}
std::ostream& operator<<(std::ostream& os, const arith_uint256& num);
std::ostream& operator<<(std::ostream& os, const uint160& num);
std::ostream& operator<<(std::ostream& os, const uint256& num);
class HasReason
{
public:
explicit HasReason(std::string_view reason) : m_reason(reason) {}
bool operator()(std::string_view s) const { return s.find(m_reason) != std::string_view::npos; }
bool operator()(const std::exception& e) const { return (*this)(e.what()); }
private:
const std::string m_reason;
};
#endif