mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
clusterlin: Make IsAcyclic() a DepGraph member function
... instead of being a separate test-only function. Also add a fuzz test for it returning false.
This commit is contained in:
parent
0aa874a357
commit
bfeb69f6e0
3 changed files with 43 additions and 15 deletions
|
@ -309,6 +309,17 @@ public:
|
||||||
return a < b;
|
return a < b;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check if this graph is acyclic. */
|
||||||
|
bool IsAcyclic() const noexcept
|
||||||
|
{
|
||||||
|
for (auto i : Positions()) {
|
||||||
|
if ((Ancestors(i) & Descendants(i)) != SetType::Singleton(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A set of transactions together with their aggregate feerate. */
|
/** A set of transactions together with their aggregate feerate. */
|
||||||
|
|
|
@ -401,13 +401,42 @@ FUZZ_TARGET(clusterlin_depgraph_serialization)
|
||||||
// Construct a graph by deserializing.
|
// Construct a graph by deserializing.
|
||||||
SpanReader reader(buffer);
|
SpanReader reader(buffer);
|
||||||
DepGraph<TestBitSet> depgraph;
|
DepGraph<TestBitSet> depgraph;
|
||||||
|
ClusterIndex par_code{0}, chl_code{0};
|
||||||
try {
|
try {
|
||||||
reader >> Using<DepGraphFormatter>(depgraph);
|
reader >> Using<DepGraphFormatter>(depgraph) >> VARINT(par_code) >> VARINT(chl_code);
|
||||||
} catch (const std::ios_base::failure&) {}
|
} catch (const std::ios_base::failure&) {}
|
||||||
SanityCheck(depgraph);
|
SanityCheck(depgraph);
|
||||||
|
|
||||||
// Verify the graph is a DAG.
|
// Verify the graph is a DAG.
|
||||||
assert(IsAcyclic(depgraph));
|
assert(depgraph.IsAcyclic());
|
||||||
|
|
||||||
|
// Introduce a cycle, and then test that IsAcyclic returns false.
|
||||||
|
if (depgraph.TxCount() < 2) return;
|
||||||
|
ClusterIndex par(0), chl(0);
|
||||||
|
// Pick any transaction of depgraph as parent.
|
||||||
|
par_code %= depgraph.TxCount();
|
||||||
|
for (auto i : depgraph.Positions()) {
|
||||||
|
if (par_code == 0) {
|
||||||
|
par = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--par_code;
|
||||||
|
}
|
||||||
|
// Pick any ancestor of par (excluding itself) as child, if any.
|
||||||
|
auto ancestors = depgraph.Ancestors(par) - TestBitSet::Singleton(par);
|
||||||
|
if (ancestors.None()) return;
|
||||||
|
chl_code %= ancestors.Count();
|
||||||
|
for (auto i : ancestors) {
|
||||||
|
if (chl_code == 0) {
|
||||||
|
chl = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--chl_code;
|
||||||
|
}
|
||||||
|
// Add the cycle-introducing dependency.
|
||||||
|
depgraph.AddDependencies(TestBitSet::Singleton(par), chl);
|
||||||
|
// Check that we now detect a cycle.
|
||||||
|
assert(!depgraph.IsAcyclic());
|
||||||
}
|
}
|
||||||
|
|
||||||
FUZZ_TARGET(clusterlin_components)
|
FUZZ_TARGET(clusterlin_components)
|
||||||
|
|
|
@ -23,18 +23,6 @@ using namespace cluster_linearize;
|
||||||
|
|
||||||
using TestBitSet = BitSet<32>;
|
using TestBitSet = BitSet<32>;
|
||||||
|
|
||||||
/** Check if a graph is acyclic. */
|
|
||||||
template<typename SetType>
|
|
||||||
bool IsAcyclic(const DepGraph<SetType>& depgraph) noexcept
|
|
||||||
{
|
|
||||||
for (ClusterIndex i : depgraph.Positions()) {
|
|
||||||
if ((depgraph.Ancestors(i) & depgraph.Descendants(i)) != SetType::Singleton(i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A formatter for a bespoke serialization for acyclic DepGraph objects.
|
/** A formatter for a bespoke serialization for acyclic DepGraph objects.
|
||||||
*
|
*
|
||||||
* The serialization format outputs information about transactions in a topological order (parents
|
* The serialization format outputs information about transactions in a topological order (parents
|
||||||
|
@ -337,7 +325,7 @@ void SanityCheck(const DepGraph<SetType>& depgraph)
|
||||||
assert((depgraph.Descendants(child) & children).IsSubsetOf(SetType::Singleton(child)));
|
assert((depgraph.Descendants(child) & children).IsSubsetOf(SetType::Singleton(child)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IsAcyclic(depgraph)) {
|
if (depgraph.IsAcyclic()) {
|
||||||
// If DepGraph is acyclic, serialize + deserialize must roundtrip.
|
// If DepGraph is acyclic, serialize + deserialize must roundtrip.
|
||||||
std::vector<unsigned char> ser;
|
std::vector<unsigned char> ser;
|
||||||
VectorWriter writer(ser, 0);
|
VectorWriter writer(ser, 0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue