mempool_ephemeral_spends.cpp raw

   1  // Copyright (c) 2011-2022 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <bench/bench.h>
   6  #include <consensus/amount.h>
   7  #include <kernel/cs_main.h>
   8  #include <policy/ephemeral_policy.h>
   9  #include <policy/policy.h>
  10  #include <primitives/transaction.h>
  11  #include <script/script.h>
  12  #include <sync.h>
  13  #include <test/util/setup_common.h>
  14  #include <test/util/txmempool.h>
  15  #include <txmempool.h>
  16  #include <util/check.h>
  17  
  18  #include <cstdint>
  19  #include <memory>
  20  #include <vector>
  21  
  22  
  23  static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
  24  {
  25      int64_t nTime{0};
  26      unsigned int nHeight{1};
  27      uint64_t sequence{0};
  28      bool spendsCoinbase{false};
  29      unsigned int sigOpCost{4};
  30      uint64_t fee{0};
  31      LockPoints lp;
  32      AddToMempool(pool, CTxMemPoolEntry(
  33          tx, fee, nTime, nHeight, sequence,
  34          COIN_AGE_CACHE_ZERO,
  35          spendsCoinbase, /*extra_weight=*/0, sigOpCost, lp));
  36  }
  37  
  38  static void MempoolCheckEphemeralSpends(benchmark::Bench& bench)
  39  {
  40      const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
  41  
  42      int number_outputs{1000};
  43      if (bench.complexityN() > 1) {
  44          number_outputs = static_cast<int>(bench.complexityN());
  45      }
  46  
  47      // Tx with many outputs
  48      CMutableTransaction tx1;
  49      tx1.vin.resize(1);
  50      tx1.vout.resize(number_outputs);
  51      for (size_t i = 0; i < tx1.vout.size(); i++) {
  52          tx1.vout[i].scriptPubKey = CScript();
  53          // Each output progressively larger
  54          tx1.vout[i].nValue = i * CENT;
  55      }
  56  
  57      const auto& parent_txid = tx1.GetHash();
  58  
  59      // Spends all outputs of tx1, other details don't matter
  60      CMutableTransaction tx2;
  61      tx2.vin.resize(tx1.vout.size());
  62      for (size_t i = 0; i < tx2.vin.size(); i++) {
  63          tx2.vin[0].prevout.hash = parent_txid;
  64          tx2.vin[0].prevout.n = i;
  65      }
  66      tx2.vout.resize(1);
  67  
  68      CTxMemPool& pool = *Assert(testing_setup->m_node.mempool);
  69      LOCK2(cs_main, pool.cs);
  70      // Create transaction references outside the "hot loop"
  71      const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
  72      const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
  73  
  74      AddTx(tx1_r, pool);
  75  
  76      uint32_t iteration{0};
  77  
  78      TxValidationState dummy_state;
  79      Wtxid dummy_wtxid;
  80  
  81      bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
  82  
  83          CheckEphemeralSpends({tx2_r}, /*dust_relay_rate=*/CFeeRate(iteration * COIN / 10), pool, dummy_state, dummy_wtxid);
  84          iteration++;
  85      });
  86  }
  87  
  88  BENCHMARK(MempoolCheckEphemeralSpends, benchmark::PriorityLevel::HIGH);
  89