Skip to content

Commit 0a1e36e

Browse files
committed
Merge bitcoin/bitcoin#32151: Follow-ups for txgraph #31363
a52b539 clusterlin: add GetConnectedComponent (Pieter Wuille) c7d5dca clusterlin: fix typos (Pieter Wuille) 777179b txgraph: rename group_data in ApplyDependencies (Pieter Wuille) Pull request description: This addresses a few review comments in #31363 after merge: * bitcoin/bitcoin#31363 (comment) (rename `group_data` to `group_entry`) * bitcoin/bitcoin#31363 (comment) (introduce `GetConnectedComponent` and use it in the txgraph fuzz test). * bitcoin/bitcoin#31363 (comment) (typo in `FixLinearization`) * bitcoin/bitcoin#32151 (comment) (more typos) ACKs for top commit: instagibbs: ACK bitcoin/bitcoin@a52b539 glozow: ACK a52b539 Tree-SHA512: e8a98101ecb9c09b860306c7fbd22cf20bd12990768879753680dfbf7db31283506d9f30bb7ee726daebd90c34a1c565d07b3e1147b2a87426247acb19058ed3
2 parents e3c4bb1 + a52b539 commit 0a1e36e

File tree

5 files changed

+54
-38
lines changed

5 files changed

+54
-38
lines changed

src/cluster_linearize.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,8 @@ class DepGraph
250250
return ret;
251251
}
252252

253-
/** Find some connected component within the subset "todo" of this graph.
254-
*
255-
* Specifically, this finds the connected component which contains the first transaction of
256-
* todo (if any).
253+
/** Get the connected component within the subset "todo" that contains tx (which must be in
254+
* todo).
257255
*
258256
* Two transactions are considered connected if they are both in `todo`, and one is an ancestor
259257
* of the other in the entire graph (so not just within `todo`), or transitively there is a
@@ -262,10 +260,11 @@ class DepGraph
262260
*
263261
* Complexity: O(ret.Count()).
264262
*/
265-
SetType FindConnectedComponent(const SetType& todo) const noexcept
263+
SetType GetConnectedComponent(const SetType& todo, DepGraphIndex tx) const noexcept
266264
{
267-
if (todo.None()) return todo;
268-
auto to_add = SetType::Singleton(todo.First());
265+
Assume(todo[tx]);
266+
Assume(todo.IsSubsetOf(m_used));
267+
auto to_add = SetType::Singleton(tx);
269268
SetType ret;
270269
do {
271270
SetType old = ret;
@@ -279,6 +278,19 @@ class DepGraph
279278
return ret;
280279
}
281280

281+
/** Find some connected component within the subset "todo" of this graph.
282+
*
283+
* Specifically, this finds the connected component which contains the first transaction of
284+
* todo (if any).
285+
*
286+
* Complexity: O(ret.Count()).
287+
*/
288+
SetType FindConnectedComponent(const SetType& todo) const noexcept
289+
{
290+
if (todo.None()) return todo;
291+
return GetConnectedComponent(todo, todo.First());
292+
}
293+
282294
/** Determine if a subset is connected.
283295
*
284296
* Complexity: O(subset.Count()).
@@ -1367,7 +1379,7 @@ void FixLinearization(const DepGraph<SetType>& depgraph, std::span<DepGraphIndex
13671379
// in between forward.
13681380
while (place_before.Any()) {
13691381
// j cannot be 0 here; if it was, then there was necessarily nothing earlier which
1370-
// elem needs to be place before anymore, and place_before would be empty.
1382+
// elem needs to be placed before anymore, and place_before would be empty.
13711383
Assume(j > 0);
13721384
auto to_swap = linearization[len - 1 - (j - 1)];
13731385
place_before.Reset(to_swap);

src/test/fuzz/cluster_linearize.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,19 +446,36 @@ FUZZ_TARGET(clusterlin_components)
446446
// Construct a depgraph.
447447
SpanReader reader(buffer);
448448
DepGraph<TestBitSet> depgraph;
449+
std::vector<DepGraphIndex> linearization;
449450
try {
450451
reader >> Using<DepGraphFormatter>(depgraph);
451452
} catch (const std::ios_base::failure&) {}
452453

453454
TestBitSet todo = depgraph.Positions();
454455
while (todo.Any()) {
455-
// Find a connected component inside todo.
456-
auto component = depgraph.FindConnectedComponent(todo);
456+
// Pick a transaction in todo, or nothing.
457+
std::optional<DepGraphIndex> picked;
458+
{
459+
uint64_t picked_num{0};
460+
try {
461+
reader >> VARINT(picked_num);
462+
} catch (const std::ios_base::failure&) {}
463+
if (picked_num < todo.Size() && todo[picked_num]) {
464+
picked = picked_num;
465+
}
466+
}
467+
468+
// Find a connected component inside todo, including picked if any.
469+
auto component = picked ? depgraph.GetConnectedComponent(todo, *picked)
470+
: depgraph.FindConnectedComponent(todo);
457471

458472
// The component must be a subset of todo and non-empty.
459473
assert(component.IsSubsetOf(todo));
460474
assert(component.Any());
461475

476+
// If picked was provided, the component must include it.
477+
if (picked) assert(component[*picked]);
478+
462479
// If todo is the entire graph, and the entire graph is connected, then the component must
463480
// be the entire graph.
464481
if (todo == depgraph.Positions()) {

src/test/fuzz/txgraph.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -561,36 +561,23 @@ FUZZ_TARGET(txgraph)
561561
std::shuffle(refs.begin(), refs.end(), rng);
562562
// Invoke the real function.
563563
auto result = real->CountDistinctClusters(refs, use_main);
564-
// Build a vector with representatives of the clusters the Refs occur in in the
564+
// Build a set with representatives of the clusters the Refs occur in in the
565565
// simulated graph. For each, remember the lowest-index transaction SimPos in the
566566
// cluster.
567-
std::vector<DepGraphIndex> sim_reps;
567+
SimTxGraph::SetType sim_reps;
568568
for (auto ref : refs) {
569569
// Skip Refs that do not occur in the simulated graph.
570570
auto simpos = sel_sim.Find(ref);
571571
if (simpos == SimTxGraph::MISSING) continue;
572-
// Start with component equal to just the Ref's SimPos.
573-
auto component = SimTxGraph::SetType::Singleton(simpos);
574-
// Keep adding ancestors/descendants of all elements in component until it no
575-
// longer changes.
576-
while (true) {
577-
auto old_component = component;
578-
for (auto i : component) {
579-
component |= sel_sim.graph.Ancestors(i);
580-
component |= sel_sim.graph.Descendants(i);
581-
}
582-
if (component == old_component) break;
583-
}
572+
// Find the component that includes ref.
573+
auto component = sel_sim.graph.GetConnectedComponent(sel_sim.graph.Positions(), simpos);
584574
// Remember the lowest-index SimPos in component, as a representative for it.
585575
assert(component.Any());
586-
sim_reps.push_back(component.First());
576+
sim_reps.Set(component.First());
587577
}
588-
// Remove duplicates from sim_reps.
589-
std::sort(sim_reps.begin(), sim_reps.end());
590-
sim_reps.erase(std::unique(sim_reps.begin(), sim_reps.end()), sim_reps.end());
591578
// Compare the number of deduplicated representatives with the value returned by
592579
// the real function.
593-
assert(result == sim_reps.size());
580+
assert(result == sim_reps.Count());
594581
break;
595582
} else if (command-- == 0) {
596583
// DoWork.

src/txgraph.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ class TxGraphImpl final : public TxGraph
335335

336336
// Simple helper functions.
337337

338-
/** Swap the Entrys referred to by a and b. */
338+
/** Swap the Entry referred to by a and the one referred to by b. */
339339
void SwapIndexes(GraphIndex a, GraphIndex b) noexcept;
340340
/** If idx exists in the specified level ClusterSet (explicitly, or in the level below and not
341341
* removed), return the Cluster it is in. Otherwise, return nullptr. */
@@ -408,8 +408,8 @@ class TxGraphImpl final : public TxGraph
408408

409409
// Functions related to various normalization/application steps.
410410
/** Get rid of unlinked Entry objects in m_entries, if possible (this changes the GraphIndex
411-
* values for remaining Entrys, so this only does something when no to-be-applied operations
412-
* or staged removals referring to GraphIndexes remain). */
411+
* values for remaining Entry objects, so this only does something when no to-be-applied
412+
* operations or staged removals referring to GraphIndexes remain). */
413413
void Compact() noexcept;
414414
/** If cluster is not in staging, copy it there, and return a pointer to it. This has no
415415
* effect if only a main graph exists, but if staging exists this modifies the locators of its
@@ -505,7 +505,7 @@ void TxGraphImpl::ClearLocator(int level, GraphIndex idx) noexcept
505505

506506
void Cluster::Updated(TxGraphImpl& graph) noexcept
507507
{
508-
// Update all the Locators for this Cluster's Entrys.
508+
// Update all the Locators for this Cluster's Entry objects.
509509
for (DepGraphIndex idx : m_linearization) {
510510
auto& entry = graph.m_entries[m_mapping[idx]];
511511
entry.m_locator[m_level].SetPresent(this, idx);
@@ -1321,9 +1321,9 @@ void TxGraphImpl::ApplyDependencies(int level) noexcept
13211321
if (clusterset.m_group_data->m_group_oversized) return;
13221322

13231323
// For each group of to-be-merged Clusters.
1324-
for (const auto& group_data : clusterset.m_group_data->m_groups) {
1324+
for (const auto& group_entry : clusterset.m_group_data->m_groups) {
13251325
auto cluster_span = std::span{clusterset.m_group_data->m_group_clusters}
1326-
.subspan(group_data.m_cluster_offset, group_data.m_cluster_count);
1326+
.subspan(group_entry.m_cluster_offset, group_entry.m_cluster_count);
13271327
// Pull in all the Clusters that contain dependencies.
13281328
if (level == 1) {
13291329
for (Cluster*& cluster : cluster_span) {
@@ -1335,7 +1335,7 @@ void TxGraphImpl::ApplyDependencies(int level) noexcept
13351335
// Actually apply all to-be-added dependencies (all parents and children from this grouping
13361336
// belong to the same Cluster at this point because of the merging above).
13371337
auto deps_span = std::span{clusterset.m_deps_to_add}
1338-
.subspan(group_data.m_deps_offset, group_data.m_deps_count);
1338+
.subspan(group_entry.m_deps_offset, group_entry.m_deps_count);
13391339
Assume(!deps_span.empty());
13401340
const auto& loc = m_entries[deps_span[0].second].m_locator[level];
13411341
Assume(loc.IsPresent());
@@ -1937,7 +1937,7 @@ void Cluster::SanityCheck(const TxGraphImpl& graph, int level) const
19371937
assert(m_depgraph.IsConnected(linchunking.GetChunk(0).transactions));
19381938
}
19391939
}
1940-
// Verify that each element of m_depgraph occured in m_linearization.
1940+
// Verify that each element of m_depgraph occurred in m_linearization.
19411941
assert(m_done == m_depgraph.Positions());
19421942
}
19431943

src/txgraph.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class TxGraph
9999
/** Create a staging graph (which cannot exist already). This acts as if a full copy of
100100
* the transaction graph is made, upon which further modifications are made. This copy can
101101
* be inspected, and then either discarded, or the main graph can be replaced by it by
102-
* commiting it. */
102+
* committing it. */
103103
virtual void StartStaging() noexcept = 0;
104104
/** Discard the existing active staging graph (which must exist). */
105105
virtual void AbortStaging() noexcept = 0;

0 commit comments

Comments
 (0)