5#ifndef BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
6#define BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
99struct DepGraphFormatter
102 [[maybe_unused]]
static uint64_t SignedToUnsigned(int64_t x)
noexcept
105 return 2 * uint64_t(-(x + 1)) + 1;
107 return 2 * uint64_t(x);
112 [[maybe_unused]]
static int64_t UnsignedToSigned(uint64_t x)
noexcept
115 return -int64_t(x / 2) - 1;
117 return int64_t(x / 2);
121 template <
typename Stream,
typename SetType>
125 std::vector<DepGraphIndex> topo_order;
126 topo_order.reserve(depgraph.
TxCount());
127 for (
auto i : depgraph.
Positions()) topo_order.push_back(i);
129 auto anc_a = depgraph.Ancestors(a).Count(), anc_b = depgraph.Ancestors(b).Count();
130 if (anc_a != anc_b) return anc_a < anc_b;
139 for (
DepGraphIndex topo_idx = 0; topo_idx < topo_order.size(); ++topo_idx) {
147 SetType written_parents;
149 for (
DepGraphIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
153 if (depgraph.
Descendants(dep_idx).Overlaps(written_parents))
continue;
159 written_parents.Set(dep_idx);
166 auto add_holes = SetType::Fill(idx) - done - depgraph.
Positions();
167 if (add_holes.None()) {
170 auto skips = (done - SetType::Fill(idx)).Count();
176 s <<
VARINT(diff + done.Count() + add_holes.Count());
186 template <
typename Stream,
typename SetType>
194 std::vector<DepGraphIndex> reordering;
201 SetType new_ancestors;
203 bool read_error{
false};
209 static_assert(0x3FFFFF >= 4000000);
210 if (size == 0 || topo_depgraph.
TxCount() == SetType::Size())
break;
214 coded_fee &= 0xFFFFFFFFFFFFF;
215 static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
216 new_feerate = {UnsignedToSigned(coded_fee), size};
218 auto topo_idx = reordering.
size();
220 for (
DepGraphIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
224 if (new_ancestors[dep_topo_idx])
continue;
227 new_ancestors |= topo_depgraph.
Ancestors(dep_topo_idx);
235 }
catch (
const std::ios_base::failure&) {
240 if (new_feerate.
IsEmpty())
break;
241 assert(reordering.size() < SetType::Size());
244 if (total_size < SetType::Size()) {
246 diff %= SetType::Size();
247 if (diff <= total_size) {
249 for (
auto& pos : reordering) {
250 pos += (pos >= total_size - diff);
252 reordering.push_back(total_size++ - diff);
256 reordering.push_back(total_size++);
264 diff %= (SetType::Size() - reordering.size());
265 SetType holes = SetType::Fill(SetType::Size());
266 for (
auto pos : reordering) holes.Reset(pos);
267 for (
auto pos : holes) {
269 reordering.push_back(pos);
276 if (read_error)
break;
280 depgraph =
DepGraph(topo_depgraph, reordering, total_size);
285template<
typename SetType>
293 position_range = i + 1;
297 assert(position_range >= num_positions);
298 assert(position_range <= SetType::Size());
320 for (
auto parent : parents) {
321 assert((depgraph.
Ancestors(parent) & parents).IsSubsetOf(SetType::Singleton(parent)));
324 for (
auto child : children) {
325 assert((depgraph.
Descendants(child) & children).IsSubsetOf(SetType::Singleton(child)));
330 std::vector<unsigned char> ser;
332 writer << Using<DepGraphFormatter>(depgraph);
335 reader >> Using<DepGraphFormatter>(decoded_depgraph);
336 assert(depgraph == decoded_depgraph);
340 assert(ser.size() >= 1 && ser.back() == 0);
343 decoded_depgraph = {};
344 reader >> Using<DepGraphFormatter>(decoded_depgraph);
345 assert(depgraph == decoded_depgraph);
357 SetType ancestors = SetType::Singleton(i);
360 const auto old_ancestors = ancestors;
361 for (
auto j : ancestors) ancestors |= parents[j];
363 if (old_ancestors == ancestors)
break;
368 SetType descendants = SetType::Singleton(i);
371 const auto old_descendants = descendants;
372 for (
auto j : descendants) descendants |= children[j];
374 if (old_descendants == descendants)
break;
382template<
typename SetType>
383void SanityCheck(
const DepGraph<SetType>& depgraph, std::span<const DepGraphIndex> linearization)
388 for (
auto i : linearization) {
397inline uint64_t MaxOptimalLinearizationIters(
DepGraphIndex cluster_count)
408 static constexpr uint64_t MAX_OPTIMAL_ITERS[65] = {
409 0, 4, 8, 12, 18, 26, 37, 51, 70, 97, 133, 182, 251, 346, 480, 666, 927, 1296, 1815, 2545,
410 3576, 5031, 7087, 9991, 14094, 19895, 28096, 39690, 56083, 79263, 112041, 158391, 223936,
411 316629, 447712, 633086, 895241, 1265980, 1790280, 2531747, 3580335, 5063259, 7160424,
412 10126257, 14320575, 20252230, 28640853, 40504150, 57281380, 81007962, 114562410, 162015557,
413 229124437, 324030718, 458248463, 648061011, 916496483, 1296121563, 1832992493, 2592242635,
414 3665984477, 5184484745, 7331968412, 10368968930, 14663936244
416 assert(cluster_count <
sizeof(MAX_OPTIMAL_ITERS) /
sizeof(MAX_OPTIMAL_ITERS[0]));
417 return MAX_OPTIMAL_ITERS[cluster_count];
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,(BITS+std::numeric_limits< size_t >::digits - 1)/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.
uint32_t DepGraphIndex
Data type to represent transaction indices in DepGraphs and the clusters they represent.
#define VARINT_MODE(obj, mode)
Data structure storing a fee and size, ordered by increasing fee/size.
bool IsEmpty() const noexcept
Check if this is empty (size and fee are 0).