coincontrol.cpp raw

   1  // Copyright (c) 2022-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 <test/fuzz/FuzzedDataProvider.h>
   6  #include <test/fuzz/fuzz.h>
   7  #include <test/fuzz/util.h>
   8  #include <test/util/setup_common.h>
   9  #include <wallet/coincontrol.h>
  10  #include <wallet/test/util.h>
  11  
  12  namespace wallet {
  13  namespace {
  14  
  15  const TestingSetup* g_setup;
  16  
  17  void initialize_coincontrol()
  18  {
  19      static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
  20      g_setup = testing_setup.get();
  21  }
  22  
  23  FUZZ_TARGET(coincontrol, .init = initialize_coincontrol)
  24  {
  25      FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
  26      const auto& node = g_setup->m_node;
  27      ArgsManager& args = *node.args;
  28  
  29      // for GetBoolArg to return true sometimes
  30      args.ForceSetArg("-avoidpartialspends", fuzzed_data_provider.ConsumeBool()?"1":"0");
  31  
  32      CCoinControl coin_control;
  33      COutPoint out_point;
  34  
  35      LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
  36      {
  37          CallOneOf(
  38              fuzzed_data_provider,
  39              [&] {
  40                  std::optional<COutPoint> optional_out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
  41                  if (!optional_out_point) {
  42                      return;
  43                  }
  44                  out_point = *optional_out_point;
  45              },
  46              [&] {
  47                  (void)coin_control.HasSelected();
  48              },
  49              [&] {
  50                  (void)coin_control.IsSelected(out_point);
  51              },
  52              [&] {
  53                  (void)coin_control.IsExternalSelected(out_point);
  54              },
  55              [&] {
  56                  (void)coin_control.GetExternalOutput(out_point);
  57              },
  58              [&] {
  59                  (void)coin_control.Select(out_point);
  60                  assert(coin_control.IsSelected(out_point));
  61              },
  62              [&] {
  63                  const CTxOut tx_out{ConsumeMoney(fuzzed_data_provider), ConsumeScript(fuzzed_data_provider)};
  64                  auto& input = coin_control.Select(out_point);
  65                  const auto set_tx_out{fuzzed_data_provider.ConsumeBool()};
  66                  if (set_tx_out) {
  67                      input.SetTxOut(tx_out);
  68                  }
  69                  auto has_tx_out{input.HasTxOut()};
  70                  auto is_external_selected{coin_control.IsExternalSelected(out_point)};
  71                  if (set_tx_out) {
  72                      assert(has_tx_out);
  73                      assert(input.GetTxOut() == tx_out);
  74                      assert(is_external_selected);
  75                  } else if (!has_tx_out) {
  76                      assert(!is_external_selected);
  77                  }
  78              },
  79              [&] {
  80                  coin_control.UnSelect(out_point);
  81                  assert(!coin_control.IsSelected(out_point));
  82              },
  83              [&] {
  84                  coin_control.UnSelectAll();
  85                  assert(!coin_control.HasSelected());
  86              },
  87              [&] {
  88                  const std::vector<COutPoint> selected = coin_control.ListSelected();
  89                  for (const auto& out : selected) {
  90                      assert(coin_control.IsSelected(out));
  91                  }
  92              },
  93              [&] {
  94                  int64_t weight{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
  95                  coin_control.SetInputWeight(out_point, weight);
  96                  assert(coin_control.GetInputWeight(out_point) == weight);
  97              },
  98              [&] {
  99                  const bool is_selected = coin_control.IsSelected(out_point);
 100                  assert(!coin_control.GetInputWeight(out_point) || is_selected);
 101                  assert(!coin_control.GetSequence(out_point) || is_selected);
 102              },
 103              [&] {
 104                  const auto scripts = coin_control.GetScripts(out_point);
 105                  assert(coin_control.IsSelected(out_point) || (!scripts.first && !scripts.second));
 106              },
 107              [&] {
 108                  assert(coin_control.HasSelectedOrder() || !coin_control.GetSelectionPos(out_point));
 109              },
 110              [&] {
 111                  assert(!coin_control.GetSelectionPos(out_point) || coin_control.IsSelected(out_point));
 112              },
 113              [&] {
 114                  auto& input = coin_control.Select(out_point);
 115                  uint32_t sequence{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
 116                  input.SetSequence(sequence);
 117                  assert(input.GetSequence() == sequence);
 118                  assert(coin_control.GetSequence(out_point) == sequence);
 119              },
 120              [&] {
 121                  auto& input = coin_control.Select(out_point);
 122                  const CScript script{ConsumeScript(fuzzed_data_provider)};
 123                  input.SetScriptSig(script);
 124                  assert(input.HasScripts());
 125                  assert(input.GetScripts().first == script);
 126                  assert(coin_control.GetScripts(out_point).first == script);
 127              },
 128              [&] {
 129                  auto& input = coin_control.Select(out_point);
 130                  const CScriptWitness script_wit{ConsumeScriptWitness(fuzzed_data_provider)};
 131                  input.SetScriptWitness(script_wit);
 132                  assert(input.HasScripts());
 133                  assert(input.GetScripts().second->stack == script_wit.stack);
 134                  assert(coin_control.GetScripts(out_point).second->stack == script_wit.stack);
 135              },
 136              [&] {
 137                  auto& input = coin_control.Select(out_point);
 138                  unsigned int pos{fuzzed_data_provider.ConsumeIntegral<unsigned int>()};
 139                  input.SetPosition(pos);
 140                  assert(input.GetPosition() == pos);
 141                  assert(coin_control.GetSelectionPos(out_point) == pos);
 142              });
 143      }
 144  }
 145  } // namespace
 146  } // namespace wallet
 147