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