diff options
author | Pieter Wuille <pieter@wuille.net> | 2024-08-08 21:42:28 -0400 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2024-09-12 15:15:36 -0400 |
commit | b80e6dfe780b3678bb41f2d9d63816f097529b2e (patch) | |
tree | cfbbfbacd06b204d4db1e166c07816994af77e72 | |
parent | 85a285a306100d1815c4ad0f4e52ccbcae8b0fbc (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.h | 22 | ||||
-rw-r--r-- | src/test/util/cluster_linearize.h | 38 |
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); } }; |