@@ -1001,9 +1001,12 @@ bool Cluster::Split(TxGraphImpl& graph, int level) noexcept
10011001 // Iterate over the connected components of this Cluster's m_depgraph.
10021002 while (todo.Any ()) {
10031003 auto component = m_depgraph.FindConnectedComponent (todo);
1004- auto split_quality = component.Count () <= 2 ? QualityLevel::OPTIMAL : new_quality;
1005- if (first && component == todo) {
1006- // The existing Cluster is an entire component. Leave it be, but update its quality.
1004+ auto component_size = component.Count ();
1005+ auto split_quality = component_size <= 2 ? QualityLevel::OPTIMAL : new_quality;
1006+ if (first && component == todo && SetType::Fill (component_size) == component) {
1007+ // The existing Cluster is an entire component, without holes. Leave it be, but update
1008+ // its quality. If there are holes, we continue, so that the Cluster is reconstructed
1009+ // without holes, reducing memory usage.
10071010 Assume (todo == m_depgraph.Positions ());
10081011 graph.SetClusterQuality (level, m_quality, m_setindex, split_quality);
10091012 // If this made the quality ACCEPTABLE or OPTIMAL, we need to compute and cache its
@@ -1064,12 +1067,11 @@ void Cluster::Merge(TxGraphImpl& graph, int level, Cluster& other) noexcept
10641067 auto idx = other.m_mapping [pos];
10651068 // Copy the transaction into this Cluster, and remember its position.
10661069 auto new_pos = m_depgraph.AddTransaction (other.m_depgraph .FeeRate (pos));
1070+ // Since this cluster must have been made hole-free before being merged into, all added
1071+ // transactions should appear at the end.
1072+ Assume (new_pos == m_mapping.size ());
10671073 remap[pos] = new_pos;
1068- if (new_pos == m_mapping.size ()) {
1069- m_mapping.push_back (idx);
1070- } else {
1071- m_mapping[new_pos] = idx;
1072- }
1074+ m_mapping.push_back (idx);
10731075 m_linearization.push_back (new_pos);
10741076 // Copy the transaction's dependencies, translating them using remap. Note that since
10751077 // pos iterates over other.m_linearization, which is in topological order, all parents
@@ -2286,6 +2288,10 @@ void Cluster::SanityCheck(const TxGraphImpl& graph, int level) const
22862288 assert (m_depgraph.PositionRange () == m_mapping.size ());
22872289 // The linearization for this Cluster must contain every transaction once.
22882290 assert (m_depgraph.TxCount () == m_linearization.size ());
2291+ // Unless a split is to be applied, the cluster cannot have any holes.
2292+ if (!NeedsSplitting ()) {
2293+ assert (m_depgraph.Positions () == SetType::Fill (m_depgraph.TxCount ()));
2294+ }
22892295
22902296 // Compute the chunking of m_linearization.
22912297 LinearizationChunking linchunking (m_depgraph, m_linearization);
0 commit comments