aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2024-08-08 21:42:28 -0400
committerPieter Wuille <pieter@wuille.net>2024-09-12 15:15:36 -0400
commitb80e6dfe780b3678bb41f2d9d63816f097529b2e (patch)
treecfbbfbacd06b204d4db1e166c07816994af77e72
parent85a285a306100d1815c4ad0f4e52ccbcae8b0fbc (diff)
clusterlin: add reordering support for DepGraph
Add a DepGraph(depgraph, reordering) function that constructs a new DepGraph corresponding to an old one, but with its transactions is a modified order (given as a vector from old to new positions). Also use this reordering feature inside DepGraphFormatter::Unser, which needs a small modification so that its reordering mapping is old-to-new (rather than the new-to-old it used before).
-rw-r--r--src/cluster_linearize.h22
-rw-r--r--src/test/util/cluster_linearize.h38
2 files changed, 37 insertions, 23 deletions
diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h
index a52ea5c379..7e74460c7e 100644
--- a/src/cluster_linearize.h
+++ b/src/cluster_linearize.h
@@ -118,6 +118,28 @@ public:
}
}
+ /** Construct a DepGraph object given another DepGraph and a mapping from old to new.
+ *
+ * Complexity: O(N^2) where N=depgraph.TxCount().
+ */
+ DepGraph(const DepGraph<SetType>& depgraph, Span<const ClusterIndex> mapping) noexcept : entries(depgraph.TxCount())
+ {
+ Assert(mapping.size() == depgraph.TxCount());
+ // Fill in fee, size, ancestors.
+ for (ClusterIndex i = 0; i < depgraph.TxCount(); ++i) {
+ const auto& input = depgraph.entries[i];
+ auto& output = entries[mapping[i]];
+ output.feerate = input.feerate;
+ for (auto j : input.ancestors) output.ancestors.Set(mapping[j]);
+ }
+ // Fill in descendant information.
+ for (ClusterIndex i = 0; i < entries.size(); ++i) {
+ for (auto j : entries[i].ancestors) {
+ entries[j].descendants.Set(i);
+ }
+ }
+ }
+
/** Get the number of transactions in the graph. Complexity: O(1). */
auto TxCount() const noexcept { return entries.size(); }
/** Get the feerate of a given transaction i. Complexity: O(1). */
diff --git a/src/test/util/cluster_linearize.h b/src/test/util/cluster_linearize.h
index 9477d2ed41..5336d6015c 100644
--- a/src/test/util/cluster_linearize.h
+++ b/src/test/util/cluster_linearize.h
@@ -186,7 +186,7 @@ struct DepGraphFormatter
/** The dependency graph which we deserialize into first, with transactions in
* topological serialization order, not original cluster order. */
DepGraph<SetType> topo_depgraph;
- /** Mapping from cluster order to serialization order, used later to reconstruct the
+ /** Mapping from serialization order to cluster order, used later to reconstruct the
* cluster order. */
std::vector<ClusterIndex> reordering;
@@ -205,9 +205,9 @@ struct DepGraphFormatter
coded_fee &= 0xFFFFFFFFFFFFF; // Enough for fee between -21M...21M BTC.
static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
auto fee = UnsignedToSigned(coded_fee);
- // Extend topo_depgraph with the new transaction (at the end).
+ // Extend topo_depgraph with the new transaction (preliminarily at the end).
auto topo_idx = topo_depgraph.AddTransaction({fee, size});
- reordering.push_back(topo_idx);
+ reordering.push_back(reordering.size());
// Read dependency information.
uint64_t diff = 0; //!< How many potential parents we have to skip.
s >> VARINT(diff);
@@ -226,31 +226,23 @@ struct DepGraphFormatter
--diff;
}
}
- // If we reach this point, we can interpret the remaining skip value as how far from the
- // end of reordering topo_idx should be placed (wrapping around), so move it to its
- // correct location. The preliminary reordering.push_back(topo_idx) above was to make
- // sure that if a deserialization exception occurs, topo_idx still appears somewhere.
+ // If we reach this point, we can interpret the remaining skip value as how far
+ // from the end of reordering the new transaction should be placed (wrapping
+ // around), so remove the preliminary position it was put in above (which was to
+ // make sure that if a deserialization exception occurs, the new transaction still
+ // has some entry in reordering).
reordering.pop_back();
- reordering.insert(reordering.end() - (diff % (reordering.size() + 1)), topo_idx);
+ ClusterIndex insert_distance = diff % (reordering.size() + 1);
+ // And then update reordering to reflect this new transaction's insertion.
+ for (auto& pos : reordering) {
+ pos += (pos >= reordering.size() - insert_distance);
+ }
+ reordering.push_back(reordering.size() - insert_distance);
}
} catch (const std::ios_base::failure&) {}
// Construct the original cluster order depgraph.
- depgraph = {};
- // Add transactions to depgraph in the original cluster order.
- for (auto topo_idx : reordering) {
- depgraph.AddTransaction(topo_depgraph.FeeRate(topo_idx));
- }
- // Translate dependencies from topological to cluster order.
- for (ClusterIndex idx = 0; idx < reordering.size(); ++idx) {
- ClusterIndex topo_idx = reordering[idx];
- for (ClusterIndex dep_idx = 0; dep_idx < reordering.size(); ++dep_idx) {
- ClusterIndex dep_topo_idx = reordering[dep_idx];
- if (topo_depgraph.Ancestors(topo_idx)[dep_topo_idx]) {
- depgraph.AddDependency(dep_idx, idx);
- }
- }
- }
+ depgraph = DepGraph(topo_depgraph, reordering);
}
};