duplicate_inputs.cpp raw

   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 <util/check.h>
  20  #include <validation.h>
  21  
  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);
  80