From 2c5cf987e96a3e8f783d370a8bc8914f5a4a9682 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 31 Mar 2025 12:47:10 -0400 Subject: [PATCH 1/4] TxGraphImpl::PullIn: only allowed when staging exists --- src/txgraph.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 8fb5300a664..0d66780c11c 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -411,8 +411,8 @@ public: * values for remaining Entry objects, so this only does something when no to-be-applied * operations or staged removals referring to GraphIndexes remain). */ void Compact() noexcept; - /** If cluster is not in staging, copy it there, and return a pointer to it. This has no - * effect if only a main graph exists, but if staging exists this modifies the locators of its + /** If cluster is not in staging, copy it there, and return a pointer to it. + * Staging must exist, and this modifies the locators of its * transactions from inherited (P,M) to explicit (P,P). */ Cluster* PullIn(Cluster* cluster) noexcept; /** Apply all removals queued up in m_to_remove to the relevant Clusters (which get a @@ -928,7 +928,7 @@ Cluster* TxGraphImpl::FindCluster(GraphIndex idx, int level) const noexcept Cluster* TxGraphImpl::PullIn(Cluster* cluster) noexcept { int to_level = GetTopLevel(); - if (to_level == 0) return cluster; + Assume(to_level == 1); int level = cluster->m_level; Assume(level <= to_level); // Copy the Cluster from main to staging, if it's not already there. From 8bca0d325a4ffa13a171eaed83096003aa28520e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 31 Mar 2025 12:48:07 -0400 Subject: [PATCH 2/4] TxGraphImpl::Compact: m_main_clusterset.m_removed is always empty --- src/txgraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 0d66780c11c..fa1395273da 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -1008,7 +1008,7 @@ void TxGraphImpl::Compact() noexcept // to rewrite them. It is easier to delay the compaction until they have been applied. if (!m_main_clusterset.m_deps_to_add.empty()) return; if (!m_main_clusterset.m_to_remove.empty()) return; - if (!m_main_clusterset.m_removed.empty()) return; + Assume(m_main_clusterset.m_removed.empty()); // non-staging m_removed is always empty if (m_staging_clusterset.has_value()) { if (!m_staging_clusterset->m_deps_to_add.empty()) return; if (!m_staging_clusterset->m_to_remove.empty()) return; From 57433502e6756b0dea7332026f3abf926daf0e35 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 31 Mar 2025 13:01:54 -0400 Subject: [PATCH 3/4] CountDistinctClusters: nullptrs disallowed --- src/txgraph.cpp | 2 +- src/txgraph.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index fa1395273da..22dce81fee1 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -1880,7 +1880,7 @@ TxGraph::GraphIndex TxGraphImpl::CountDistinctClusters(std::span clusters; clusters.reserve(refs.size()); for (const Ref* ref : refs) { - if (ref == nullptr) continue; + Assume(ref); if (GetRefGraph(*ref) == nullptr) continue; Assume(GetRefGraph(*ref) == this); auto cluster = FindCluster(GetRefIndex(*ref), level); diff --git a/src/txgraph.h b/src/txgraph.h index 803696440c2..91c3bd5cb17 100644 --- a/src/txgraph.h +++ b/src/txgraph.h @@ -159,8 +159,8 @@ public: virtual std::strong_ordering CompareMainOrder(const Ref& a, const Ref& b) noexcept = 0; /** Count the number of distinct clusters that the specified transactions belong to. If * main_only is false and a staging graph exists, staging clusters are counted. Otherwise, - * main clusters are counted. Refs that do not exist in the queried graph are ignored. The - * queried graph must not be oversized. */ + * main clusters are counted. Refs that do not exist in the queried graph are ignored. Refs + * can not be null. The queried graph must not be oversized. */ virtual GraphIndex CountDistinctClusters(std::span, bool main_only = false) noexcept = 0; /** Perform an internal consistency check on this object. */ From a40bd374aaf8e10116fa664fa7b480d85ee2fe59 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 31 Mar 2025 13:05:20 -0400 Subject: [PATCH 4/4] Get*Union: disallow nulltpr Refs --- src/txgraph.cpp | 2 ++ src/txgraph.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 22dce81fee1..9e4bf116b02 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -1595,6 +1595,7 @@ std::vector TxGraphImpl::GetAncestorsUnion(std::span> matches; matches.reserve(args.size()); for (auto arg : args) { + Assume(arg); // Skip empty Refs. if (GetRefGraph(*arg) == nullptr) continue; Assume(GetRefGraph(*arg) == this); @@ -1627,6 +1628,7 @@ std::vector TxGraphImpl::GetDescendantsUnion(std::span> matches; matches.reserve(args.size()); for (auto arg : args) { + Assume(arg); // Skip empty Refs. if (GetRefGraph(*arg) == nullptr) continue; Assume(GetRefGraph(*arg) == this); diff --git a/src/txgraph.h b/src/txgraph.h index 91c3bd5cb17..cdfb2fe6dec 100644 --- a/src/txgraph.h +++ b/src/txgraph.h @@ -144,11 +144,11 @@ public: virtual std::vector GetDescendants(const Ref& arg, bool main_only = false) noexcept = 0; /** Like GetAncestors, but return the Refs for all transactions in the union of the provided * arguments' ancestors (each transaction is only reported once). Refs that do not exist in - * the queried graph are ignored. */ + * the queried graph are ignored. Null refs are not allowed. */ virtual std::vector GetAncestorsUnion(std::span args, bool main_only = false) noexcept = 0; /** Like GetDescendants, but return the Refs for all transactions in the union of the provided * arguments' descendants (each transaction is only reported once). Refs that do not exist in - * the queried graph are ignored. */ + * the queried graph are ignored. Null refs are not allowed. */ virtual std::vector GetDescendantsUnion(std::span args, bool main_only = false) noexcept = 0; /** Get the total number of transactions in the graph. If main_only is false and a staging * graph exists, it is queried; otherwise the main graph is queried. This is available even