|
| 1 | +// Copyright (c) 2011-2019 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 <policy/policy.h> |
| 7 | +#include <txmempool.h> |
| 8 | + |
| 9 | +#include <vector> |
| 10 | + |
| 11 | +static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) |
| 12 | +{ |
| 13 | + int64_t nTime = 0; |
| 14 | + unsigned int nHeight = 1; |
| 15 | + bool spendsCoinbase = false; |
| 16 | + unsigned int sigOpCost = 4; |
| 17 | + LockPoints lp; |
| 18 | + pool.addUnchecked(CTxMemPoolEntry(tx, 1000, nTime, nHeight, spendsCoinbase, sigOpCost, lp)); |
| 19 | +} |
| 20 | + |
| 21 | +struct Available { |
| 22 | + CTransactionRef ref; |
| 23 | + size_t vin_left{0}; |
| 24 | + size_t tx_count; |
| 25 | + Available(CTransactionRef& ref, size_t tx_count) : ref(ref), tx_count(tx_count){} |
| 26 | + Available& operator=(Available other) { |
| 27 | + ref = other.ref; |
| 28 | + vin_left = other.vin_left; |
| 29 | + tx_count = other.tx_count; |
| 30 | + return *this; |
| 31 | + } |
| 32 | +}; |
| 33 | + |
| 34 | +static void ComplexMemPool(benchmark::State& state) |
| 35 | +{ |
| 36 | + FastRandomContext det_rand{true}; |
| 37 | + std::vector<Available> available_coins; |
| 38 | + std::vector<CTransactionRef> ordered_coins; |
| 39 | + // Create some base transactions |
| 40 | + size_t tx_counter = 1; |
| 41 | + for (auto x = 0; x < 100; ++x) { |
| 42 | + CMutableTransaction tx = CMutableTransaction(); |
| 43 | + tx.vin.resize(1); |
| 44 | + tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter); |
| 45 | + tx.vin[0].scriptWitness.stack.push_back(CScriptNum(x).getvch()); |
| 46 | + tx.vout.resize(det_rand.randrange(10)+2); |
| 47 | + for (auto& out : tx.vout) { |
| 48 | + out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL; |
| 49 | + out.nValue = 10 * COIN; |
| 50 | + } |
| 51 | + ordered_coins.emplace_back(MakeTransactionRef(tx)); |
| 52 | + available_coins.emplace_back(ordered_coins.back(), tx_counter++); |
| 53 | + } |
| 54 | + for (auto x = 0; x < 800 && !available_coins.empty(); ++x) { |
| 55 | + CMutableTransaction tx = CMutableTransaction(); |
| 56 | + size_t n_ancestors = det_rand.randrange(10)+1; |
| 57 | + for (size_t ancestor = 0; ancestor < n_ancestors && !available_coins.empty(); ++ancestor){ |
| 58 | + size_t idx = det_rand.randrange(available_coins.size()); |
| 59 | + Available coin = available_coins[idx]; |
| 60 | + uint256 hash = coin.ref->GetHash(); |
| 61 | + // biased towards taking just one ancestor, but maybe more |
| 62 | + size_t n_to_take = det_rand.randrange(2) == 0 ? 1 : 1+det_rand.randrange(coin.ref->vout.size() - coin.vin_left); |
| 63 | + for (size_t i = 0; i < n_to_take; ++i) { |
| 64 | + tx.vin.emplace_back(); |
| 65 | + tx.vin.back().prevout = COutPoint(hash, coin.vin_left++); |
| 66 | + tx.vin.back().scriptSig = CScript() << coin.tx_count; |
| 67 | + tx.vin.back().scriptWitness.stack.push_back(CScriptNum(coin.tx_count).getvch()); |
| 68 | + } |
| 69 | + if (coin.vin_left == coin.ref->vin.size()) { |
| 70 | + coin = available_coins.back(); |
| 71 | + available_coins.pop_back(); |
| 72 | + } |
| 73 | + tx.vout.resize(det_rand.randrange(10)+2); |
| 74 | + for (auto& out : tx.vout) { |
| 75 | + out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL; |
| 76 | + out.nValue = 10 * COIN; |
| 77 | + } |
| 78 | + } |
| 79 | + ordered_coins.emplace_back(MakeTransactionRef(tx)); |
| 80 | + available_coins.emplace_back(ordered_coins.back(), tx_counter++); |
| 81 | + } |
| 82 | + CTxMemPool pool; |
| 83 | + LOCK2(cs_main, pool.cs); |
| 84 | + while (state.KeepRunning()) { |
| 85 | + for (auto& tx : ordered_coins) { |
| 86 | + AddTx(tx, pool); |
| 87 | + } |
| 88 | + pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); |
| 89 | + pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front())); |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +BENCHMARK(ComplexMemPool, 1); |
0 commit comments