/ src / test / fuzz / transaction.cpp
transaction.cpp
  1  // Copyright (c) 2019-2022 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      DataStream 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      DataStream ds_mtx{buffer};
 45      CMutableTransaction mutable_tx;
 46      try {
 47          ds_mtx >> TX_WITH_WITNESS(mutable_tx);
 48      } catch (const std::ios_base::failure&) {
 49          valid_mutable_tx = false;
 50      }
 51      assert(valid_tx == valid_mutable_tx);
 52      if (!valid_tx) {
 53          return;
 54      }
 55  
 56      {
 57          TxValidationState state_with_dupe_check;
 58          const bool res{CheckTransaction(tx, state_with_dupe_check)};
 59          Assert(res == state_with_dupe_check.IsValid());
 60      }
 61  
 62      const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
 63      std::string reason;
 64      const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
 65      const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
 66      if (is_standard_without_permit_bare_multisig) {
 67          assert(is_standard_with_permit_bare_multisig);
 68      }
 69  
 70      (void)tx.GetHash();
 71      (void)tx.GetTotalSize();
 72      try {
 73          (void)tx.GetValueOut();
 74      } catch (const std::runtime_error&) {
 75      }
 76      (void)tx.GetWitnessHash();
 77      (void)tx.HasWitness();
 78      (void)tx.IsCoinBase();
 79      (void)tx.IsNull();
 80      (void)tx.ToString();
 81  
 82      (void)EncodeHexTx(tx);
 83      (void)GetLegacySigOpCount(tx);
 84      (void)GetTransactionWeight(tx);
 85      (void)GetVirtualTransactionSize(tx);
 86      (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
 87      (void)RecursiveDynamicUsage(tx);
 88      (void)SignalsOptInRBF(tx);
 89  
 90      CCoinsView coins_view;
 91      const CCoinsViewCache coins_view_cache(&coins_view);
 92      (void)AreInputsStandard(tx, coins_view_cache);
 93      (void)IsWitnessStandard(tx, coins_view_cache);
 94  
 95      if (tx.GetTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding
 96          {
 97              UniValue u{UniValue::VOBJ};
 98              TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u);
 99          }
100          {
101              UniValue u{UniValue::VOBJ};
102              TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u);
103          }
104      }
105  }