truc_policy.h raw

   1  // Copyright (c) 2022 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef LIMENKA_POLICY_TRUC_POLICY_H
   6  #define LIMENKA_POLICY_TRUC_POLICY_H
   7  
   8  #include <consensus/amount.h>
   9  #include <policy/packages.h>
  10  #include <policy/policy.h>
  11  #include <primitives/transaction.h>
  12  #include <txmempool.h>
  13  #include <util/result.h>
  14  
  15  #include <set>
  16  #include <string>
  17  
  18  // This module enforces rules for BIP 431 TRUC transactions which help make
  19  // RBF abilities more robust. A transaction with version=3 is treated as TRUC.
  20  static constexpr decltype(CTransaction::version) TRUC_VERSION{3};
  21  
  22  // TRUC only allows 1 parent and 1 child when unconfirmed. This translates to a descendant set size
  23  // of 2 and ancestor set size of 2.
  24  /** Maximum number of transactions including an unconfirmed tx and its descendants. */
  25  static constexpr unsigned int TRUC_DESCENDANT_LIMIT{2};
  26  /** Maximum number of transactions including a TRUC tx and all its mempool ancestors. */
  27  static constexpr unsigned int TRUC_ANCESTOR_LIMIT{2};
  28  
  29  /** Maximum sigop-adjusted virtual size of all v3 transactions. */
  30  static constexpr int64_t TRUC_MAX_VSIZE{10000};
  31  /** Maximum sigop-adjusted virtual size of a tx which spends from an unconfirmed TRUC transaction. */
  32  static constexpr int64_t TRUC_CHILD_MAX_VSIZE{1000};
  33  // These limits are within the default ancestor/descendant limits.
  34  static_assert(TRUC_MAX_VSIZE + TRUC_CHILD_MAX_VSIZE <= DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1000);
  35  static_assert(TRUC_MAX_VSIZE + TRUC_CHILD_MAX_VSIZE <= DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * 1000);
  36  
  37  /** Must be called for every transaction, even if not TRUC. Not strictly necessary for transactions
  38   * accepted through AcceptMultipleTransactions.
  39   *
  40   * Checks the following rules:
  41   * 1. A TRUC tx must only have TRUC unconfirmed ancestors.
  42   * 2. A non-TRUC tx must only have non-TRUC unconfirmed ancestors.
  43   * 3. A TRUC's ancestor set, including itself, must be within TRUC_ANCESTOR_LIMIT.
  44   * 4. A TRUC's descendant set, including itself, must be within TRUC_DESCENDANT_LIMIT.
  45   * 5. If a TRUC tx has any unconfirmed ancestors, the tx's sigop-adjusted vsize must be within
  46   * TRUC_CHILD_MAX_VSIZE.
  47   * 6. A TRUC tx must be within TRUC_MAX_VSIZE.
  48   *
  49   *
  50   * @param[in]   mempool_ancestors       The in-mempool ancestors of ptx.
  51   * @param[in]   direct_conflicts        In-mempool transactions this tx conflicts with. These conflicts
  52   *                                      are used to more accurately calculate the resulting descendant
  53   *                                      count of in-mempool ancestors.
  54   * @param[in]   vsize                   The sigop-adjusted virtual size of ptx.
  55   *
  56   * @returns 3 possibilities:
  57   * - std::nullopt if all TRUC checks were applied successfully
  58   * - debug string + pointer to a mempool sibling if this transaction would be the second child in a
  59   *   1-parent-1-child cluster; the caller may consider evicting the specified sibling or return an
  60   *   error with the debug string.
  61   * - debug string + nullptr if this transaction violates some TRUC rule and sibling eviction is not
  62   *   applicable.
  63   */
  64  std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx,
  65                                            const std::string& reason_prefix, std::string& out_reason,
  66                                            const ignore_rejects_type& ignore_rejects,
  67                                            const CTxMemPool::setEntries& mempool_ancestors,
  68                                            const std::set<Txid>& direct_conflicts,
  69                                            int64_t vsize);
  70  
  71  /** Must be called for every transaction that is submitted within a package, even if not TRUC.
  72   *
  73   * For each transaction in a package:
  74   * If it's not a TRUC transaction, verify it has no direct TRUC parents in the mempool or the package.
  75  
  76   * If it is a TRUC transaction, verify that any direct parents in the mempool or the package are TRUC.
  77   * If such a parent exists, verify that parent has no other children in the package or the mempool,
  78   * and that the transaction itself has no children in the package.
  79   *
  80   * If any TRUC violations in the package exist, this test will fail for one of them:
  81   * - if a TRUC transaction T has a parent in the mempool and a child in the package, then PTRUCC(T) will fail
  82   * - if a TRUC transaction T has a parent in the package and a child in the package, then PTRUCC(T) will fail
  83   * - if a TRUC transaction T and a TRUC (sibling) transaction U have some parent in the mempool,
  84   *   then PTRUCC(T) and PTRUCC(U) will fail
  85   * - if a TRUC transaction T and a TRUC (sibling) transaction U have some parent in the package,
  86   *   then PTRUCC(T) and PTRUCC(U) will fail
  87   * - if a TRUC transaction T has a parent P and a grandparent G in the package, then
  88   *   PTRUCC(P) will fail (though PTRUCC(G) and PTRUCC(T) might succeed).
  89   *
  90   * @returns debug string if an error occurs, std::nullopt otherwise.
  91   * */
  92  std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize,
  93                                             const std::string& reason_prefix, std::string& out_reason,
  94                                             const ignore_rejects_type& ignore_rejects,
  95                                             const Package& package,
  96                                             const CTxMemPool::setEntries& mempool_ancestors);
  97  
  98  #endif // LIMENKA_POLICY_TRUC_POLICY_H
  99