duplicate_inputs.cpp
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 <chain.h> 7 #include <chainparams.h> 8 #include <consensus/consensus.h> 9 #include <consensus/merkle.h> 10 #include <consensus/validation.h> 11 #include <pow.h> 12 #include <primitives/block.h> 13 #include <primitives/transaction.h> 14 #include <random.h> 15 #include <script/script.h> 16 #include <sync.h> 17 #include <test/util/setup_common.h> 18 #include <uint256.h> 19 #include <validation.h> 20 21 #include <cassert> 22 #include <cstdint> 23 #include <memory> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 28 29 static void DuplicateInputs(benchmark::Bench& bench) 30 { 31 const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); 32 33 const CScript SCRIPT_PUB{CScript(OP_TRUE)}; 34 35 const CChainParams& chainparams = Params(); 36 37 CBlock block{}; 38 CMutableTransaction coinbaseTx{}; 39 CMutableTransaction naughtyTx{}; 40 41 LOCK(cs_main); 42 CBlockIndex* pindexPrev = testing_setup->m_node.chainman->ActiveChain().Tip(); 43 assert(pindexPrev != nullptr); 44 block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus()); 45 block.nNonce = 0; 46 auto nHeight = pindexPrev->nHeight + 1; 47 48 // Make a coinbase TX 49 coinbaseTx.vin.resize(1); 50 coinbaseTx.vin[0].prevout.SetNull(); 51 coinbaseTx.vout.resize(1); 52 coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB; 53 coinbaseTx.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus()); 54 coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; 55 56 57 naughtyTx.vout.resize(1); 58 naughtyTx.vout[0].nValue = 0; 59 naughtyTx.vout[0].scriptPubKey = SCRIPT_PUB; 60 61 uint64_t n_inputs = (((MAX_BLOCK_SERIALIZED_SIZE / WITNESS_SCALE_FACTOR) - (CTransaction(coinbaseTx).ComputeTotalSize() + CTransaction(naughtyTx).ComputeTotalSize())) / 41) - 100; 62 for (uint64_t x = 0; x < (n_inputs - 1); ++x) { 63 naughtyTx.vin.emplace_back(Txid::FromUint256(GetRandHash()), 0, CScript(), 0); 64 } 65 naughtyTx.vin.emplace_back(naughtyTx.vin.back()); 66 67 block.vtx.push_back(MakeTransactionRef(std::move(coinbaseTx))); 68 block.vtx.push_back(MakeTransactionRef(std::move(naughtyTx))); 69 70 block.hashMerkleRoot = BlockMerkleRoot(block); 71 72 bench.run([&] { 73 BlockValidationState cvstate{}; 74 assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false)); 75 assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate"); 76 }); 77 } 78 79 BENCHMARK(DuplicateInputs);