clusterlin: add more Assumes and sanity checks (tests)

This commit is contained in:
Pieter Wuille committed 2026-02-17 09:04:36 -05:00
1 parent d69c9f56ea
commit 268fcb6a53
1 file changed
+16 -2
+16 -2
View File
@@ -865,6 +865,7 @@ private:
--pick; --pick;
} }
} }
Assume(false);
break; break;
} }
pick -= count; pick -= count;
@@ -1031,6 +1032,7 @@ public:
/** Make state topological. Can be called after constructing, or after LoadLinearization. */ /** Make state topological. Can be called after constructing, or after LoadLinearization. */
void MakeTopological() noexcept void MakeTopological() noexcept
{ {
Assume(m_suboptimal_chunks.empty());
for (auto tx : m_transaction_idxs) { for (auto tx : m_transaction_idxs) {
auto& tx_data = m_tx_data[tx]; auto& tx_data = m_tx_data[tx];
if (tx_data.chunk_rep == tx) { if (tx_data.chunk_rep == tx) {
@@ -1074,6 +1076,7 @@ public:
/** Initialize the data structure for optimization. It must be topological already. */ /** Initialize the data structure for optimization. It must be topological already. */
void StartOptimizing() noexcept void StartOptimizing() noexcept
{ {
Assume(m_suboptimal_chunks.empty());
// Mark chunks suboptimal. // Mark chunks suboptimal.
for (auto tx : m_transaction_idxs) { for (auto tx : m_transaction_idxs) {
auto& tx_data = m_tx_data[tx]; auto& tx_data = m_tx_data[tx];
@@ -1469,6 +1472,7 @@ public:
// //
// Verify the chunks against the list of active dependencies // Verify the chunks against the list of active dependencies
// //
SetType chunk_cover;
for (auto tx_idx: m_depgraph.Positions()) { for (auto tx_idx: m_depgraph.Positions()) {
// Only process chunks for now. // Only process chunks for now.
if (m_tx_data[tx_idx].chunk_rep == tx_idx) { if (m_tx_data[tx_idx].chunk_rep == tx_idx) {
@@ -1478,6 +1482,8 @@ public:
for (auto chunk_tx : chunk_data.chunk_setinfo.transactions) { for (auto chunk_tx : chunk_data.chunk_setinfo.transactions) {
assert(m_tx_data[chunk_tx].chunk_rep == tx_idx); assert(m_tx_data[chunk_tx].chunk_rep == tx_idx);
} }
assert(!chunk_cover.Overlaps(chunk_data.chunk_setinfo.transactions));
chunk_cover |= chunk_data.chunk_setinfo.transactions;
// Verify the chunk's transaction set: it must contain the representative, and for // Verify the chunk's transaction set: it must contain the representative, and for
// every active dependency, if it contains the parent or child, it must contain // every active dependency, if it contains the parent or child, it must contain
// both. It must have exactly N-1 active dependencies in it, guaranteeing it is // both. It must have exactly N-1 active dependencies in it, guaranteeing it is
@@ -1504,6 +1510,8 @@ public:
m_depgraph.FeeRate(chunk_data.chunk_setinfo.transactions)); m_depgraph.FeeRate(chunk_data.chunk_setinfo.transactions));
} }
} }
// Verify that together, the chunks cover all transactions.
assert(chunk_cover == m_depgraph.Positions());
// //
// Verify other transaction data. // Verify other transaction data.
@@ -1539,17 +1547,23 @@ public:
const auto& dep_data = m_dep_data[dep_idx]; const auto& dep_data = m_dep_data[dep_idx];
// Verify the top_info's transactions: it must contain the parent, and for every // Verify the top_info's transactions: it must contain the parent, and for every
// active dependency, except dep_idx itself, if it contains the parent or child, it // active dependency, except dep_idx itself, if it contains the parent or child, it
// must contain both. // must contain both. It must have exactly N-1 active dependencies in it, guaranteeing
// it is acyclic.
SetType expected_top = SetType::Singleton(par_idx); SetType expected_top = SetType::Singleton(par_idx);
while (true) { while (true) {
auto old = expected_top; auto old = expected_top;
size_t active_dep_count{0};
for (const auto& [par2_idx, chl2_idx, dep2_idx] : active_dependencies) { for (const auto& [par2_idx, chl2_idx, dep2_idx] : active_dependencies) {
if (dep2_idx != dep_idx && (expected_top[par2_idx] || expected_top[chl2_idx])) { if (dep2_idx != dep_idx && (expected_top[par2_idx] || expected_top[chl2_idx])) {
expected_top.Set(par2_idx); expected_top.Set(par2_idx);
expected_top.Set(chl2_idx); expected_top.Set(chl2_idx);
++active_dep_count;
} }
} }
if (old == expected_top) break; if (old == expected_top) {
assert(expected_top.Count() == active_dep_count + 1);
break;
}
} }
assert(!expected_top[chl_idx]); assert(!expected_top[chl_idx]);
assert(dep_data.top_setinfo.transactions == expected_top); assert(dep_data.top_setinfo.transactions == expected_top);