/ src / test / fuzz / policy_estimator.cpp
policy_estimator.cpp
  1  // Copyright (c) 2020-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 <kernel/mempool_entry.h>
  6  #include <policy/fees/block_policy_estimator.h>
  7  #include <policy/fees/block_policy_estimator_args.h>
  8  #include <primitives/transaction.h>
  9  #include <streams.h>
 10  #include <test/fuzz/FuzzedDataProvider.h>
 11  #include <test/fuzz/fuzz.h>
 12  #include <test/fuzz/util.h>
 13  #include <test/fuzz/util/mempool.h>
 14  #include <test/util/setup_common.h>
 15  
 16  #include <memory>
 17  #include <optional>
 18  #include <vector>
 19  
 20  namespace {
 21  const BasicTestingSetup* g_setup;
 22  } // namespace
 23  
 24  void initialize_policy_estimator()
 25  {
 26      static const auto testing_setup = MakeNoLogFileContext<>();
 27      g_setup = testing_setup.get();
 28  }
 29  
 30  FUZZ_TARGET(policy_estimator, .init = initialize_policy_estimator)
 31  {
 32      FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
 33      bool good_data{true};
 34  
 35      CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES};
 36  
 37      uint32_t current_height{0};
 38      const auto advance_height{
 39          [&] { current_height = fuzzed_data_provider.ConsumeIntegralInRange<decltype(current_height)>(current_height, 1 << 30); },
 40      };
 41      advance_height();
 42      LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
 43      {
 44          CallOneOf(
 45              fuzzed_data_provider,
 46              [&] {
 47                  const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
 48                  if (!mtx) {
 49                      good_data = false;
 50                      return;
 51                  }
 52                  const CTransaction tx{*mtx};
 53                  const auto entry{ConsumeTxMemPoolEntry(fuzzed_data_provider, tx, current_height)};
 54                  const auto tx_submitted_in_package = fuzzed_data_provider.ConsumeBool();
 55                  const auto tx_has_mempool_parents = fuzzed_data_provider.ConsumeBool();
 56                  const auto tx_info = NewMempoolTransactionInfo(entry.GetSharedTx(), entry.GetFee(),
 57                                                                 entry.GetTxSize(), entry.GetHeight(),
 58                                                                 /*mempool_limit_bypassed=*/false,
 59                                                                 tx_submitted_in_package,
 60                                                                 /*chainstate_is_current=*/true,
 61                                                                 tx_has_mempool_parents);
 62                  block_policy_estimator.processTransaction(tx_info);
 63                  if (fuzzed_data_provider.ConsumeBool()) {
 64                      (void)block_policy_estimator.removeTx(tx.GetHash());
 65                  }
 66              },
 67              [&] {
 68                  std::list<CTxMemPoolEntry> mempool_entries;
 69                  LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
 70                  {
 71                      const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
 72                      if (!mtx) {
 73                          good_data = false;
 74                          break;
 75                      }
 76                      const CTransaction tx{*mtx};
 77                      mempool_entries.push_back(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx, current_height));
 78                  }
 79                  std::vector<RemovedMempoolTransactionInfo> txs;
 80                  txs.reserve(mempool_entries.size());
 81                  for (const CTxMemPoolEntry& mempool_entry : mempool_entries) {
 82                      txs.emplace_back(mempool_entry);
 83                  }
 84                  advance_height();
 85                  block_policy_estimator.processBlock(txs, current_height);
 86              },
 87              [&] {
 88                  (void)block_policy_estimator.removeTx(Txid::FromUint256(ConsumeUInt256(fuzzed_data_provider)));
 89              },
 90              [&] {
 91                  block_policy_estimator.FlushUnconfirmed();
 92              });
 93          (void)block_policy_estimator.estimateFee(fuzzed_data_provider.ConsumeIntegral<int>());
 94          EstimationResult result;
 95          auto conf_target = fuzzed_data_provider.ConsumeIntegral<int>();
 96          auto success_threshold = fuzzed_data_provider.ConsumeFloatingPoint<double>();
 97          auto horizon = fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS);
 98          auto* result_ptr = fuzzed_data_provider.ConsumeBool() ? &result : nullptr;
 99          (void)block_policy_estimator.estimateRawFee(conf_target, success_threshold, horizon, result_ptr);
100  
101          FeeCalculation fee_calculation;
102          conf_target = fuzzed_data_provider.ConsumeIntegral<int>();
103          auto* fee_calc_ptr = fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr;
104          auto conservative = fuzzed_data_provider.ConsumeBool();
105          (void)block_policy_estimator.estimateSmartFee(conf_target, fee_calc_ptr, conservative);
106  
107          (void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS));
108      }
109      {
110          FuzzedFileProvider fuzzed_file_provider{fuzzed_data_provider};
111          AutoFile fuzzed_auto_file{fuzzed_file_provider.open()};
112          block_policy_estimator.Write(fuzzed_auto_file);
113          block_policy_estimator.Read(fuzzed_auto_file);
114          (void)fuzzed_auto_file.fclose();
115      }
116  }