Skip to content

Commit b80e6df

Browse files
committed
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).
1 parent 85a285a commit b80e6df

File tree

2 files changed

+37
-23
lines changed

2 files changed

+37
-23
lines changed

src/cluster_linearize.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,28 @@ class DepGraph
118118
}
119119
}
120120

121+
/** Construct a DepGraph object given another DepGraph and a mapping from old to new.
122+
*
123+
* Complexity: O(N^2) where N=depgraph.TxCount().
124+
*/
125+
DepGraph(const DepGraph<SetType>& depgraph, Span<const ClusterIndex> mapping) noexcept : entries(depgraph.TxCount())
126+
{
127+
Assert(mapping.size() == depgraph.TxCount());
128+
// Fill in fee, size, ancestors.
129+
for (ClusterIndex i = 0; i < depgraph.TxCount(); ++i) {
130+
const auto& input = depgraph.entries[i];
131+
auto& output = entries[mapping[i]];
132+
output.feerate = input.feerate;
133+
for (auto j : input.ancestors) output.ancestors.Set(mapping[j]);
134+
}
135+
// Fill in descendant information.
136+
for (ClusterIndex i = 0; i < entries.size(); ++i) {
137+
for (auto j : entries[i].ancestors) {
138+
entries[j].descendants.Set(i);
139+
}
140+
}
141+
}
142+
121143
/** Get the number of transactions in the graph. Complexity: O(1). */
122144
auto TxCount() const noexcept { return entries.size(); }
123145
/** Get the feerate of a given transaction i. Complexity: O(1). */

src/test/util/cluster_linearize.h

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ struct DepGraphFormatter
186186
/** The dependency graph which we deserialize into first, with transactions in
187187
* topological serialization order, not original cluster order. */
188188
DepGraph<SetType> topo_depgraph;
189-
/** Mapping from cluster order to serialization order, used later to reconstruct the
189+
/** Mapping from serialization order to cluster order, used later to reconstruct the
190190
* cluster order. */
191191
std::vector<ClusterIndex> reordering;
192192

@@ -205,9 +205,9 @@ struct DepGraphFormatter
205205
coded_fee &= 0xFFFFFFFFFFFFF; // Enough for fee between -21M...21M BTC.
206206
static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
207207
auto fee = UnsignedToSigned(coded_fee);
208-
// Extend topo_depgraph with the new transaction (at the end).
208+
// Extend topo_depgraph with the new transaction (preliminarily at the end).
209209
auto topo_idx = topo_depgraph.AddTransaction({fee, size});
210-
reordering.push_back(topo_idx);
210+
reordering.push_back(reordering.size());
211211
// Read dependency information.
212212
uint64_t diff = 0; //!< How many potential parents we have to skip.
213213
s >> VARINT(diff);
@@ -226,31 +226,23 @@ struct DepGraphFormatter
226226
--diff;
227227
}
228228
}
229-
// If we reach this point, we can interpret the remaining skip value as how far from the
230-
// end of reordering topo_idx should be placed (wrapping around), so move it to its
231-
// correct location. The preliminary reordering.push_back(topo_idx) above was to make
232-
// sure that if a deserialization exception occurs, topo_idx still appears somewhere.
229+
// If we reach this point, we can interpret the remaining skip value as how far
230+
// from the end of reordering the new transaction should be placed (wrapping
231+
// around), so remove the preliminary position it was put in above (which was to
232+
// make sure that if a deserialization exception occurs, the new transaction still
233+
// has some entry in reordering).
233234
reordering.pop_back();
234-
reordering.insert(reordering.end() - (diff % (reordering.size() + 1)), topo_idx);
235+
ClusterIndex insert_distance = diff % (reordering.size() + 1);
236+
// And then update reordering to reflect this new transaction's insertion.
237+
for (auto& pos : reordering) {
238+
pos += (pos >= reordering.size() - insert_distance);
239+
}
240+
reordering.push_back(reordering.size() - insert_distance);
235241
}
236242
} catch (const std::ios_base::failure&) {}
237243

238244
// Construct the original cluster order depgraph.
239-
depgraph = {};
240-
// Add transactions to depgraph in the original cluster order.
241-
for (auto topo_idx : reordering) {
242-
depgraph.AddTransaction(topo_depgraph.FeeRate(topo_idx));
243-
}
244-
// Translate dependencies from topological to cluster order.
245-
for (ClusterIndex idx = 0; idx < reordering.size(); ++idx) {
246-
ClusterIndex topo_idx = reordering[idx];
247-
for (ClusterIndex dep_idx = 0; dep_idx < reordering.size(); ++dep_idx) {
248-
ClusterIndex dep_topo_idx = reordering[dep_idx];
249-
if (topo_depgraph.Ancestors(topo_idx)[dep_topo_idx]) {
250-
depgraph.AddDependency(dep_idx, idx);
251-
}
252-
}
253-
}
245+
depgraph = DepGraph(topo_depgraph, reordering);
254246
}
255247
};
256248

0 commit comments

Comments
 (0)