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) {
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).