// Copyright (c) 2011-2018 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 #include #include #include #include #include #include static void DuplicateInputs(benchmark::State& state) { const CScript SCRIPT_PUB{CScript(OP_TRUE)}; // Switch to regtest so we can mine faster // Also segwit is active, so we can include witness transactions SelectParams(CBaseChainParams::REGTEST); InitScriptExecutionCache(); boost::thread_group thread_group; CScheduler scheduler; const CChainParams& chainparams = Params(); { LOCK(cs_main); ::pblocktree.reset(new CBlockTreeDB(1 << 20, true)); ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); } { thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler)); GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); LoadGenesisBlock(chainparams); CValidationState cvstate; ActivateBestChain(cvstate, chainparams); assert(::chainActive.Tip() != nullptr); const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())}; assert(witness_enabled); } CBlock block{}; CMutableTransaction coinbaseTx{}; CMutableTransaction naughtyTx{}; CBlockIndex* pindexPrev = ::chainActive.Tip(); assert(pindexPrev != nullptr); block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus()); block.nNonce = 0; auto nHeight = pindexPrev->nHeight + 1; // Make a coinbase TX coinbaseTx.vin.resize(1); coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB; coinbaseTx.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; naughtyTx.vout.resize(1); naughtyTx.vout[0].nValue = 0; naughtyTx.vout[0].scriptPubKey = SCRIPT_PUB; uint64_t n_inputs = (((MAX_BLOCK_SERIALIZED_SIZE / WITNESS_SCALE_FACTOR) - (CTransaction(coinbaseTx).GetTotalSize() + CTransaction(naughtyTx).GetTotalSize())) / 41) - 100; for (uint64_t x = 0; x < (n_inputs - 1); ++x) { naughtyTx.vin.emplace_back(GetRandHash(), 0, CScript(), 0); } naughtyTx.vin.emplace_back(naughtyTx.vin.back()); block.vtx.push_back(MakeTransactionRef(std::move(coinbaseTx))); block.vtx.push_back(MakeTransactionRef(std::move(naughtyTx))); block.hashMerkleRoot = BlockMerkleRoot(block); while (state.KeepRunning()) { CValidationState cvstate{}; assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false)); assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate"); } thread_group.interrupt_all(); thread_group.join_all(); GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().UnregisterBackgroundSignalScheduler(); } BENCHMARK(DuplicateInputs, 10);