Bitcoin Core  27.99.0
P2P Digital Currency
minisketch.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 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 <minisketch.h>
8 #include <test/fuzz/fuzz.h>
9 #include <test/fuzz/util.h>
10 #include <util/check.h>
11 
12 #include <map>
13 #include <numeric>
14 
15 namespace {
16 
17 Minisketch MakeFuzzMinisketch32(size_t capacity, uint32_t impl)
18 {
19  return Assert(Minisketch(32, impl, capacity));
20 }
21 
22 } // namespace
23 
25 {
26  FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
27 
28  const auto capacity{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 200)};
29  const uint32_t impl{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, Minisketch::MaxImplementation())};
30  if (!Minisketch::ImplementationSupported(32, impl)) return;
31 
32  Minisketch sketch_a{MakeFuzzMinisketch32(capacity, impl)};
33  Minisketch sketch_b{MakeFuzzMinisketch32(capacity, impl)};
34  sketch_a.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
35  sketch_b.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
36 
37  // Fill two sets and keep the difference in a map
38  std::map<uint32_t, bool> diff;
39  LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
40  {
41  const auto entry{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, std::numeric_limits<uint32_t>::max() - 1)};
42  const auto KeepDiff{[&] {
43  bool& mut{diff[entry]};
44  mut = !mut;
45  }};
46  CallOneOf(
47  fuzzed_data_provider,
48  [&] {
49  sketch_a.Add(entry);
50  KeepDiff();
51  },
52  [&] {
53  sketch_b.Add(entry);
54  KeepDiff();
55  },
56  [&] {
57  sketch_a.Add(entry);
58  sketch_b.Add(entry);
59  });
60  }
61  const auto num_diff{std::accumulate(diff.begin(), diff.end(), size_t{0}, [](auto n, const auto& e) { return n + e.second; })};
62 
63  Minisketch sketch_ar{MakeFuzzMinisketch32(capacity, impl)};
64  Minisketch sketch_br{MakeFuzzMinisketch32(capacity, impl)};
65  sketch_ar.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
66  sketch_br.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
67 
68  sketch_ar.Deserialize(sketch_a.Serialize());
69  sketch_br.Deserialize(sketch_b.Serialize());
70 
71  Minisketch sketch_diff{std::move(fuzzed_data_provider.ConsumeBool() ? sketch_a : sketch_ar)};
72  sketch_diff.Merge(fuzzed_data_provider.ConsumeBool() ? sketch_b : sketch_br);
73 
74  if (capacity >= num_diff) {
75  const auto max_elements{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(num_diff, capacity)};
76  const auto dec{*Assert(sketch_diff.Decode(max_elements))};
77  Assert(dec.size() == num_diff);
78  for (auto d : dec) {
79  Assert(diff.at(d));
80  }
81  }
82 }
#define Assert(val)
Identity function.
Definition: check.h:77
T ConsumeIntegralInRange(T min, T max)
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
Definition: fuzz.h:23
struct minisketch minisketch
Opaque type for decoded sketches.
Definition: minisketch.h:41
FUZZ_TARGET(minisketch)
Definition: minisketch.cpp:24
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
Definition: util.h:35