diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -15,6 +15,7 @@ bench/bench_bitcoin.cpp \ bench/bench.cpp \ bench/bench.h \ + bench/block_assemble.cpp \ bench/cashaddr.cpp \ bench/checkblock.cpp \ bench/checkqueue.cpp \ diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -37,6 +37,7 @@ base58.cpp bench.cpp bench_bitcoin.cpp + block_assemble.cpp cashaddr.cpp ccoins_caching.cpp checkblock.cpp diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp new file mode 100644 --- /dev/null +++ b/src/bench/block_assemble.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2011-2017 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 +#include +#include +#include +#include +#include + +#include + +static std::shared_ptr +PrepareBlock(const Config &config, const CScript &coinbase_scriptPubKey) { + auto block = + std::make_shared(BlockAssembler{config, ::g_mempool} + .CreateNewBlock(coinbase_scriptPubKey) + ->block); + + block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1; + block->hashMerkleRoot = BlockMerkleRoot(*block); + + return block; +} + +static CTxIn MineBlock(const Config &config, + const CScript &coinbase_scriptPubKey) { + auto block = PrepareBlock(config, coinbase_scriptPubKey); + + while (!CheckProofOfWork(block->GetHash(), block->nBits, + config.GetChainParams().GetConsensus())) { + ++block->nNonce; + assert(block->nNonce); + } + + bool processed = ProcessNewBlock(config, block, true, nullptr); + assert(processed); + + return CTxIn{block->vtx[0]->GetId(), 0}; +} + +static void AssembleBlock(benchmark::State &state) { + const Config &config = GetConfig(); + + const CScript redeemScript = CScript() << OP_DROP << OP_TRUE; + const CScript SCRIPT_PUB = + CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) + << OP_EQUAL; + + const CScript scriptSig = CScript() << std::vector(100, 0xff) + << ToByteVector(redeemScript); + + // Collect some loose transactions that spend the coinbases of our mined + // blocks + constexpr size_t NUM_BLOCKS{200}; + std::array txs; + for (size_t b = 0; b < NUM_BLOCKS; ++b) { + CMutableTransaction tx; + tx.vin.push_back(MineBlock(config, SCRIPT_PUB)); + tx.vin.back().scriptSig = scriptSig; + tx.vout.emplace_back(1337 * SATOSHI, SCRIPT_PUB); + if (NUM_BLOCKS - b >= COINBASE_MATURITY) { + txs.at(b) = MakeTransactionRef(tx); + } + } + + { + // Required for ::AcceptToMemoryPool. + LOCK(::cs_main); + + for (const auto &txr : txs) { + CValidationState vstate; + bool ret{::AcceptToMemoryPool(config, ::g_mempool, vstate, txr, + nullptr /* pfMissingInputs */, + false /* bypass_limits */, + /* nAbsurdFee */ Amount::zero())}; + assert(ret); + } + } + + while (state.KeepRunning()) { + PrepareBlock(config, SCRIPT_PUB); + } +} + +BENCHMARK(AssembleBlock, 700);