/ src / test / fuzz / transaction.cpp
transaction.cpp
  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      CCoinsView coins_view;
 90      const CCoinsViewCache coins_view_cache(&coins_view);
 91      (void)AreInputsStandard(tx, coins_view_cache);
 92      (void)IsWitnessStandard(tx, coins_view_cache);
 93  
 94      if (tx.ComputeTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding
 95          {
 96              UniValue u{UniValue::VOBJ};
 97              TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u);
 98          }
 99          {
100              UniValue u{UniValue::VOBJ};
101              TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u);
102          }
103      }
104  }