mempool_ephemeral_spends.cpp raw

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