5#ifndef BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
6#define BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
103 return 2 * uint64_t(-(x + 1)) + 1;
105 return 2 * uint64_t(x);
113 return -int64_t(x / 2) - 1;
115 return int64_t(x / 2);
119 template <
typename Stream,
typename SetType>
123 std::vector<DepGraphIndex> topo_order;
124 topo_order.reserve(depgraph.
TxCount());
125 for (
auto i : depgraph.
Positions()) topo_order.push_back(i);
127 auto anc_a = depgraph.Ancestors(a).Count(), anc_b = depgraph.Ancestors(b).Count();
128 if (anc_a != anc_b) return anc_a < anc_b;
137 for (
DepGraphIndex topo_idx = 0; topo_idx < topo_order.size(); ++topo_idx) {
145 SetType written_parents;
147 for (
DepGraphIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
151 if (depgraph.
Descendants(dep_idx).Overlaps(written_parents))
continue;
157 written_parents.Set(dep_idx);
164 auto add_holes = SetType::Fill(idx) - done - depgraph.
Positions();
165 if (add_holes.None()) {
168 auto skips = (done - SetType::Fill(idx)).Count();
174 s <<
VARINT(diff + done.Count() + add_holes.Count());
184 template <
typename Stream,
typename SetType>
192 std::vector<DepGraphIndex> reordering;
199 SetType new_ancestors;
201 bool read_error{
false};
207 static_assert(0x3FFFFF >= 4000000);
208 if (size == 0 || topo_depgraph.
TxCount() == SetType::Size())
break;
212 coded_fee &= 0xFFFFFFFFFFFFF;
213 static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
216 auto topo_idx = reordering.size();
218 for (
DepGraphIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
222 if (new_ancestors[dep_topo_idx])
continue;
225 new_ancestors |= topo_depgraph.
Ancestors(dep_topo_idx);
233 }
catch (
const std::ios_base::failure&) {
238 if (new_feerate.
IsEmpty())
break;
239 assert(reordering.size() < SetType::Size());
242 if (total_size < SetType::Size()) {
244 diff %= SetType::Size();
245 if (diff <= total_size) {
247 for (
auto& pos : reordering) {
248 pos += (pos >= total_size - diff);
250 reordering.push_back(total_size++ - diff);
254 reordering.push_back(total_size++);
262 diff %= (SetType::Size() - reordering.size());
263 SetType holes = SetType::Fill(SetType::Size());
264 for (
auto pos : reordering) holes.Reset(pos);
265 for (
auto pos : holes) {
267 reordering.push_back(pos);
274 if (read_error)
break;
278 depgraph =
DepGraph(topo_depgraph, reordering, total_size);
283template<
typename SetType>
291 position_range = i + 1;
295 assert(position_range >= num_positions);
296 assert(position_range <= SetType::Size());
318 for (
auto parent : parents) {
319 assert((depgraph.
Ancestors(parent) & parents).IsSubsetOf(SetType::Singleton(parent)));
322 for (
auto child : children) {
323 assert((depgraph.
Descendants(child) & children).IsSubsetOf(SetType::Singleton(child)));
328 std::vector<unsigned char> ser;
330 writer << Using<DepGraphFormatter>(depgraph);
333 reader >> Using<DepGraphFormatter>(decoded_depgraph);
334 assert(depgraph == decoded_depgraph);
338 assert(ser.size() >= 1 && ser.back() == 0);
341 decoded_depgraph = {};
342 reader >> Using<DepGraphFormatter>(decoded_depgraph);
343 assert(depgraph == decoded_depgraph);
355 SetType ancestors = SetType::Singleton(i);
358 const auto old_ancestors = ancestors;
359 for (
auto j : ancestors) ancestors |= parents[j];
361 if (old_ancestors == ancestors)
break;
366 SetType descendants = SetType::Singleton(i);
369 const auto old_descendants = descendants;
370 for (
auto j : descendants) descendants |= children[j];
372 if (old_descendants == descendants)
break;
380template<
typename SetType>
386 for (
auto i : linearization) {
401 static constexpr uint64_t COSTS[65] = {
403 0, 545, 928, 1633, 2647, 4065, 5598, 8258,
404 9505, 11471, 14137, 19553, 20460, 26191, 28397, 32599,
405 41631, 47419, 56329, 57767, 72196, 63652, 95366, 96537,
406 115653, 125407, 131734, 145090, 156349, 164665, 194224, 203953,
407 207710, 225878, 239971, 252284, 256534, 222142, 251332, 357098,
408 325788, 295867, 410053, 497483, 533892, 576572, 577845, 572400,
409 592536, 455082, 609249, 659130, 714091, 544507, 718788, 562378,
410 601926, 1025081, 732725, 708896, 738224, 900445, 1092519, 1139946
412 assert(cluster_count < std::size(COSTS));
414 return COSTS[cluster_count] * 2;
std::conditional_t<(BITS<=32), bitset_detail::IntBitSet< uint32_t >, std::conditional_t<(BITS<=std::numeric_limits< size_t >::digits), bitset_detail::IntBitSet< size_t >, bitset_detail::MultiIntBitSet< size_t, CeilDiv(BITS, size_t{std::numeric_limits< size_t >::digits})> > > BitSet
Minimal stream for reading from an existing byte array by std::span.
Data structure that holds a transaction graph's preprocessed data (fee, size, ancestors,...
const SetType & Ancestors(DepGraphIndex i) const noexcept
Get the ancestors of a given transaction i.
SetType GetReducedChildren(DepGraphIndex i) const noexcept
Compute the (reduced) set of children of node i in this graph.
SetType GetReducedParents(DepGraphIndex i) const noexcept
Compute the (reduced) set of parents of node i in this graph.
const FeeFrac & FeeRate(DepGraphIndex i) const noexcept
Get the feerate of a given transaction i.
DepGraphIndex PositionRange() const noexcept
Get the range of positions in this DepGraph.
DepGraphIndex AddTransaction(const FeeFrac &feefrac) noexcept
Add a new unconnected transaction to this transaction graph (in the first available position),...
auto TxCount() const noexcept
Get the number of transactions in the graph.
const SetType & Descendants(DepGraphIndex i) const noexcept
Get the descendants of a given transaction i.
const SetType & Positions() const noexcept
Get the set of transactions positions in use.
void AddDependencies(const SetType &parents, DepGraphIndex child) noexcept
Modify this transaction graph, adding multiple parents to a specified child.
bool IsAcyclic() const noexcept
Check if this graph is acyclic.
uint64_t MaxOptimalLinearizationCost(DepGraphIndex cluster_count)
uint32_t DepGraphIndex
Data type to represent transaction indices in DepGraphs and the clusters they represent.
void SanityCheck(const DepGraph< SetType > &depgraph)
Perform a sanity/consistency check on a DepGraph.
#define VARINT_MODE(obj, mode)
Data structure storing a fee and size.
bool IsEmpty() const noexcept
Check if this is empty (size and fee are 0).