[doc] replace mentions of v3 with TRUC

Keep mentions of v3 in debug strings to help people who might not know
that TRUC is applied when version=3.
Also keep variable names in tests, as it is less verbose to keep v3 and v2.
This commit is contained in:
glozow
2024-06-11 13:37:05 +01:00
parent 089b5757df
commit a573dd2617
9 changed files with 131 additions and 130 deletions

View File

@@ -43,7 +43,7 @@ struct ParentInfo {
const Txid& m_txid;
/** Wtxid used for debug string */
const Wtxid& m_wtxid;
/** version used to check inheritance of v3 and non-v3 */
/** version used to check inheritance of TRUC and non-TRUC */
decltype(CTransaction::version) m_version;
/** If parent is in mempool, whether it has any descendants in mempool. */
bool m_has_mempool_descendant;
@@ -65,7 +65,7 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
const auto in_package_parents{FindInPackageParents(package, ptx)};
// Now we have all ancestors, so we can start checking v3 rules.
// Now we have all ancestors, so we can start checking TRUC rules.
if (ptx->version == TRUC_VERSION) {
// SingleV3Checks should have checked this already.
if (!Assume(vsize <= V3_MAX_VSIZE)) {
@@ -80,7 +80,7 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
const bool has_parent{mempool_ancestors.size() + in_package_parents.size() > 0};
if (has_parent) {
// A v3 child cannot be too large.
// A TRUC child cannot be too large.
if (vsize > V3_CHILD_MAX_VSIZE) {
return strprintf("v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
@@ -140,7 +140,7 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
}
}
} else {
// Non-v3 transactions cannot have v3 parents.
// Non-TRUC transactions cannot have TRUC parents.
for (auto it : mempool_ancestors) {
if (it->GetTx().version == TRUC_VERSION) {
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)",
@@ -166,7 +166,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
const std::set<Txid>& direct_conflicts,
int64_t vsize)
{
// Check v3 and non-v3 inheritance.
// Check TRUC and non-TRUC inheritance.
for (const auto& entry : mempool_ancestors) {
if (ptx->version != TRUC_VERSION && entry->GetTx().version == TRUC_VERSION) {
return std::make_pair(strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)",
@@ -203,7 +203,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
// Remaining checks only pertain to transactions with unconfirmed ancestors.
if (mempool_ancestors.size() > 0) {
// If this transaction spends V3 parents, it cannot be too large.
// If this transaction spends TRUC parents, it cannot be too large.
if (vsize > V3_CHILD_MAX_VSIZE) {
return std::make_pair(strprintf("v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, V3_CHILD_MAX_VSIZE),
@@ -217,14 +217,14 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
// possible through a reorg.
const auto& children = parent_entry->GetMemPoolChildrenConst();
// Don't double-count a transaction that is going to be replaced. This logic assumes that
// any descendant of the V3 transaction is a direct child, which makes sense because a V3
// transaction can only have 1 descendant.
// any descendant of the TRUC transaction is a direct child, which makes sense because a
// TRUC transaction can only have 1 descendant.
const bool child_will_be_replaced = !children.empty() &&
std::any_of(children.cbegin(), children.cend(),
[&direct_conflicts](const CTxMemPoolEntry& child){return direct_conflicts.count(child.GetTx().GetHash()) > 0;});
if (parent_entry->GetCountWithDescendants() + 1 > V3_DESCENDANT_LIMIT && !child_will_be_replaced) {
// Allow sibling eviction for v3 transaction: if another child already exists, even if
// we don't conflict inputs with it, consider evicting it under RBF rules. We rely on v3 rules
// Allow sibling eviction for TRUC transaction: if another child already exists, even if
// we don't conflict inputs with it, consider evicting it under RBF rules. We rely on TRUC rules
// only permitting 1 descendant, as otherwise we would need to have logic for deciding
// which descendant to evict. Skip if this isn't true, e.g. if the transaction has
// multiple children or the sibling also has descendants due to a reorg.

View File

@@ -15,35 +15,36 @@
#include <set>
#include <string>
// This module enforces rules for BIP 431 TRUC transactions (with version=3) which help make
// RBF abilities more robust.
// This module enforces rules for BIP 431 TRUC transactions which help make
// RBF abilities more robust. A transaction with version=3 is treated as TRUC.
static constexpr decltype(CTransaction::version) TRUC_VERSION{3};
// v3 only allows 1 parent and 1 child when unconfirmed.
// TRUC only allows 1 parent and 1 child when unconfirmed. This translates to a descendant set size
// of 2 and ancestor set size of 2.
/** Maximum number of transactions including an unconfirmed tx and its descendants. */
static constexpr unsigned int V3_DESCENDANT_LIMIT{2};
/** Maximum number of transactions including a V3 tx and all its mempool ancestors. */
/** Maximum number of transactions including a TRUC tx and all its mempool ancestors. */
static constexpr unsigned int V3_ANCESTOR_LIMIT{2};
/** Maximum sigop-adjusted virtual size of all v3 transactions. */
static constexpr int64_t V3_MAX_VSIZE{10000};
/** Maximum sigop-adjusted virtual size of a tx which spends from an unconfirmed v3 transaction. */
/** Maximum sigop-adjusted virtual size of a tx which spends from an unconfirmed TRUC transaction. */
static constexpr int64_t V3_CHILD_MAX_VSIZE{1000};
// These limits are within the default ancestor/descendant limits.
static_assert(V3_MAX_VSIZE + V3_CHILD_MAX_VSIZE <= DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1000);
static_assert(V3_MAX_VSIZE + V3_CHILD_MAX_VSIZE <= DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * 1000);
/** Must be called for every transaction, even if not v3. Not strictly necessary for transactions
/** Must be called for every transaction, even if not TRUC. Not strictly necessary for transactions
* accepted through AcceptMultipleTransactions.
*
* Checks the following rules:
* 1. A v3 tx must only have v3 unconfirmed ancestors.
* 2. A non-v3 tx must only have non-v3 unconfirmed ancestors.
* 3. A v3's ancestor set, including itself, must be within V3_ANCESTOR_LIMIT.
* 4. A v3's descendant set, including itself, must be within V3_DESCENDANT_LIMIT.
* 5. If a v3 tx has any unconfirmed ancestors, the tx's sigop-adjusted vsize must be within
* 1. A TRUC tx must only have TRUC unconfirmed ancestors.
* 2. A non-TRUC tx must only have non-TRUC unconfirmed ancestors.
* 3. A TRUC's ancestor set, including itself, must be within V3_ANCESTOR_LIMIT.
* 4. A TRUC's descendant set, including itself, must be within V3_DESCENDANT_LIMIT.
* 5. If a TRUC tx has any unconfirmed ancestors, the tx's sigop-adjusted vsize must be within
* V3_CHILD_MAX_VSIZE.
* 6. A v3 tx must be within V3_MAX_VSIZE.
* 6. A TRUC tx must be within V3_MAX_VSIZE.
*
*
* @param[in] mempool_ancestors The in-mempool ancestors of ptx.
@@ -53,11 +54,11 @@ static_assert(V3_MAX_VSIZE + V3_CHILD_MAX_VSIZE <= DEFAULT_DESCENDANT_SIZE_LIMIT
* @param[in] vsize The sigop-adjusted virtual size of ptx.
*
* @returns 3 possibilities:
* - std::nullopt if all v3 checks were applied successfully
* - std::nullopt if all TRUC checks were applied successfully
* - debug string + pointer to a mempool sibling if this transaction would be the second child in a
* 1-parent-1-child cluster; the caller may consider evicting the specified sibling or return an
* error with the debug string.
* - debug string + nullptr if this transaction violates some v3 rule and sibling eviction is not
* - debug string + nullptr if this transaction violates some TRUC rule and sibling eviction is not
* applicable.
*/
std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTransactionRef& ptx,
@@ -65,23 +66,23 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
const std::set<Txid>& direct_conflicts,
int64_t vsize);
/** Must be called for every transaction that is submitted within a package, even if not v3.
/** Must be called for every transaction that is submitted within a package, even if not TRUC.
*
* For each transaction in a package:
* If it's not a v3 transaction, verify it has no direct v3 parents in the mempool or the package.
* If it's not a TRUC transaction, verify it has no direct TRUC parents in the mempool or the package.
* If it is a v3 transaction, verify that any direct parents in the mempool or the package are v3.
* If it is a TRUC transaction, verify that any direct parents in the mempool or the package are TRUC.
* If such a parent exists, verify that parent has no other children in the package or the mempool,
* and that the transaction itself has no children in the package.
*
* If any v3 violations in the package exist, this test will fail for one of them:
* - if a v3 transaction T has a parent in the mempool and a child in the package, then PV3C(T) will fail
* - if a v3 transaction T has a parent in the package and a child in the package, then PV3C(T) will fail
* - if a v3 transaction T and a v3 (sibling) transaction U have some parent in the mempool,
* If any TRUC violations in the package exist, this test will fail for one of them:
* - if a TRUC transaction T has a parent in the mempool and a child in the package, then PV3C(T) will fail
* - if a TRUC transaction T has a parent in the package and a child in the package, then PV3C(T) will fail
* - if a TRUC transaction T and a TRUC (sibling) transaction U have some parent in the mempool,
* then PV3C(T) and PV3C(U) will fail
* - if a v3 transaction T and a v3 (sibling) transaction U have some parent in the package,
* - if a TRUC transaction T and a TRUC (sibling) transaction U have some parent in the package,
* then PV3C(T) and PV3C(U) will fail
* - if a v3 transaction T has a parent P and a grandparent G in the package, then
* - if a TRUC transaction T has a parent P and a grandparent G in the package, then
* PV3C(P) will fail (though PV3C(G) and PV3C(T) might succeed).
*
* @returns debug string if an error occurs, std::nullopt otherwise.