30std::vector<COutPoint> g_outpoints_coinbase_init_mature;
 
   36        lastRollingFeeUpdate = 
GetTime();
 
   37        blockSinceLastRollingFeeBump = 
true;
 
   41void initialize_tx_pool()
 
   43    static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
 
   44    g_setup = testing_setup.get();
 
   47    BlockAssembler::Options options;
 
   54            g_outpoints_coinbase_init_mature.push_back(prevout);
 
   61    std::set<COutPoint>& m_mempool_outpoints;
 
   63    explicit OutpointsUpdater(std::set<COutPoint>& r)
 
   64        : m_mempool_outpoints{r} {}
 
   71        for (uint32_t index{0}; index < tx.
info.
m_tx->vout.size(); ++index) {
 
   79        for (
const auto& input : tx->vin) {
 
   81            m_mempool_outpoints.insert(input.prevout);
 
   84        for (uint32_t index{0}; index < tx->vout.size(); ++index) {
 
   85            m_mempool_outpoints.erase(
COutPoint{tx->GetHash(), index});
 
   91    std::set<CTransactionRef>& m_added;
 
   93    explicit TransactionsDelta(std::set<CTransactionRef>& a)
 
  113                                  std::numeric_limits<
decltype(chainstate.
m_chain.
Tip()->
nTime)>::max());
 
  133    mempool_opts.check_ratio = 1;
 
  138    auto mempool{std::make_unique<CTxMemPool>(std::move(mempool_opts), error)};
 
  145std::unique_ptr<CTxMemPool> MakeEphemeralMempool(
const NodeContext& 
node)
 
  153    mempool_opts.require_standard = 
true;
 
  156    mempool_opts.min_relay_feerate = 
CFeeRate(0);
 
  160    auto mempool{std::make_unique<CTxMemPool>(std::move(mempool_opts), error)};
 
  170std::optional<COutPoint> GetChildEvictingPrevout(
const CTxMemPool& tx_pool)
 
  173    for (
const auto& tx_info : tx_pool.
infoAll()) {
 
  174        const auto& entry = *
Assert(tx_pool.
GetEntry(tx_info.tx->GetHash()));
 
  176        if (!dust_indexes.empty()) {
 
  177            const auto& children = entry.GetMemPoolChildrenConst();
 
  178            if (!children.empty()) {
 
  179                Assert(children.size() == 1);
 
  181                const auto& only_child = children.begin()->get().GetTx();
 
  182                for (
const auto& tx_input : only_child.vin) {
 
  183                    if (tx_input.prevout.hash != tx_info.tx->GetHash()) {
 
  184                        return tx_input.prevout;
 
  204    std::set<COutPoint> mempool_outpoints;
 
  205    std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
 
  206    for (
const auto& outpoint : g_outpoints_coinbase_init_mature) {
 
  207        Assert(mempool_outpoints.insert(outpoint).second);
 
  208        outpoints_value[outpoint] = 50 * 
COIN;
 
  211    auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
 
  212    node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
 
  214    auto tx_pool_{MakeEphemeralMempool(
node)};
 
  215    MockedTxPool& tx_pool = *
static_cast<MockedTxPool*
>(tx_pool_.get());
 
  217    chainstate.SetMempool(&tx_pool);
 
  221        Assert(!mempool_outpoints.empty());
 
  223        std::vector<CTransactionRef> txs;
 
  231        std::set<COutPoint> package_outpoints;
 
  232        while (txs.size() < num_txs) {
 
  234            txs.emplace_back([&] {
 
  241                bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
 
  242                const auto num_in = outpoint_to_rbf ? 2 :
 
  247                auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
 
  249                Assert((
int)outpoints.size() >= num_in && num_in > 0);
 
  252                for (
int i = 0; i < num_in; ++i) {
 
  255                    auto pop = outpoints.begin();
 
  257                    auto outpoint = *pop;
 
  259                    if (i == 0 && outpoint_to_rbf) {
 
  260                        outpoint = *outpoint_to_rbf;
 
  261                        outpoints.erase(outpoint);
 
  263                        outpoints.erase(pop);
 
  266                    amount_in += outpoints_value.at(outpoint);
 
  273                    tx_mut.
vin.push_back(in);
 
  277                const auto amount_out = (amount_in - amount_fee) / num_out;
 
  278                for (
int i = 0; i < num_out; ++i) {
 
  291                    for (
const auto& in : tx->vin) {
 
  295                    for (
size_t i = 0; i < tx->vout.size(); ++i) {
 
  296                        package_outpoints.emplace(tx->GetHash(), i);
 
  300                for (
size_t i = 0; i < tx->vout.size(); ++i) {
 
  301                    outpoints_value[
COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
 
  309                                   txs.back()->GetHash() :
 
  314            if (tx_pool.exists(txid)) {
 
  315                const auto tx_info{tx_pool.info(txid)};
 
  316                if (
GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate).empty()) {
 
  317                    tx_pool.PrioritiseTransaction(txid, delta);
 
  322        auto single_submit = txs.size() == 1;
 
  328                                   false, !single_submit));
 
  334            const bool expect_valid{result_package.m_state.IsValid()};
 
  338        node.validation_signals->SyncWithValidationInterfaceQueue();
 
  343    node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
 
  345    WITH_LOCK(
::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
 
  359    std::set<COutPoint> mempool_outpoints;
 
  360    std::unordered_map<COutPoint, CAmount, SaltedOutpointHasher> outpoints_value;
 
  361    for (
const auto& outpoint : g_outpoints_coinbase_init_mature) {
 
  362        Assert(mempool_outpoints.insert(outpoint).second);
 
  363        outpoints_value[outpoint] = 50 * 
COIN;
 
  366    auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
 
  367    node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
 
  370    MockedTxPool& tx_pool = *
static_cast<MockedTxPool*
>(tx_pool_.get());
 
  372    chainstate.SetMempool(&tx_pool);
 
  376        Assert(!mempool_outpoints.empty());
 
  378        std::vector<CTransactionRef> txs;
 
  382        std::set<COutPoint> package_outpoints;
 
  383        while (txs.size() < num_txs) {
 
  385            txs.emplace_back([&] {
 
  392                bool last_tx = num_txs > 1 && txs.size() == num_txs - 1;
 
  396                auto& outpoints = last_tx ? package_outpoints : mempool_outpoints;
 
  398                Assert(!outpoints.empty());
 
  401                for (
size_t i = 0; i < num_in; ++i) {
 
  404                    auto pop = outpoints.begin();
 
  406                    const auto outpoint = *pop;
 
  407                    outpoints.erase(pop);
 
  409                    amount_in += outpoints_value.at(outpoint);
 
  413                    const auto script_sig = 
CScript{};
 
  422                    tx_mut.
vin.push_back(in);
 
  428                    tx_mut.
vin.push_back(tx_mut.
vin.back());
 
  433                    tx_mut.
vin.emplace_back();
 
  445                const auto amount_out = (amount_in - amount_fee) / num_out;
 
  446                for (
int i = 0; i < num_out; ++i) {
 
  452                    for (
const auto& in : tx->vin) {
 
  457                    for (
size_t i = 0; i < tx->vout.size(); ++i) {
 
  458                        package_outpoints.emplace(tx->GetHash(), i);
 
  462                for (
size_t i = 0; i < tx->vout.size(); ++i) {
 
  463                    outpoints_value[
COutPoint(tx->GetHash(), i)] = tx->vout[i].nValue;
 
  473            tx_pool.RollingFeeUpdate();
 
  477                                   txs.back()->GetHash() :
 
  480            tx_pool.PrioritiseTransaction(txid, delta);
 
  484        std::set<CTransactionRef> added;
 
  485        auto txr = std::make_shared<TransactionsDelta>(added);
 
  486        node.validation_signals->RegisterSharedValidationInterface(txr);
 
  494        std::optional<CFeeRate> client_maxfeerate{};
 
  500                                    return ProcessNewPackage(chainstate, tx_pool, txs, single_submit, client_maxfeerate));
 
  505                                   false, !single_submit));
 
  508        node.validation_signals->SyncWithValidationInterfaceQueue();
 
  509        node.validation_signals->UnregisterSharedValidationInterface(txr);
 
  513            Assert(passed != added.empty());
 
  514            Assert(passed == res.m_state.IsValid());
 
  516                Assert(added.size() == 1);
 
  517                Assert(txs.back() == *added.begin());
 
  523            const bool expect_valid{result_package.m_state.IsValid()};
 
  527            Assert(result_package.m_tx_results.size() == txs.size() || result_package.m_tx_results.empty());
 
  533        if (tx_pool.m_opts.require_standard) {
 
  538    node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
 
  540    WITH_LOCK(
::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
 
int64_t CAmount
Amount in satoshis (Can be negative)
 
static constexpr CAmount COIN
The amount of satoshis in one BTC.
 
#define Assert(val)
Identity function.
 
int64_t GetMedianTimePast() const
 
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
 
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
 
An outpoint - a combination of a transaction hash and an index n into its vout.
 
Serialized script, used inside transaction inputs and outputs.
 
static const uint32_t CURRENT_VERSION
 
An input of a transaction.
 
CScriptWitness scriptWitness
Only serialized through CTransaction.
 
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
 
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
 
std::vector< TxMempoolInfo > infoAll() const
 
const CTxMemPoolEntry * GetEntry(const Txid &txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs)
 
An output of a transaction.
 
Implement this to subscribe to events generated in validation and mempool.
 
virtual void TransactionRemovedFromMempool(const CTransactionRef &tx, MemPoolRemovalReason reason, uint64_t mempool_sequence)
Notifies listeners of a transaction leaving mempool.
 
virtual void TransactionAddedToMempool(const NewMempoolTransactionInfo &tx, uint64_t mempool_sequence)
Notifies listeners of a transaction having been added to mempool.
 
Chainstate stores and provides an API to update our local knowledge of the current best chain.
 
CChain m_chain
The current chain of blockheaders we consult and build on.
 
T ConsumeIntegralInRange(T min, T max)
 
Generate a new block, without valid proof-of-work.
 
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
 
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
 
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
 
MemPoolRemovalReason
Reason why a transaction was removed from the mempool, this is passed to the notification signal.
 
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
 
unsigned int nBytesPerSigOp
 
std::vector< uint32_t > GetDust(const CTransaction &tx, CFeeRate dust_relay_rate)
Get the vout index numbers of all dust outputs.
 
static CTransactionRef MakeTransactionRef(Tx &&txIn)
 
std::shared_ptr< const CTransaction > CTransactionRef
 
A mutable version of CTransaction.
 
std::vector< CTxOut > vout
 
std::vector< std::vector< unsigned char > > stack
 
Testing setup that configures a complete environment.
 
const CTransactionRef m_tx
 
int64_t ancestor_count
The maximum allowed number of transactions in a package including the entry and its ancestors.
 
Options struct containing options for constructing a CTxMemPool.
 
CFeeRate dust_relay_feerate
 
NodeContext struct containing references to chain state and connection state.
 
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
 
std::unique_ptr< ChainstateManager > chainman
 
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
 
uint32_t ConsumeSequence(FuzzedDataProvider &fuzzed_data_provider) noexcept
 
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
 
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
 
COutPoint MineBlock(const NodeContext &node, const node::BlockAssembler::Options &assembler_options)
Returns the generated coin.
 
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
 
@ ZEROS
Seed with a compile time constant of zeros.
 
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TRUE_STACK
 
static const std::vector< std::vector< uint8_t > > P2WSH_EMPTY_TWO_STACK
 
static const CScript P2WSH_EMPTY
 
void CheckMempoolTRUCInvariants(const CTxMemPool &tx_pool)
For every transaction in tx_pool, check TRUC invariants:
 
CTxMemPool::Options MemPoolOptionsForTest(const NodeContext &node)
 
std::optional< std::string > CheckPackageMempoolAcceptResult(const Package &txns, const PackageMempoolAcceptResult &result, bool expect_valid, const CTxMemPool *mempool)
Check expected properties for every PackageMempoolAcceptResult, regardless of value.
 
void CheckMempoolEphemeralInvariants(const CTxMemPool &tx_pool)
Check that we never get into a state where an ephemeral dust transaction would be mined without the s...
 
#define EXCLUSIVE_LOCKS_REQUIRED(...)
 
static constexpr decltype(CTransaction::version) TRUC_VERSION
 
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
 
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
 
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
 
MempoolAcceptResult AcceptToMemoryPool(Chainstate &active_chainstate, const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept)
Try to add a transaction to the mempool.
 
FuzzedDataProvider & fuzzed_data_provider