5#ifndef BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
6#define BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
27template<
typename SetType>
31 if ((depgraph.Ancestors(i) & depgraph.Descendants(i)) != SetType::Singleton(i)) {
111struct DepGraphFormatter
114 [[maybe_unused]]
static uint64_t SignedToUnsigned(int64_t x)
noexcept
117 return 2 * uint64_t(-(x + 1)) + 1;
119 return 2 * uint64_t(x);
124 [[maybe_unused]]
static int64_t UnsignedToSigned(uint64_t x)
noexcept
127 return -int64_t(x / 2) - 1;
129 return int64_t(x / 2);
133 template <
typename Stream,
typename SetType>
137 std::vector<ClusterIndex> topo_order;
138 topo_order.reserve(depgraph.
TxCount());
139 for (
auto i : depgraph.
Positions()) topo_order.push_back(i);
141 auto anc_a = depgraph.Ancestors(a).Count(), anc_b = depgraph.Ancestors(b).Count();
142 if (anc_a != anc_b) return anc_a < anc_b;
151 for (
ClusterIndex topo_idx = 0; topo_idx < topo_order.size(); ++topo_idx) {
159 SetType written_parents;
161 for (
ClusterIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
163 ClusterIndex dep_idx = topo_order[topo_idx - 1 - dep_dist];
165 if (depgraph.
Descendants(dep_idx).Overlaps(written_parents))
continue;
171 written_parents.Set(dep_idx);
178 auto add_holes = SetType::Fill(idx) - done - depgraph.
Positions();
179 if (add_holes.None()) {
182 auto skips = (done - SetType::Fill(idx)).Count();
188 s <<
VARINT(diff + done.Count() + add_holes.Count());
198 template <
typename Stream,
typename SetType>
206 std::vector<ClusterIndex> reordering;
213 SetType new_ancestors;
215 bool read_error{
false};
221 static_assert(0x3FFFFF >= 4000000);
222 if (size == 0 || topo_depgraph.
TxCount() == SetType::Size())
break;
226 coded_fee &= 0xFFFFFFFFFFFFF;
227 static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
228 new_feerate = {UnsignedToSigned(coded_fee), size};
230 auto topo_idx = reordering.
size();
232 for (
ClusterIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
236 if (new_ancestors[dep_topo_idx])
continue;
239 new_ancestors |= topo_depgraph.
Ancestors(dep_topo_idx);
247 }
catch (
const std::ios_base::failure&) {
252 if (new_feerate.
IsEmpty())
break;
253 assert(reordering.size() < SetType::Size());
256 if (total_size < SetType::Size()) {
258 diff %= SetType::Size();
259 if (diff <= total_size) {
261 for (
auto& pos : reordering) {
262 pos += (pos >= total_size - diff);
264 reordering.push_back(total_size++ - diff);
268 reordering.push_back(total_size++);
276 diff %= (SetType::Size() - reordering.size());
277 SetType holes = SetType::Fill(SetType::Size());
278 for (
auto pos : reordering) holes.Reset(pos);
279 for (
auto pos : holes) {
281 reordering.push_back(pos);
288 if (read_error)
break;
292 depgraph =
DepGraph(topo_depgraph, reordering, total_size);
297template<
typename SetType>
305 position_range = i + 1;
309 assert(position_range >= num_positions);
310 assert(position_range <= SetType::Size());
332 for (
auto parent : parents) {
333 assert((depgraph.
Ancestors(parent) & parents).IsSubsetOf(SetType::Singleton(parent)));
336 for (
auto child : children) {
337 assert((depgraph.
Descendants(child) & children).IsSubsetOf(SetType::Singleton(child)));
340 if (IsAcyclic(depgraph)) {
342 std::vector<unsigned char> ser;
344 writer << Using<DepGraphFormatter>(depgraph);
347 reader >> Using<DepGraphFormatter>(decoded_depgraph);
348 assert(depgraph == decoded_depgraph);
352 assert(ser.size() >= 1 && ser.back() == 0);
355 decoded_depgraph = {};
356 reader >> Using<DepGraphFormatter>(decoded_depgraph);
357 assert(depgraph == decoded_depgraph);
369 SetType ancestors = SetType::Singleton(i);
372 const auto old_ancestors = ancestors;
373 for (
auto j : ancestors) ancestors |= parents[j];
375 if (old_ancestors == ancestors)
break;
380 SetType descendants = SetType::Singleton(i);
383 const auto old_descendants = descendants;
384 for (
auto j : descendants) descendants |= children[j];
386 if (old_descendants == descendants)
break;
394template<
typename SetType>
400 for (
auto i : linearization) {
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
constexpr std::size_t size() const noexcept
Minimal stream for reading from an existing byte array by Span.
Data structure that holds a transaction graph's preprocessed data (fee, size, ancestors,...
SetType GetReducedParents(ClusterIndex i) const noexcept
Compute the (reduced) set of parents of node i in this graph.
const FeeFrac & FeeRate(ClusterIndex i) const noexcept
Get the feerate of a given transaction i.
const SetType & Ancestors(ClusterIndex i) const noexcept
Get the ancestors of a given transaction i.
void AddDependencies(const SetType &parents, ClusterIndex child) noexcept
Modify this transaction graph, adding multiple parents to a specified child.
ClusterIndex PositionRange() const noexcept
Get the range of positions in this DepGraph.
auto TxCount() const noexcept
Get the number of transactions in the graph.
const SetType & Positions() const noexcept
Get the set of transactions positions in use.
SetType GetReducedChildren(ClusterIndex i) const noexcept
Compute the (reduced) set of children of node i in this graph.
const SetType & Descendants(ClusterIndex i) const noexcept
Get the descendants of a given transaction i.
ClusterIndex AddTransaction(const FeeFrac &feefrac) noexcept
Add a new unconnected transaction to this transaction graph (in the first available position),...
uint32_t ClusterIndex
Data type to represent transaction indices in clusters.
#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).