mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-19 12:10:19 +01:00
clusterlin: Add FixLinearization function + fuzz test
This function takes an existing ordering for transactions in a DepGraph, and makes it a valid linearization for it (i.e., topological). Any topological prefix of the input remains untouched.
This commit is contained in:
@@ -1118,3 +1118,65 @@ FUZZ_TARGET(clusterlin_merge)
|
||||
auto cmp2 = CompareChunks(chunking_merged, chunking2);
|
||||
assert(cmp2 >= 0);
|
||||
}
|
||||
|
||||
FUZZ_TARGET(clusterlin_fix_linearization)
|
||||
{
|
||||
// Verify expected properties of FixLinearization() on arbitrary linearizations.
|
||||
|
||||
// Retrieve a depgraph from the fuzz input.
|
||||
SpanReader reader(buffer);
|
||||
DepGraph<TestBitSet> depgraph;
|
||||
try {
|
||||
reader >> Using<DepGraphFormatter>(depgraph);
|
||||
} catch (const std::ios_base::failure&) {}
|
||||
|
||||
// Construct an arbitrary linearization (not necessarily topological for depgraph).
|
||||
std::vector<ClusterIndex> linearization;
|
||||
/** Which transactions of depgraph are yet to be included in linearization. */
|
||||
TestBitSet todo = depgraph.Positions();
|
||||
while (todo.Any()) {
|
||||
// Read a number from the fuzz input in range [0, todo.Count()).
|
||||
uint64_t val{0};
|
||||
try {
|
||||
reader >> VARINT(val);
|
||||
} catch (const std::ios_base::failure&) {}
|
||||
val %= todo.Count();
|
||||
// Find the val'th element in todo, remove it from todo, and append it to linearization.
|
||||
for (auto idx : todo) {
|
||||
if (val == 0) {
|
||||
linearization.push_back(idx);
|
||||
todo.Reset(idx);
|
||||
break;
|
||||
}
|
||||
--val;
|
||||
}
|
||||
}
|
||||
assert(linearization.size() == depgraph.TxCount());
|
||||
|
||||
// Determine what prefix of linearization is topological, i.e., the position of the first entry
|
||||
// in linearization which corresponds to a transaction that is not preceded by all its
|
||||
// ancestors.
|
||||
size_t topo_prefix = 0;
|
||||
todo = depgraph.Positions();
|
||||
while (topo_prefix < linearization.size()) {
|
||||
ClusterIndex idx = linearization[topo_prefix];
|
||||
todo.Reset(idx);
|
||||
if (todo.Overlaps(depgraph.Ancestors(idx))) break;
|
||||
++topo_prefix;
|
||||
}
|
||||
|
||||
// Then make a fixed copy of linearization.
|
||||
auto linearization_fixed = linearization;
|
||||
FixLinearization(depgraph, linearization_fixed);
|
||||
// Sanity check it (which includes testing whether it is topological).
|
||||
SanityCheck(depgraph, linearization_fixed);
|
||||
|
||||
// FixLinearization does not modify the topological prefix of linearization.
|
||||
assert(std::equal(linearization.begin(), linearization.begin() + topo_prefix,
|
||||
linearization_fixed.begin()));
|
||||
// This also means that if linearization was entirely topological, FixLinearization cannot have
|
||||
// modified it. This is implied by the assertion above already, but repeat it explicitly.
|
||||
if (topo_prefix == linearization.size()) {
|
||||
assert(linearization == linearization_fixed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user