transaction.cpp raw

   1  // Copyright (c) 2019-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 <chainparams.h>
   6  #include <coins.h>
   7  #include <consensus/tx_check.h>
   8  #include <consensus/tx_verify.h>
   9  #include <consensus/validation.h>
  10  #include <core_io.h>
  11  #include <core_memusage.h>
  12  #include <policy/policy.h>
  13  #include <policy/settings.h>
  14  #include <primitives/transaction.h>
  15  #include <streams.h>
  16  #include <test/fuzz/fuzz.h>
  17  #include <test/util/random.h>
  18  #include <univalue.h>
  19  #include <util/chaintype.h>
  20  #include <util/rbf.h>
  21  #include <validation.h>
  22  
  23  #include <cassert>
  24  
  25  void initialize_transaction()
  26  {
  27      SelectParams(ChainType::REGTEST);
  28  }
  29  
  30  FUZZ_TARGET(transaction, .init = initialize_transaction)
  31  {
  32      SeedRandomStateForTest(SeedRand::ZEROS);
  33      SpanReader ds{buffer};
  34      bool valid_tx = true;
  35      const CTransaction tx = [&] {
  36          try {
  37              return CTransaction(deserialize, TX_WITH_WITNESS, ds);
  38          } catch (const std::ios_base::failure&) {
  39              valid_tx = false;
  40              return CTransaction{CMutableTransaction{}};
  41          }
  42      }();
  43      bool valid_mutable_tx = true;
  44      CMutableTransaction mutable_tx;
  45      try {
  46          SpanReader{buffer} >> TX_WITH_WITNESS(mutable_tx);
  47      } catch (const std::ios_base::failure&) {
  48          valid_mutable_tx = false;
  49      }
  50      assert(valid_tx == valid_mutable_tx);
  51      if (!valid_tx) {
  52          return;
  53      }
  54  
  55      {
  56          TxValidationState state_with_dupe_check;
  57          const bool res{CheckTransaction(tx, state_with_dupe_check)};
  58          Assert(res == state_with_dupe_check.IsValid());
  59      }
  60  
  61      const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
  62      std::string reason;
  63      const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
  64      const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
  65      if (is_standard_without_permit_bare_multisig) {
  66          assert(is_standard_with_permit_bare_multisig);
  67      }
  68  
  69      (void)tx.GetHash();
  70      (void)tx.ComputeTotalSize();
  71      try {
  72          (void)tx.GetValueOut();
  73      } catch (const std::runtime_error&) {
  74      }
  75      (void)tx.GetWitnessHash();
  76      (void)tx.HasWitness();
  77      (void)tx.IsCoinBase();
  78      (void)tx.IsNull();
  79      (void)tx.ToString();
  80  
  81      (void)EncodeHexTx(tx);
  82      (void)GetLegacySigOpCount(tx);
  83      (void)GetTransactionWeight(tx);
  84      (void)GetVirtualTransactionSize(tx);
  85      (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
  86      (void)RecursiveDynamicUsage(tx);
  87      (void)SignalsOptInRBF(tx);
  88  
  89      const CCoinsViewCache coins_view_cache{&CoinsViewEmpty::Get()};
  90      (void)ValidateInputsStandardness(tx, coins_view_cache);
  91      (void)IsWitnessStandard(tx, coins_view_cache);
  92  
  93      if (tx.ComputeTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding
  94          {
  95              UniValue u{UniValue::VOBJ};
  96              TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u);
  97          }
  98          {
  99              UniValue u{UniValue::VOBJ};
 100              TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u);
 101          }
 102      }
 103  }
 104