txgraph: Add ability to trim oversized clusters (feature)

During reorganisations, it is possible that dependencies get add which
result in clusters that violate limits (count, size), when linking the
new from-block transactions to the old from-mempool transactions.

Unlike RBF scenarios, we cannot simply reject these policy violations
when they are due to received blocks. To accomodate this, add a Trim()
function to TxGraph, which removes transactions (including descendants)
in order to make all resulting clusters satisfy the limits.

In the initial version of the function added here, the following approach
is used:
- Lazily compute a naive linearization for the to-be-merged cluster (using
  an O(n log n) algorithm, optimized for far larger groups of transactions
  than the normal linearization code).
- Initialize a set of accepted transactions to {}
- Iterate over the transactions in this cluster one by one:
  - If adding the transaction to the set makes it exceed the max cluster size
    or count limit, stop.
  - Add the transaction to the set.
- Remove all transactions from the cluster that were not included in the set
  (note that this necessarily includes all descendants too, because they
  appear later in the naive linearization).

Co-authored-by: Greg Sanders <gsanders87@gmail.com>
This commit is contained in:
Pieter Wuille
2024-12-16 17:57:57 -05:00
parent eabcd0eb6f
commit a04e205ab0
3 changed files with 300 additions and 0 deletions

View File

@@ -169,6 +169,11 @@ public:
* that appear identically in both. Use FeeFrac rather than FeePerWeight so CompareChunks is
* usable without type-conversion. */
virtual std::pair<std::vector<FeeFrac>, std::vector<FeeFrac>> GetMainStagingDiagrams() noexcept = 0;
/** Remove transactions (including their own descendants) according to a fast but best-effort
* strategy such that the TxGraph's cluster and size limits are respected. Applies to staging
* if it exists, and to main otherwise. Returns the list of all removed transactions in
* unspecified order. This has no effect unless the relevant graph is oversized. */
virtual std::vector<Ref*> Trim() noexcept = 0;
/** Interface returned by GetBlockBuilder. */
class BlockBuilder