|
3 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
4 | 4 |
|
5 | 5 | #include <cluster_linearize.h>
|
| 6 | +#include <random.h> |
6 | 7 | #include <serialize.h>
|
7 | 8 | #include <streams.h>
|
8 | 9 | #include <test/fuzz/fuzz.h>
|
@@ -176,7 +177,7 @@ void MakeConnected(DepGraph<BS>& depgraph)
|
176 | 177 | while (todo.Any()) {
|
177 | 178 | auto nextcomp = depgraph.FindConnectedComponent(todo);
|
178 | 179 | Assume(depgraph.IsConnected(nextcomp));
|
179 |
| - depgraph.AddDependency(comp.Last(), nextcomp.First()); |
| 180 | + depgraph.AddDependencies(BS::Singleton(comp.Last()), nextcomp.First()); |
180 | 181 | todo -= nextcomp;
|
181 | 182 | comp = nextcomp;
|
182 | 183 | }
|
@@ -240,32 +241,65 @@ std::vector<ClusterIndex> ReadLinearization(const DepGraph<BS>& depgraph, SpanRe
|
240 | 241 |
|
241 | 242 | } // namespace
|
242 | 243 |
|
243 |
| -FUZZ_TARGET(clusterlin_add_dependency) |
| 244 | +FUZZ_TARGET(clusterlin_add_dependencies) |
244 | 245 | {
|
245 |
| - // Verify that computing a DepGraph from a cluster, or building it step by step using AddDependency |
246 |
| - // have the same effect. |
| 246 | + // Verify that computing a DepGraph from a cluster, or building it step by step using |
| 247 | + // AddDependencies has the same effect. |
247 | 248 |
|
248 |
| - // Construct a cluster of a certain length, with no dependencies. |
249 | 249 | FuzzedDataProvider provider(buffer.data(), buffer.size());
|
250 |
| - auto num_tx = provider.ConsumeIntegralInRange<ClusterIndex>(2, 32); |
| 250 | + auto rng_seed = provider.ConsumeIntegral<uint64_t>(); |
| 251 | + InsecureRandomContext rng(rng_seed); |
| 252 | + |
| 253 | + // Construct a cluster of a certain length, with no dependencies. |
| 254 | + auto num_tx = provider.ConsumeIntegralInRange<ClusterIndex>(2, TestBitSet::Size()); |
251 | 255 | Cluster<TestBitSet> cluster(num_tx, std::pair{FeeFrac{0, 1}, TestBitSet{}});
|
252 | 256 | // Construct the corresponding DepGraph object (also no dependencies).
|
253 |
| - DepGraph depgraph(cluster); |
254 |
| - SanityCheck(depgraph); |
255 |
| - // Read (parent, child) pairs, and add them to the cluster and depgraph. |
256 |
| - LIMITED_WHILE(provider.remaining_bytes() > 0, TestBitSet::Size() * TestBitSet::Size()) { |
257 |
| - auto parent = provider.ConsumeIntegralInRange<ClusterIndex>(0, num_tx - 1); |
258 |
| - auto child = provider.ConsumeIntegralInRange<ClusterIndex>(0, num_tx - 2); |
259 |
| - child += (child >= parent); |
260 |
| - cluster[child].second.Set(parent); |
261 |
| - depgraph.AddDependency(parent, child); |
262 |
| - assert(depgraph.Ancestors(child)[parent]); |
263 |
| - assert(depgraph.Descendants(parent)[child]); |
| 257 | + DepGraph depgraph_batch(cluster); |
| 258 | + SanityCheck(depgraph_batch); |
| 259 | + // Read (parents, child) pairs, and add the dependencies to the cluster and depgraph. |
| 260 | + std::vector<std::pair<ClusterIndex, ClusterIndex>> deps_list; |
| 261 | + LIMITED_WHILE(provider.remaining_bytes() > 0, TestBitSet::Size()) { |
| 262 | + const auto parents_mask = provider.ConsumeIntegralInRange<uint64_t>(0, (uint64_t{1} << num_tx) - 1); |
| 263 | + auto child = provider.ConsumeIntegralInRange<ClusterIndex>(0, num_tx - 1); |
| 264 | + |
| 265 | + auto parents_mask_shifted = parents_mask; |
| 266 | + TestBitSet deps; |
| 267 | + for (ClusterIndex i = 0; i < num_tx; ++i) { |
| 268 | + if (parents_mask_shifted & 1) { |
| 269 | + deps.Set(i); |
| 270 | + cluster[child].second.Set(i); |
| 271 | + } |
| 272 | + parents_mask_shifted >>= 1; |
| 273 | + } |
| 274 | + assert(parents_mask_shifted == 0); |
| 275 | + depgraph_batch.AddDependencies(deps, child); |
| 276 | + for (auto i : deps) { |
| 277 | + deps_list.emplace_back(i, child); |
| 278 | + assert(depgraph_batch.Ancestors(child)[i]); |
| 279 | + assert(depgraph_batch.Descendants(i)[child]); |
| 280 | + } |
264 | 281 | }
|
265 | 282 | // Sanity check the result.
|
266 |
| - SanityCheck(depgraph); |
| 283 | + SanityCheck(depgraph_batch); |
267 | 284 | // Verify that the resulting DepGraph matches one recomputed from the cluster.
|
268 |
| - assert(DepGraph(cluster) == depgraph); |
| 285 | + assert(DepGraph(cluster) == depgraph_batch); |
| 286 | + |
| 287 | + DepGraph<TestBitSet> depgraph_individual; |
| 288 | + // Add all transactions to depgraph_individual. |
| 289 | + for (const auto& [feerate, parents] : cluster) { |
| 290 | + depgraph_individual.AddTransaction(feerate); |
| 291 | + } |
| 292 | + SanityCheck(depgraph_individual); |
| 293 | + // Add all individual dependencies to depgraph_individual in randomized order. |
| 294 | + std::shuffle(deps_list.begin(), deps_list.end(), rng); |
| 295 | + for (auto [parent, child] : deps_list) { |
| 296 | + depgraph_individual.AddDependencies(TestBitSet::Singleton(parent), child); |
| 297 | + assert(depgraph_individual.Ancestors(child)[parent]); |
| 298 | + assert(depgraph_individual.Descendants(parent)[child]); |
| 299 | + } |
| 300 | + // Sanity check and compare again the batched version. |
| 301 | + SanityCheck(depgraph_individual); |
| 302 | + assert(depgraph_individual == depgraph_batch); |
269 | 303 | }
|
270 | 304 |
|
271 | 305 | FUZZ_TARGET(clusterlin_cluster_serialization)
|
@@ -897,12 +931,16 @@ FUZZ_TARGET(clusterlin_postlinearize_tree)
|
897 | 931 | if (direction & 1) {
|
898 | 932 | for (ClusterIndex i = 0; i < depgraph_gen.TxCount(); ++i) {
|
899 | 933 | auto children = depgraph_gen.GetReducedChildren(i);
|
900 |
| - if (children.Any()) depgraph_tree.AddDependency(i, children.First()); |
| 934 | + if (children.Any()) { |
| 935 | + depgraph_tree.AddDependencies(TestBitSet::Singleton(i), children.First()); |
| 936 | + } |
901 | 937 | }
|
902 | 938 | } else {
|
903 | 939 | for (ClusterIndex i = 0; i < depgraph_gen.TxCount(); ++i) {
|
904 | 940 | auto parents = depgraph_gen.GetReducedParents(i);
|
905 |
| - if (parents.Any()) depgraph_tree.AddDependency(parents.First(), i); |
| 941 | + if (parents.Any()) { |
| 942 | + depgraph_tree.AddDependencies(TestBitSet::Singleton(parents.First()), i); |
| 943 | + } |
906 | 944 | }
|
907 | 945 | }
|
908 | 946 |
|
|
0 commit comments