/ 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 <univalue.h>
 18  #include <util/chaintype.h>
 19  #include <util/rbf.h>
 20  #include <validation.h>
 21  
 22  #include <cassert>
 23  
 24  void initialize_transaction()
 25  {
 26      SelectParams(ChainType::REGTEST);
 27  }
 28  
 29  FUZZ_TARGET(transaction, .init = initialize_transaction)
 30  {
 31      DataStream ds{buffer};
 32      bool valid_tx = true;
 33      const CTransaction tx = [&] {
 34          try {
 35              return CTransaction(deserialize, TX_WITH_WITNESS, ds);
 36          } catch (const std::ios_base::failure&) {
 37              valid_tx = false;
 38              return CTransaction{CMutableTransaction{}};
 39          }
 40      }();
 41      bool valid_mutable_tx = true;
 42      DataStream ds_mtx{buffer};
 43      CMutableTransaction mutable_tx;
 44      try {
 45          ds_mtx >> TX_WITH_WITNESS(mutable_tx);
 46      } catch (const std::ios_base::failure&) {
 47          valid_mutable_tx = false;
 48      }
 49      assert(valid_tx == valid_mutable_tx);
 50      if (!valid_tx) {
 51          return;
 52      }
 53  
 54      {
 55          TxValidationState state_with_dupe_check;
 56          const bool res{CheckTransaction(tx, state_with_dupe_check)};
 57          Assert(res == state_with_dupe_check.IsValid());
 58      }
 59  
 60      const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
 61      std::string reason;
 62      const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
 63      const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
 64      if (is_standard_without_permit_bare_multisig) {
 65          assert(is_standard_with_permit_bare_multisig);
 66      }
 67  
 68      (void)tx.GetHash();
 69      (void)tx.GetTotalSize();
 70      try {
 71          (void)tx.GetValueOut();
 72      } catch (const std::runtime_error&) {
 73      }
 74      (void)tx.GetWitnessHash();
 75      (void)tx.HasWitness();
 76      (void)tx.IsCoinBase();
 77      (void)tx.IsNull();
 78      (void)tx.ToString();
 79  
 80      (void)EncodeHexTx(tx);
 81      (void)GetLegacySigOpCount(tx);
 82      (void)GetTransactionWeight(tx);
 83      (void)GetVirtualTransactionSize(tx);
 84      (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
 85      (void)RecursiveDynamicUsage(tx);
 86      (void)SignalsOptInRBF(tx);
 87  
 88      CCoinsView coins_view;
 89      const CCoinsViewCache coins_view_cache(&coins_view);
 90      (void)AreInputsStandard(tx, coins_view_cache);
 91      (void)IsWitnessStandard(tx, coins_view_cache);
 92  
 93      if (tx.GetTotalSize() < 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  }