diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 48a18312838..e4e4903c618 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -153,8 +153,9 @@ public: * union of their descendants to output. */ void GetDescendantRefs(const TxGraphImpl& graph, std::span>& args, std::vector& output) noexcept; /** Populate range with refs for the transactions in this Cluster's linearization, from - * position start_pos until start_pos+range.size()-1, inclusive. */ - void GetClusterRefs(TxGraphImpl& graph, std::span range, LinearizationIndex start_pos) noexcept; + * position start_pos until start_pos+range.size()-1, inclusive. Returns whether that + * range includes the last transaction in the linearization. */ + bool GetClusterRefs(TxGraphImpl& graph, std::span range, LinearizationIndex start_pos) noexcept; /** Get the individual transaction feerate of a Cluster element. */ FeePerWeight GetIndividualFeerate(DepGraphIndex idx) noexcept; /** Modify the fee of a Cluster element. */ @@ -586,6 +587,8 @@ class BlockBuilderImpl final : public TxGraph::BlockBuilder /** Which cluster the current chunk belongs to, so we can exclude further transactions from it * when that chunk is skipped. */ Cluster* m_cur_cluster; + /** Whether we know that m_cur_iter points to the last chunk of m_cur_cluster. */ + bool m_known_end_of_cluster; // Move m_cur_iter / m_cur_cluster to the next acceptable chunk. void Next() noexcept; @@ -1692,7 +1695,7 @@ void Cluster::GetDescendantRefs(const TxGraphImpl& graph, std::span range, LinearizationIndex start_pos) noexcept +bool Cluster::GetClusterRefs(TxGraphImpl& graph, std::span range, LinearizationIndex start_pos) noexcept { // Translate the transactions in the Cluster (in linearization order, starting at start_pos in // the linearization) to Refs, and fill them in range. @@ -1702,6 +1705,8 @@ void Cluster::GetClusterRefs(TxGraphImpl& graph, std::span range, Assume(entry.m_ref != nullptr); ref = entry.m_ref; } + // Return whether start_pos has advanced to the end of the Cluster. + return start_pos == m_linearization.size(); } FeePerWeight Cluster::GetIndividualFeerate(DepGraphIndex idx) noexcept @@ -2338,6 +2343,7 @@ void BlockBuilderImpl::Next() noexcept const auto& chunk_data = *m_cur_iter; const auto& chunk_end_entry = m_graph->m_entries[chunk_data.m_graph_index]; m_cur_cluster = chunk_end_entry.m_locator[0].cluster; + m_known_end_of_cluster = false; // If we previously skipped a chunk from this cluster we cannot include more from it. if (!m_excluded_clusters.contains(m_cur_cluster)) break; } @@ -2354,7 +2360,7 @@ std::optional, FeePerWeight>> BlockBuilderI ret->first.resize(chunk_data.m_chunk_count); auto start_pos = chunk_end_entry.m_main_lin_index + 1 - chunk_data.m_chunk_count; Assume(m_cur_cluster); - m_cur_cluster->GetClusterRefs(*m_graph, ret->first, start_pos); + m_known_end_of_cluster = m_cur_cluster->GetClusterRefs(*m_graph, ret->first, start_pos); ret->second = chunk_end_entry.m_main_chunk_feerate; } return ret; @@ -2397,8 +2403,12 @@ void BlockBuilderImpl::Include() noexcept void BlockBuilderImpl::Skip() noexcept { // When skipping a chunk we need to not include anything more of the cluster, as that could make - // the result topologically invalid. - if (m_cur_cluster != nullptr) m_excluded_clusters.insert(m_cur_cluster); + // the result topologically invalid. However, don't do this if the chunk is known to be the last + // chunk of the cluster. This may significantly reduce the size of m_excluded_clusters, + // especially when many singleton clusters are ignored. + if (m_cur_cluster != nullptr && !m_known_end_of_cluster) { + m_excluded_clusters.insert(m_cur_cluster); + } Next(); }