policy_estimator.cpp raw

   1  // Copyright (c) 2020-2022 The Limenka 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.h>
   7  #include <policy/fees_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      LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10'000)
  37      {
  38          CallOneOf(
  39              fuzzed_data_provider,
  40              [&] {
  41                  const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
  42                  if (!mtx) {
  43                      good_data = false;
  44                      return;
  45                  }
  46                  const CTransaction tx{*mtx};
  47                  if (!SanityCheckForConsumeTxMemPoolEntry(tx)) return;
  48                  const CTxMemPoolEntry& entry = ConsumeTxMemPoolEntry(fuzzed_data_provider, tx);
  49                  const auto tx_submitted_in_package = fuzzed_data_provider.ConsumeBool();
  50                  const auto tx_has_mempool_parents = fuzzed_data_provider.ConsumeBool();
  51                  const auto tx_info = NewMempoolTransactionInfo(entry.GetSharedTx(), entry.GetFee(),
  52                                                                 entry.GetTxSize(), entry.GetHeight(),
  53                                                                 empty_ignore_rejects,
  54                                                                 tx_submitted_in_package,
  55                                                                 /*chainstate_is_current=*/true,
  56                                                                 tx_has_mempool_parents);
  57                  block_policy_estimator.processTransaction(tx_info);
  58                  if (fuzzed_data_provider.ConsumeBool()) {
  59                      (void)block_policy_estimator.removeTx(tx.GetHash());
  60                  }
  61              },
  62              [&] {
  63                  std::list<CTxMemPoolEntry> mempool_entries;
  64                  LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
  65                  {
  66                      const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
  67                      if (!mtx) {
  68                          good_data = false;
  69                          break;
  70                      }
  71                      const CTransaction tx{*mtx};
  72                      if (!SanityCheckForConsumeTxMemPoolEntry(tx)) return;
  73                      mempool_entries.emplace_back(CTxMemPoolEntry::ExplicitCopy, ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
  74                  }
  75                  std::vector<RemovedMempoolTransactionInfo> txs;
  76                  txs.reserve(mempool_entries.size());
  77                  for (const CTxMemPoolEntry& mempool_entry : mempool_entries) {
  78                      txs.emplace_back(mempool_entry);
  79                  }
  80                  block_policy_estimator.processBlock(txs, fuzzed_data_provider.ConsumeIntegral<unsigned int>());
  81              },
  82              [&] {
  83                  (void)block_policy_estimator.removeTx(ConsumeUInt256(fuzzed_data_provider));
  84              },
  85              [&] {
  86                  block_policy_estimator.FlushUnconfirmed();
  87              });
  88          (void)block_policy_estimator.estimateFee(fuzzed_data_provider.ConsumeIntegral<int>());
  89          EstimationResult result;
  90          auto conf_target = fuzzed_data_provider.ConsumeIntegral<int>();
  91          auto success_threshold = fuzzed_data_provider.ConsumeFloatingPoint<double>();
  92          auto horizon = fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS);
  93          auto* result_ptr = fuzzed_data_provider.ConsumeBool() ? &result : nullptr;
  94          (void)block_policy_estimator.estimateRawFee(conf_target, success_threshold, horizon, result_ptr);
  95  
  96          FeeCalculation fee_calculation;
  97          conf_target = fuzzed_data_provider.ConsumeIntegral<int>();
  98          auto* fee_calc_ptr = fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr;
  99          auto conservative = fuzzed_data_provider.ConsumeBool();
 100          (void)block_policy_estimator.estimateSmartFee(conf_target, fee_calc_ptr, conservative);
 101  
 102          (void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS));
 103      }
 104      {
 105          FuzzedFileProvider fuzzed_file_provider{fuzzed_data_provider};
 106          AutoFile fuzzed_auto_file{fuzzed_file_provider.open()};
 107          block_policy_estimator.Write(fuzzed_auto_file);
 108          block_policy_estimator.Read(fuzzed_auto_file);
 109          (void)fuzzed_auto_file.fclose();
 110      }
 111  }
 112