diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -50,6 +50,7 @@ gcs_filter.cpp lockedpool.cpp mempool_eviction.cpp + mempool_stress.cpp merkle_root.cpp prevector.cpp rollingbloom.cpp diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp new file mode 100644 --- /dev/null +++ b/src/bench/mempool_stress.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2011-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +#include + +static void AddTx(const CTransactionRef &tx, CTxMemPool &pool) + EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { + int64_t nTime = 0; + unsigned int nHeight = 1; + bool spendsCoinbase = false; + unsigned int sigOpCost = 4; + LockPoints lp; + pool.addUnchecked(CTxMemPoolEntry(tx, 1000 * SATOSHI, nTime, nHeight, + spendsCoinbase, sigOpCost, lp)); +} + +struct Available { + CTransactionRef ref; + size_t vin_left{0}; + size_t tx_count; + Available(CTransactionRef &_ref, size_t _tx_count) + : ref(_ref), tx_count(_tx_count) {} +}; + +static void ComplexMemPool(benchmark::State &state) { + FastRandomContext det_rand{true}; + std::vector available_coins; + std::vector ordered_coins; + // Create some base transactions + size_t tx_counter = 1; + for (auto x = 0; x < 100; ++x) { + CMutableTransaction tx = CMutableTransaction(); + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter); + tx.vout.resize(det_rand.randrange(10) + 2); + for (auto &out : tx.vout) { + out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL; + out.nValue = 10 * COIN; + } + ordered_coins.emplace_back(MakeTransactionRef(tx)); + available_coins.emplace_back(ordered_coins.back(), tx_counter++); + } + for (auto x = 0; x < 800 && !available_coins.empty(); ++x) { + CMutableTransaction tx = CMutableTransaction(); + size_t n_ancestors = det_rand.randrange(10) + 1; + for (size_t ancestor = 0; + ancestor < n_ancestors && !available_coins.empty(); ++ancestor) { + size_t idx = det_rand.randrange(available_coins.size()); + Available coin = available_coins[idx]; + TxId txid = coin.ref->GetId(); + // biased towards taking just one ancestor, but maybe more + size_t n_to_take = + det_rand.randrange(2) == 0 + ? 1 + : 1 + det_rand.randrange(coin.ref->vout.size() - + coin.vin_left); + for (size_t i = 0; i < n_to_take; ++i) { + tx.vin.emplace_back(); + tx.vin.back().prevout = COutPoint(txid, coin.vin_left++); + tx.vin.back().scriptSig = CScript() << coin.tx_count; + } + if (coin.vin_left == coin.ref->vin.size()) { + coin = available_coins.back(); + available_coins.pop_back(); + } + tx.vout.resize(det_rand.randrange(10) + 2); + for (auto &out : tx.vout) { + out.scriptPubKey = CScript() + << CScriptNum(tx_counter) << OP_EQUAL; + out.nValue = 10 * COIN; + } + } + ordered_coins.emplace_back(MakeTransactionRef(tx)); + available_coins.emplace_back(ordered_coins.back(), tx_counter++); + } + CTxMemPool pool; + LOCK2(cs_main, pool.cs); + while (state.KeepRunning()) { + for (auto &tx : ordered_coins) { + AddTx(tx, pool); + } + pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); + pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front())); + } +} + +BENCHMARK(ComplexMemPool, 1); diff --git a/src/psbt.h b/src/psbt.h --- a/src/psbt.h +++ b/src/psbt.h @@ -328,9 +328,6 @@ bool AddInput(const CTxIn &txin, PSBTInput &psbtin); bool AddOutput(const CTxOut &txout, const PSBTOutput &psbtout); PartiallySignedTransaction() {} - PartiallySignedTransaction(const PartiallySignedTransaction &psbt_in) - : tx(psbt_in.tx), inputs(psbt_in.inputs), outputs(psbt_in.outputs), - unknown(psbt_in.unknown) {} explicit PartiallySignedTransaction(const CMutableTransaction &txIn); /** * Finds the UTXO for a given input index