5 #ifndef BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H 6 #define BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H 27 template<
typename SetType>
31 if ((depgraph.Ancestors(i) & depgraph.Descendants(i)) != SetType::Singleton(i)) {
102 struct DepGraphFormatter
105 static uint64_t SignedToUnsigned(int64_t x) noexcept
108 return 2 * uint64_t(-(x + 1)) + 1;
110 return 2 * uint64_t(x);
115 static int64_t UnsignedToSigned(uint64_t x) noexcept
118 return -int64_t(x / 2) - 1;
120 return int64_t(x / 2);
124 template <
typename Stream,
typename SetType>
128 std::vector<ClusterIndex> topo_order(depgraph.
TxCount());
129 std::iota(topo_order.begin(), topo_order.end(),
ClusterIndex{0});
132 if (anc_a != anc_b)
return anc_a < anc_b;
138 std::vector<ClusterIndex> rebuilt_order;
139 rebuilt_order.reserve(depgraph.
TxCount());
142 for (
ClusterIndex topo_idx = 0; topo_idx < topo_order.size(); ++topo_idx) {
150 SetType written_parents;
152 for (
ClusterIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
154 ClusterIndex dep_idx = topo_order[topo_idx - 1 - dep_dist];
156 if (depgraph.
Descendants(dep_idx).Overlaps(written_parents))
continue;
162 written_parents.Set(dep_idx);
170 while (insert_distance < rebuilt_order.size()) {
172 if (idx > *(rebuilt_order.end() - 1 - insert_distance))
break;
175 rebuilt_order.insert(rebuilt_order.end() - insert_distance, idx);
176 s <<
VARINT(diff + insert_distance);
183 template <
typename Stream,
typename SetType>
191 std::vector<ClusterIndex> reordering;
200 static_assert(0x3FFFFF >= 4000000);
201 if (size == 0 || topo_depgraph.
TxCount() == SetType::Size())
break;
205 coded_fee &= 0xFFFFFFFFFFFFF;
206 static_assert(0xFFFFFFFFFFFFF > uint64_t{2} * 21000000 * 100000000);
207 auto fee = UnsignedToSigned(coded_fee);
210 reordering.push_back(topo_idx);
214 for (
ClusterIndex dep_dist = 0; dep_dist < topo_idx; ++dep_dist) {
218 if (topo_depgraph.
Descendants(dep_topo_idx)[topo_idx])
continue;
233 reordering.pop_back();
234 reordering.insert(reordering.end() - (diff % (reordering.size() + 1)), topo_idx);
236 }
catch (
const std::ios_base::failure&) {}
241 for (
auto topo_idx : reordering) {
245 for (
ClusterIndex idx = 0; idx < reordering.size(); ++idx) {
247 for (
ClusterIndex dep_idx = 0; dep_idx < reordering.size(); ++dep_idx) {
249 if (topo_depgraph.
Ancestors(topo_idx)[dep_topo_idx]) {
258 template<
typename SetType>
277 if (IsAcyclic(depgraph)) {
278 std::vector<unsigned char> ser;
280 writer << Using<DepGraphFormatter>(depgraph);
283 reader >> Using<DepGraphFormatter>(decoded_depgraph);
284 assert(depgraph == decoded_depgraph);
288 assert(ser.size() >= 1 && ser.back() == 0);
291 decoded_depgraph = {};
292 reader >> Using<DepGraphFormatter>(decoded_depgraph);
293 assert(depgraph == decoded_depgraph);
299 template<
typename SetType>
304 SanityCheck(depgraph);
314 auto ancestors = SetType::Singleton(i);
317 const auto old_ancestors = ancestors;
318 for (
auto ancestor : ancestors) {
319 ancestors |= cluster[ancestor].second;
321 if (old_ancestors == ancestors)
break;
329 for (
auto parent : cluster[i].second) {
330 assert(ancestors[parent]);
336 template<
typename SetType>
342 for (
auto i : linearization) {
353 #endif // BITCOIN_TEST_UTIL_CLUSTER_LINEARIZE_H
ClusterIndex AddTransaction(const FeeFrac &feefrac) noexcept
Add a new unconnected transaction to this transaction graph (at the end), and return its ClusterIndex...
uint32_t ClusterIndex
Data type to represent transaction indices in clusters.
const SetType & Descendants(ClusterIndex i) const noexcept
Get the descendants of a given transaction i.
constexpr std::size_t size() const noexcept
Minimal stream for reading from an existing byte array by Span.
#define VARINT_MODE(obj, mode)
void AddDependency(ClusterIndex parent, ClusterIndex child) noexcept
Modify this transaction graph, adding a dependency between a specified parent and child...
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
Data structure that holds a transaction graph's preprocessed data (fee, size, ancestors, descendants).
const FeeFrac & FeeRate(ClusterIndex i) const noexcept
Get the feerate of a given transaction i.
std::vector< std::pair< FeeFrac, SetType > > Cluster
Data type to represent cluster input.
const SetType & Ancestors(ClusterIndex i) const noexcept
Get the ancestors of a given transaction i.
auto TxCount() const noexcept
Get the number of transactions in the graph.