mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
[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:
parent
089b5757df
commit
a573dd2617
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -225,7 +225,7 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
|
||||
tx_mut.vin.emplace_back();
|
||||
}
|
||||
|
||||
// Make a p2pk output to make sigops adjusted vsize to violate v3, potentially, which is never spent
|
||||
// Make a p2pk output to make sigops adjusted vsize to violate TRUC rules, potentially, which is never spent
|
||||
if (last_tx && amount_in > 1000 && fuzzed_data_provider.ConsumeBool()) {
|
||||
tx_mut.vout.emplace_back(1000, CScript() << std::vector<unsigned char>(33, 0x02) << OP_CHECKSIG);
|
||||
// Don't add any other outputs.
|
||||
|
@ -91,7 +91,7 @@ static inline CTransactionRef make_tx(const std::vector<COutPoint>& inputs, int3
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
{
|
||||
// Test V3 policy helper functions
|
||||
// Test TRUC policy helper functions
|
||||
CTxMemPool& pool = *Assert(m_node.mempool);
|
||||
LOCK2(cs_main, pool.cs);
|
||||
TestMemPoolEntryHelper entry;
|
||||
@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
// Default values.
|
||||
CTxMemPool::Limits m_limits{};
|
||||
|
||||
// Cannot spend from an unconfirmed v3 transaction unless this tx is also v3.
|
||||
// Cannot spend from an unconfirmed TRUC transaction unless this tx is also TRUC.
|
||||
{
|
||||
// mempool_tx_v3
|
||||
// ^
|
||||
@ -140,7 +140,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
BOOST_CHECK_EQUAL(*PackageV3Checks(tx_v2_from_v2_and_v3, GetVirtualTransactionSize(*tx_v2_from_v2_and_v3), package_v3_v2_v2, empty_ancestors), expected_error_str_2);
|
||||
}
|
||||
|
||||
// V3 cannot spend from an unconfirmed non-v3 transaction.
|
||||
// TRUC cannot spend from an unconfirmed non-TRUC transaction.
|
||||
{
|
||||
// mempool_tx_v2
|
||||
// ^
|
||||
@ -202,7 +202,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
BOOST_CHECK(PackageV3Checks(tx_v2_from_v2, GetVirtualTransactionSize(*tx_v2_from_v2), package_v2_v2, empty_ancestors) == std::nullopt);
|
||||
}
|
||||
|
||||
// Tx spending v3 cannot have too many mempool ancestors
|
||||
// Tx spending TRUC cannot have too many mempool ancestors
|
||||
// Configuration where the tx has multiple direct parents.
|
||||
{
|
||||
Package package_multi_parents;
|
||||
@ -255,7 +255,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
BOOST_CHECK(PackageV3Checks(tx_v3_multi_gen, GetVirtualTransactionSize(*tx_v3_multi_gen), package_multi_gen, empty_ancestors) == std::nullopt);
|
||||
}
|
||||
|
||||
// Tx spending v3 cannot be too large in virtual size.
|
||||
// Tx spending TRUC cannot be too large in virtual size.
|
||||
auto many_inputs{random_outpoints(100)};
|
||||
many_inputs.emplace_back(mempool_tx_v3->GetHash(), 0);
|
||||
{
|
||||
@ -273,7 +273,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
expected_error_str);
|
||||
}
|
||||
|
||||
// Tx spending v3 cannot have too many sigops.
|
||||
// Tx spending TRUC cannot have too many sigops.
|
||||
// This child has 10 P2WSH multisig inputs.
|
||||
auto multisig_outpoints{random_outpoints(10)};
|
||||
multisig_outpoints.emplace_back(mempool_tx_v3->GetHash(), 0);
|
||||
@ -317,7 +317,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
expected_error_str);
|
||||
}
|
||||
|
||||
// Parent + child with v3 in the mempool. Child is allowed as long as it is under V3_CHILD_MAX_VSIZE.
|
||||
// Parent + child with TRUC in the mempool. Child is allowed as long as it is under V3_CHILD_MAX_VSIZE.
|
||||
auto tx_mempool_v3_child = make_tx({COutPoint{mempool_tx_v3->GetHash(), 0}}, /*version=*/3);
|
||||
{
|
||||
BOOST_CHECK(GetTransactionWeight(*tx_mempool_v3_child) <= V3_CHILD_MAX_VSIZE * WITNESS_SCALE_FACTOR);
|
||||
@ -329,7 +329,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
||||
BOOST_CHECK(PackageV3Checks(tx_mempool_v3_child, GetVirtualTransactionSize(*tx_mempool_v3_child), package_v3_1p1c, empty_ancestors) == std::nullopt);
|
||||
}
|
||||
|
||||
// A v3 transaction cannot have more than 1 descendant. Sibling is returned when exactly 1 exists.
|
||||
// A TRUC transaction cannot have more than 1 descendant. Sibling is returned when exactly 1 exists.
|
||||
{
|
||||
auto tx_v3_child2 = make_tx({COutPoint{mempool_tx_v3->GetHash(), 1}}, /*version=*/3);
|
||||
|
||||
|
@ -150,7 +150,7 @@ void CheckMempoolV3Invariants(const CTxMemPool& tx_pool)
|
||||
// Check that special maximum virtual size is respected
|
||||
Assert(entry.GetTxSize() <= V3_MAX_VSIZE);
|
||||
|
||||
// Check that special v3 ancestor/descendant limits and rules are always respected
|
||||
// Check that special TRUC ancestor/descendant limits and rules are always respected
|
||||
Assert(entry.GetCountWithDescendants() <= V3_DESCENDANT_LIMIT);
|
||||
Assert(entry.GetCountWithAncestors() <= V3_ANCESTOR_LIMIT);
|
||||
Assert(entry.GetSizeWithDescendants() <= V3_MAX_VSIZE + V3_CHILD_MAX_VSIZE);
|
||||
@ -159,12 +159,12 @@ void CheckMempoolV3Invariants(const CTxMemPool& tx_pool)
|
||||
// If this transaction has at least 1 ancestor, it's a "child" and has restricted weight.
|
||||
if (entry.GetCountWithAncestors() > 1) {
|
||||
Assert(entry.GetTxSize() <= V3_CHILD_MAX_VSIZE);
|
||||
// All v3 transactions must only have v3 unconfirmed parents.
|
||||
// All TRUC transactions must only have TRUC unconfirmed parents.
|
||||
const auto& parents = entry.GetMemPoolParentsConst();
|
||||
Assert(parents.begin()->get().GetSharedTx()->version == TRUC_VERSION);
|
||||
}
|
||||
} else if (entry.GetCountWithAncestors() > 1) {
|
||||
// All non-v3 transactions must only have non-v3 unconfirmed parents.
|
||||
// All non-TRUC transactions must only have non-TRUC unconfirmed parents.
|
||||
for (const auto& parent : entry.GetMemPoolParentsConst()) {
|
||||
Assert(parent.get().GetSharedTx()->version != TRUC_VERSION);
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
||||
bool expect_valid,
|
||||
const CTxMemPool* mempool);
|
||||
|
||||
/** For every transaction in tx_pool, check v3 invariants:
|
||||
* - a v3 tx's ancestor count must be within V3_ANCESTOR_LIMIT
|
||||
* - a v3 tx's descendant count must be within V3_DESCENDANT_LIMIT
|
||||
* - if a v3 tx has ancestors, its sigop-adjusted vsize must be within V3_CHILD_MAX_VSIZE
|
||||
* - any non-v3 tx must only have non-v3 parents
|
||||
* - any v3 tx must only have v3 parents
|
||||
/** For every transaction in tx_pool, check TRUC invariants:
|
||||
* - a TRUC tx's ancestor count must be within V3_ANCESTOR_LIMIT
|
||||
* - a TRUC tx's descendant count must be within V3_DESCENDANT_LIMIT
|
||||
* - if a TRUC tx has ancestors, its sigop-adjusted vsize must be within V3_CHILD_MAX_VSIZE
|
||||
* - any non-TRUC tx must only have non-TRUC parents
|
||||
* - any TRUC tx must only have TRUC parents
|
||||
* */
|
||||
void CheckMempoolV3Invariants(const CTxMemPool& tx_pool);
|
||||
|
||||
|
@ -336,7 +336,7 @@ void Chainstate::MaybeUpdateMempoolForReorg(
|
||||
// Also updates valid entries' cached LockPoints if needed.
|
||||
// If false, the tx is still valid and its lockpoints are updated.
|
||||
// If true, the tx would be invalid in the next block; remove this entry and all of its descendants.
|
||||
// Note that v3 rules are not applied here, so reorgs may cause violations of v3 inheritance or
|
||||
// Note that TRUC rules are not applied here, so reorgs may cause violations of TRUC inheritance or
|
||||
// topology restrictions.
|
||||
const auto filter_final_and_mature = [&](CTxMemPool::txiter it)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) {
|
||||
@ -829,7 +829,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// check all unconfirmed ancestors; otherwise an opt-in ancestor
|
||||
// might be replaced, causing removal of this descendant.
|
||||
//
|
||||
// All V3 transactions are considered replaceable.
|
||||
// All TRUC transactions are considered replaceable.
|
||||
//
|
||||
// Replaceability signaling of the original transactions may be
|
||||
// ignored due to node setting.
|
||||
@ -936,7 +936,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// while a tx could be package CPFP'd when entering the mempool, we do not have a DoS-resistant
|
||||
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
||||
// due to a replacement.
|
||||
// The only exception is v3 transactions.
|
||||
// The only exception is TRUC transactions.
|
||||
if (!bypass_limits && ws.m_ptx->version != TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
|
||||
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
||||
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
||||
@ -1005,7 +1005,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// If the new transaction is relatively small (up to 40k weight)
|
||||
// and has at most one ancestor (ie ancestor limit of 2, including
|
||||
// the new transaction), allow it if its parent has exactly the
|
||||
// descendant limit descendants. The transaction also cannot be v3,
|
||||
// descendant limit descendants. The transaction also cannot be TRUC,
|
||||
// as its topology restrictions do not allow a second child.
|
||||
//
|
||||
// This allows protocols which rely on distrusting counterparties
|
||||
@ -1043,15 +1043,15 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
ws.m_conflicts.insert(err->second->GetHash());
|
||||
// Adding the sibling to m_iters_conflicting here means that it doesn't count towards
|
||||
// RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
|
||||
// the descendant count is done separately in SingleV3Checks for v3 transactions.
|
||||
// the descendant count is done separately in SingleV3Checks for TRUC transactions.
|
||||
ws.m_iters_conflicting.insert(m_pool.GetIter(err->second->GetHash()).value());
|
||||
ws.m_sibling_eviction = true;
|
||||
// The sibling will be treated as part of the to-be-replaced set in ReplacementChecks.
|
||||
// Note that we are not checking whether it opts in to replaceability via BIP125 or v3
|
||||
// (which is normally done in PreChecks). However, the only way a v3 transaction can
|
||||
// have a non-v3 and non-BIP125 descendant is due to a reorg.
|
||||
// Note that we are not checking whether it opts in to replaceability via BIP125 or TRUC
|
||||
// (which is normally done in PreChecks). However, the only way a TRUC transaction can
|
||||
// have a non-TRUC and non-BIP125 descendant is due to a reorg.
|
||||
} else {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "v3-rule-violation", err->first);
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1103,7 +1103,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
||||
}
|
||||
// Enforce Rule #2.
|
||||
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, m_subpackage.m_all_conflicts)}) {
|
||||
// Sibling eviction is only done for v3 transactions, which cannot have multiple ancestors.
|
||||
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
|
||||
Assume(!ws.m_sibling_eviction);
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
|
||||
strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
|
||||
@ -1545,10 +1545,10 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
||||
}
|
||||
|
||||
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
||||
// Run the v3 checks on the package.
|
||||
// Run the TRUC checks on the package.
|
||||
for (Workspace& ws : workspaces) {
|
||||
if (auto err{PackageV3Checks(ws.m_ptx, ws.m_vsize, txns, ws.m_ancestors)}) {
|
||||
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "v3-violation", err.value());
|
||||
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());
|
||||
return PackageMempoolAcceptResult(package_state, {});
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ def cleanup(extra_args=None):
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
class MempoolAcceptV3(BitcoinTestFramework):
|
||||
class MempoolTRUC(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [[]]
|
||||
@ -52,23 +52,23 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
assert all([txid in txids for txid in mempool_contents])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=20000"])
|
||||
def test_v3_max_vsize(self):
|
||||
def test_truc_max_vsize(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3-specific maximum transaction vsize")
|
||||
self.log.info("Test TRUC-specific maximum transaction vsize")
|
||||
tx_v3_heavy = self.wallet.create_self_transfer(target_weight=(V3_MAX_VSIZE + 1) * WITNESS_SCALE_FACTOR, version=3)
|
||||
assert_greater_than_or_equal(tx_v3_heavy["tx"].get_vsize(), V3_MAX_VSIZE)
|
||||
expected_error_heavy = f"v3-rule-violation, v3 tx {tx_v3_heavy['txid']} (wtxid={tx_v3_heavy['wtxid']}) is too big"
|
||||
expected_error_heavy = f"TRUC-violation, v3 tx {tx_v3_heavy['txid']} (wtxid={tx_v3_heavy['wtxid']}) is too big"
|
||||
assert_raises_rpc_error(-26, expected_error_heavy, node.sendrawtransaction, tx_v3_heavy["hex"])
|
||||
self.check_mempool([])
|
||||
|
||||
# Ensure we are hitting the v3-specific limit and not something else
|
||||
# Ensure we are hitting the TRUC-specific limit and not something else
|
||||
tx_v2_heavy = self.wallet.send_self_transfer(from_node=node, target_weight=(V3_MAX_VSIZE + 1) * WITNESS_SCALE_FACTOR, version=2)
|
||||
self.check_mempool([tx_v2_heavy["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_acceptance(self):
|
||||
def test_truc_acceptance(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test a child of a v3 transaction cannot be more than 1000vB")
|
||||
self.log.info("Test a child of a TRUC transaction cannot be more than 1000vB")
|
||||
tx_v3_parent_normal = self.wallet.send_self_transfer(from_node=node, version=3)
|
||||
self.check_mempool([tx_v3_parent_normal["txid"]])
|
||||
tx_v3_child_heavy = self.wallet.create_self_transfer(
|
||||
@ -77,13 +77,13 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
version=3
|
||||
)
|
||||
assert_greater_than_or_equal(tx_v3_child_heavy["tx"].get_vsize(), 1000)
|
||||
expected_error_child_heavy = f"v3-rule-violation, v3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big"
|
||||
expected_error_child_heavy = f"TRUC-violation, v3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big"
|
||||
assert_raises_rpc_error(-26, expected_error_child_heavy, node.sendrawtransaction, tx_v3_child_heavy["hex"])
|
||||
self.check_mempool([tx_v3_parent_normal["txid"]])
|
||||
# tx has no descendants
|
||||
assert_equal(node.getmempoolentry(tx_v3_parent_normal["txid"])["descendantcount"], 1)
|
||||
|
||||
self.log.info("Test that, during replacements, only the new transaction counts for v3 descendant limit")
|
||||
self.log.info("Test that, during replacements, only the new transaction counts for TRUC descendant limit")
|
||||
tx_v3_child_almost_heavy = self.wallet.send_self_transfer(
|
||||
from_node=node,
|
||||
fee_rate=DEFAULT_FEE,
|
||||
@ -106,9 +106,9 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
assert_equal(node.getmempoolentry(tx_v3_parent_normal["txid"])["descendantcount"], 2)
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_replacement(self):
|
||||
def test_truc_replacement(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3 transactions may be replaced by v3 transactions")
|
||||
self.log.info("Test TRUC transactions may be replaced by TRUC transactions")
|
||||
utxo_v3_bip125 = self.wallet.get_utxo()
|
||||
tx_v3_bip125 = self.wallet.send_self_transfer(
|
||||
from_node=node,
|
||||
@ -127,7 +127,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
)
|
||||
self.check_mempool([tx_v3_bip125_rbf["txid"]])
|
||||
|
||||
self.log.info("Test v3 transactions may be replaced by V2 transactions")
|
||||
self.log.info("Test TRUC transactions may be replaced by non-TRUC (BIP125) transactions")
|
||||
tx_v3_bip125_rbf_v2 = self.wallet.send_self_transfer(
|
||||
from_node=node,
|
||||
fee_rate=DEFAULT_FEE * 3,
|
||||
@ -136,7 +136,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
)
|
||||
self.check_mempool([tx_v3_bip125_rbf_v2["txid"]])
|
||||
|
||||
self.log.info("Test that replacements cannot cause violation of inherited v3")
|
||||
self.log.info("Test that replacements cannot cause violation of inherited TRUC")
|
||||
utxo_v3_parent = self.wallet.get_utxo()
|
||||
tx_v3_parent = self.wallet.send_self_transfer(
|
||||
from_node=node,
|
||||
@ -157,15 +157,15 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
utxo_to_spend=tx_v3_parent["new_utxo"],
|
||||
version=2
|
||||
)
|
||||
expected_error_v2_v3 = f"v3-rule-violation, non-v3 tx {tx_v3_child_rbf_v2['txid']} (wtxid={tx_v3_child_rbf_v2['wtxid']}) cannot spend from v3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})"
|
||||
expected_error_v2_v3 = f"TRUC-violation, non-v3 tx {tx_v3_child_rbf_v2['txid']} (wtxid={tx_v3_child_rbf_v2['wtxid']}) cannot spend from v3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})"
|
||||
assert_raises_rpc_error(-26, expected_error_v2_v3, node.sendrawtransaction, tx_v3_child_rbf_v2["hex"])
|
||||
self.check_mempool([tx_v3_bip125_rbf_v2["txid"], tx_v3_parent["txid"], tx_v3_child["txid"]])
|
||||
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_bip125(self):
|
||||
def test_truc_bip125(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3 transactions that don't signal BIP125 are replaceable")
|
||||
self.log.info("Test TRUC transactions that don't signal BIP125 are replaceable")
|
||||
assert_equal(node.getmempoolinfo()["fullrbf"], False)
|
||||
utxo_v3_no_bip125 = self.wallet.get_utxo()
|
||||
tx_v3_no_bip125 = self.wallet.send_self_transfer(
|
||||
@ -187,9 +187,9 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
self.check_mempool([tx_v3_no_bip125_rbf["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=40000"])
|
||||
def test_v3_reorg(self):
|
||||
def test_truc_reorg(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that, during a reorg, v3 rules are not enforced")
|
||||
self.log.info("Test that, during a reorg, TRUC rules are not enforced")
|
||||
tx_v2_block = self.wallet.send_self_transfer(from_node=node, version=2)
|
||||
tx_v3_block = self.wallet.send_self_transfer(from_node=node, version=3)
|
||||
tx_v3_block2 = self.wallet.send_self_transfer(from_node=node, version=3)
|
||||
@ -211,12 +211,12 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
@cleanup(extra_args=["-limitdescendantsize=10", "-datacarriersize=40000"])
|
||||
def test_nondefault_package_limits(self):
|
||||
"""
|
||||
Max standard tx size + v3 rules imply the ancestor/descendant rules (at their default
|
||||
Max standard tx size + TRUC rules imply the ancestor/descendant rules (at their default
|
||||
values), but those checks must not be skipped. Ensure both sets of checks are done by
|
||||
changing the ancestor/descendant limit configurations.
|
||||
"""
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that a decreased limitdescendantsize also applies to v3 child")
|
||||
self.log.info("Test that a decreased limitdescendantsize also applies to TRUC child")
|
||||
parent_target_weight = 9990 * WITNESS_SCALE_FACTOR
|
||||
child_target_weight = 500 * WITNESS_SCALE_FACTOR
|
||||
tx_v3_parent_large1 = self.wallet.send_self_transfer(
|
||||
@ -253,7 +253,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
version=3
|
||||
)
|
||||
|
||||
# Parent and child are within v3 limits
|
||||
# Parent and child are within TRUC limits
|
||||
assert_greater_than_or_equal(V3_MAX_VSIZE, tx_v3_parent_large2["tx"].get_vsize())
|
||||
assert_greater_than_or_equal(1000, tx_v3_child_large2["tx"].get_vsize())
|
||||
assert_greater_than(tx_v3_parent_large2["tx"].get_vsize() + tx_v3_child_large2["tx"].get_vsize(), 10000)
|
||||
@ -262,8 +262,8 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
self.check_mempool([tx_v3_parent_large2["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_ancestors_package(self):
|
||||
self.log.info("Test that v3 ancestor limits are checked within the package")
|
||||
def test_truc_ancestors_package(self):
|
||||
self.log.info("Test that TRUC ancestor limits are checked within the package")
|
||||
node = self.nodes[0]
|
||||
tx_v3_parent_normal = self.wallet.create_self_transfer(
|
||||
fee_rate=0,
|
||||
@ -289,34 +289,34 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
|
||||
self.check_mempool([])
|
||||
result = node.submitpackage([tx_v3_parent_normal["hex"], tx_v3_parent_2_normal["hex"], tx_v3_child_multiparent["hex"]])
|
||||
assert_equal(result['package_msg'], f"v3-violation, tx {tx_v3_child_multiparent['txid']} (wtxid={tx_v3_child_multiparent['wtxid']}) would have too many ancestors")
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, tx {tx_v3_child_multiparent['txid']} (wtxid={tx_v3_child_multiparent['wtxid']}) would have too many ancestors")
|
||||
self.check_mempool([])
|
||||
|
||||
self.check_mempool([])
|
||||
result = node.submitpackage([tx_v3_parent_normal["hex"], tx_v3_child_heavy["hex"]])
|
||||
# tx_v3_child_heavy is heavy based on weight, not sigops.
|
||||
assert_equal(result['package_msg'], f"v3-violation, v3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big: {tx_v3_child_heavy['tx'].get_vsize()} > 1000 virtual bytes")
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, v3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big: {tx_v3_child_heavy['tx'].get_vsize()} > 1000 virtual bytes")
|
||||
self.check_mempool([])
|
||||
|
||||
tx_v3_parent = self.wallet.create_self_transfer(version=3)
|
||||
tx_v3_child = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_parent["new_utxo"], version=3)
|
||||
tx_v3_grandchild = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_child["new_utxo"], version=3)
|
||||
result = node.testmempoolaccept([tx_v3_parent["hex"], tx_v3_child["hex"], tx_v3_grandchild["hex"]])
|
||||
assert all([txresult["package-error"] == f"v3-violation, tx {tx_v3_grandchild['txid']} (wtxid={tx_v3_grandchild['wtxid']}) would have too many ancestors" for txresult in result])
|
||||
assert all([txresult["package-error"] == f"TRUC-violation, tx {tx_v3_grandchild['txid']} (wtxid={tx_v3_grandchild['wtxid']}) would have too many ancestors" for txresult in result])
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_ancestors_package_and_mempool(self):
|
||||
def test_truc_ancestors_package_and_mempool(self):
|
||||
"""
|
||||
A v3 transaction in a package cannot have 2 v3 parents.
|
||||
A TRUC transaction in a package cannot have 2 TRUC parents.
|
||||
Test that if we have a transaction graph A -> B -> C, where A, B, C are
|
||||
all v3 transactions, that we cannot use submitpackage to get the
|
||||
all TRUC transactions, that we cannot use submitpackage to get the
|
||||
transactions all into the mempool.
|
||||
|
||||
Verify, in particular, that if A is already in the mempool, then
|
||||
submitpackage(B, C) will fail.
|
||||
"""
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that v3 ancestor limits include transactions within the package and all in-mempool ancestors")
|
||||
self.log.info("Test that TRUC ancestor limits include transactions within the package and all in-mempool ancestors")
|
||||
# This is our transaction "A":
|
||||
tx_in_mempool = self.wallet.send_self_transfer(from_node=node, version=3)
|
||||
|
||||
@ -331,7 +331,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
|
||||
# submitpackage(B, C) should fail
|
||||
result = node.submitpackage([tx_0fee_parent["hex"], tx_child_violator["hex"]])
|
||||
assert_equal(result['package_msg'], f"v3-violation, tx {tx_child_violator['txid']} (wtxid={tx_child_violator['wtxid']}) would have too many ancestors")
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, tx {tx_child_violator['txid']} (wtxid={tx_child_violator['wtxid']}) would have too many ancestors")
|
||||
self.check_mempool([tx_in_mempool["txid"]])
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
@ -341,7 +341,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
However, this option is only available in single transaction acceptance. It doesn't work in
|
||||
a multi-testmempoolaccept (where RBF is disabled) or when doing package CPFP.
|
||||
"""
|
||||
self.log.info("Test v3 sibling eviction in submitpackage and multi-testmempoolaccept")
|
||||
self.log.info("Test TRUC sibling eviction in submitpackage and multi-testmempoolaccept")
|
||||
node = self.nodes[0]
|
||||
# Add a parent + child to mempool
|
||||
tx_mempool_parent = self.wallet.send_self_transfer_multi(
|
||||
@ -384,17 +384,17 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
# Fails with another non-related transaction via testmempoolaccept
|
||||
tx_unrelated = self.wallet.create_self_transfer(version=3)
|
||||
result_test_unrelated = node.testmempoolaccept([tx_sibling_1["hex"], tx_unrelated["hex"]])
|
||||
assert_equal(result_test_unrelated[0]["reject-reason"], "v3-rule-violation")
|
||||
assert_equal(result_test_unrelated[0]["reject-reason"], "TRUC-violation")
|
||||
|
||||
# Fails in a package via testmempoolaccept
|
||||
result_test_1p1c = node.testmempoolaccept([tx_sibling_1["hex"], tx_has_mempool_uncle["hex"]])
|
||||
assert_equal(result_test_1p1c[0]["reject-reason"], "v3-rule-violation")
|
||||
assert_equal(result_test_1p1c[0]["reject-reason"], "TRUC-violation")
|
||||
|
||||
# Allowed when tx is submitted in a package and evaluated individually.
|
||||
# Note that the child failed since it would be the 3rd generation.
|
||||
result_package_indiv = node.submitpackage([tx_sibling_1["hex"], tx_has_mempool_uncle["hex"]])
|
||||
self.check_mempool([tx_mempool_parent["txid"], tx_sibling_1["txid"]])
|
||||
expected_error_gen3 = f"v3-rule-violation, tx {tx_has_mempool_uncle['txid']} (wtxid={tx_has_mempool_uncle['wtxid']}) would have too many ancestors"
|
||||
expected_error_gen3 = f"TRUC-violation, tx {tx_has_mempool_uncle['txid']} (wtxid={tx_has_mempool_uncle['wtxid']}) would have too many ancestors"
|
||||
|
||||
assert_equal(result_package_indiv["tx-results"][tx_has_mempool_uncle['wtxid']]['error'], expected_error_gen3)
|
||||
|
||||
@ -402,17 +402,17 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
node.submitpackage([tx_mempool_parent["hex"], tx_sibling_2["hex"]])
|
||||
self.check_mempool([tx_mempool_parent["txid"], tx_sibling_2["txid"]])
|
||||
|
||||
# Child cannot pay for sibling eviction for parent, as it violates v3 topology limits
|
||||
# Child cannot pay for sibling eviction for parent, as it violates TRUC topology limits
|
||||
result_package_cpfp = node.submitpackage([tx_sibling_3["hex"], tx_bumps_parent_with_sibling["hex"]])
|
||||
self.check_mempool([tx_mempool_parent["txid"], tx_sibling_2["txid"]])
|
||||
expected_error_cpfp = f"v3-rule-violation, tx {tx_mempool_parent['txid']} (wtxid={tx_mempool_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_cpfp = f"TRUC-violation, tx {tx_mempool_parent['txid']} (wtxid={tx_mempool_parent['wtxid']}) would exceed descendant count limit"
|
||||
|
||||
assert_equal(result_package_cpfp["tx-results"][tx_sibling_3['wtxid']]['error'], expected_error_cpfp)
|
||||
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_package_inheritance(self):
|
||||
self.log.info("Test that v3 inheritance is checked within package")
|
||||
def test_truc_package_inheritance(self):
|
||||
self.log.info("Test that TRUC inheritance is checked within package")
|
||||
node = self.nodes[0]
|
||||
tx_v3_parent = self.wallet.create_self_transfer(
|
||||
fee_rate=0,
|
||||
@ -426,14 +426,14 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
)
|
||||
self.check_mempool([])
|
||||
result = node.submitpackage([tx_v3_parent["hex"], tx_v2_child["hex"]])
|
||||
assert_equal(result['package_msg'], f"v3-violation, non-v3 tx {tx_v2_child['txid']} (wtxid={tx_v2_child['wtxid']}) cannot spend from v3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})")
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, non-v3 tx {tx_v2_child['txid']} (wtxid={tx_v2_child['wtxid']}) cannot spend from v3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})")
|
||||
self.check_mempool([])
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_in_testmempoolaccept(self):
|
||||
def test_truc_in_testmempoolaccept(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
self.log.info("Test that v3 inheritance is accurately assessed in testmempoolaccept")
|
||||
self.log.info("Test that TRUC inheritance is accurately assessed in testmempoolaccept")
|
||||
tx_v2 = self.wallet.create_self_transfer(version=2)
|
||||
tx_v2_from_v2 = self.wallet.create_self_transfer(utxo_to_spend=tx_v2["new_utxo"], version=2)
|
||||
tx_v3_from_v2 = self.wallet.create_self_transfer(utxo_to_spend=tx_v2["new_utxo"], version=3)
|
||||
@ -447,11 +447,11 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
assert all([result["allowed"] for result in test_accept_v2_and_v3])
|
||||
|
||||
test_accept_v3_from_v2 = node.testmempoolaccept([tx_v2["hex"], tx_v3_from_v2["hex"]])
|
||||
expected_error_v3_from_v2 = f"v3-violation, v3 tx {tx_v3_from_v2['txid']} (wtxid={tx_v3_from_v2['wtxid']}) cannot spend from non-v3 tx {tx_v2['txid']} (wtxid={tx_v2['wtxid']})"
|
||||
expected_error_v3_from_v2 = f"TRUC-violation, v3 tx {tx_v3_from_v2['txid']} (wtxid={tx_v3_from_v2['wtxid']}) cannot spend from non-v3 tx {tx_v2['txid']} (wtxid={tx_v2['wtxid']})"
|
||||
assert all([result["package-error"] == expected_error_v3_from_v2 for result in test_accept_v3_from_v2])
|
||||
|
||||
test_accept_v2_from_v3 = node.testmempoolaccept([tx_v3["hex"], tx_v2_from_v3["hex"]])
|
||||
expected_error_v2_from_v3 = f"v3-violation, non-v3 tx {tx_v2_from_v3['txid']} (wtxid={tx_v2_from_v3['wtxid']}) cannot spend from v3 tx {tx_v3['txid']} (wtxid={tx_v3['wtxid']})"
|
||||
expected_error_v2_from_v3 = f"TRUC-violation, non-v3 tx {tx_v2_from_v3['txid']} (wtxid={tx_v2_from_v3['wtxid']}) cannot spend from v3 tx {tx_v3['txid']} (wtxid={tx_v3['wtxid']})"
|
||||
assert all([result["package-error"] == expected_error_v2_from_v3 for result in test_accept_v2_from_v3])
|
||||
|
||||
test_accept_pairs = node.testmempoolaccept([tx_v2["hex"], tx_v3["hex"], tx_v2_from_v2["hex"], tx_v3_from_v3["hex"]])
|
||||
@ -463,16 +463,16 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
tx_v3_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_parent["new_utxos"][0], version=3)
|
||||
tx_v3_child_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_parent["new_utxos"][1], version=3)
|
||||
test_accept_2children = node.testmempoolaccept([tx_v3_parent["hex"], tx_v3_child_1["hex"], tx_v3_child_2["hex"]])
|
||||
expected_error_2children = f"v3-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_2children = f"TRUC-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
assert all([result["package-error"] == expected_error_2children for result in test_accept_2children])
|
||||
|
||||
# Extra v3 transaction does not get incorrectly marked as extra descendant
|
||||
# Extra TRUC transaction does not get incorrectly marked as extra descendant
|
||||
test_accept_1child_with_exra = node.testmempoolaccept([tx_v3_parent["hex"], tx_v3_child_1["hex"], tx_v3_independent["hex"]])
|
||||
assert all([result["allowed"] for result in test_accept_1child_with_exra])
|
||||
|
||||
# Extra v3 transaction does not make us ignore the extra descendant
|
||||
# Extra TRUC transaction does not make us ignore the extra descendant
|
||||
test_accept_2children_with_exra = node.testmempoolaccept([tx_v3_parent["hex"], tx_v3_child_1["hex"], tx_v3_child_2["hex"], tx_v3_independent["hex"]])
|
||||
expected_error_extra = f"v3-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_extra = f"TRUC-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
assert all([result["package-error"] == expected_error_extra for result in test_accept_2children_with_exra])
|
||||
# Same result if the parent is already in mempool
|
||||
node.sendrawtransaction(tx_v3_parent["hex"])
|
||||
@ -482,7 +482,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
@cleanup(extra_args=None)
|
||||
def test_reorg_2child_rbf(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that children of a v3 transaction can be replaced individually, even if there are multiple due to reorg")
|
||||
self.log.info("Test that children of a TRUC transaction can be replaced individually, even if there are multiple due to reorg")
|
||||
|
||||
ancestor_tx = self.wallet.send_self_transfer_multi(from_node=node, num_outputs=2, version=3)
|
||||
self.check_mempool([ancestor_tx["txid"]])
|
||||
@ -511,8 +511,8 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
assert_equal(node.getmempoolentry(ancestor_tx["txid"])["descendantcount"], 3)
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_sibling_eviction(self):
|
||||
self.log.info("Test sibling eviction for v3")
|
||||
def test_truc_sibling_eviction(self):
|
||||
self.log.info("Test sibling eviction for TRUC")
|
||||
node = self.nodes[0]
|
||||
tx_v3_parent = self.wallet.send_self_transfer_multi(from_node=node, num_outputs=2, version=3)
|
||||
# This is the sibling to replace
|
||||
@ -609,7 +609,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
utxo_to_spend=tx_with_multi_children["new_utxos"][2],
|
||||
fee_rate=DEFAULT_FEE*50
|
||||
)
|
||||
expected_error_2siblings = f"v3-rule-violation, tx {tx_with_multi_children['txid']} (wtxid={tx_with_multi_children['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_2siblings = f"TRUC-violation, tx {tx_with_multi_children['txid']} (wtxid={tx_with_multi_children['wtxid']}) would exceed descendant count limit"
|
||||
assert_raises_rpc_error(-26, expected_error_2siblings, node.sendrawtransaction, tx_with_sibling3["hex"])
|
||||
|
||||
# However, an RBF (with conflicting inputs) is possible even if the resulting cluster size exceeds 2
|
||||
@ -627,21 +627,21 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
||||
node = self.nodes[0]
|
||||
self.wallet = MiniWallet(node)
|
||||
self.generate(self.wallet, 120)
|
||||
self.test_v3_max_vsize()
|
||||
self.test_v3_acceptance()
|
||||
self.test_v3_replacement()
|
||||
self.test_v3_bip125()
|
||||
self.test_v3_reorg()
|
||||
self.test_truc_max_vsize()
|
||||
self.test_truc_acceptance()
|
||||
self.test_truc_replacement()
|
||||
self.test_truc_bip125()
|
||||
self.test_truc_reorg()
|
||||
self.test_nondefault_package_limits()
|
||||
self.test_v3_ancestors_package()
|
||||
self.test_v3_ancestors_package_and_mempool()
|
||||
self.test_truc_ancestors_package()
|
||||
self.test_truc_ancestors_package_and_mempool()
|
||||
self.test_sibling_eviction_package()
|
||||
self.test_v3_package_inheritance()
|
||||
self.test_v3_in_testmempoolaccept()
|
||||
self.test_truc_package_inheritance()
|
||||
self.test_truc_in_testmempoolaccept()
|
||||
self.test_reorg_2child_rbf()
|
||||
self.test_v3_sibling_eviction()
|
||||
self.test_truc_sibling_eviction()
|
||||
self.test_reorg_sibling_eviction_1p2c()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
MempoolAcceptV3().main()
|
||||
MempoolTRUC().main()
|
||||
|
@ -114,16 +114,16 @@ class CreateTxWalletTest(BitcoinTestFramework):
|
||||
self.log.info('Check wallet does not create transactions with version=3 yet')
|
||||
wallet_rpc = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
|
||||
|
||||
self.nodes[0].createwallet("v3")
|
||||
wallet_v3 = self.nodes[0].get_wallet_rpc("v3")
|
||||
self.nodes[0].createwallet("version3")
|
||||
wallet_v3 = self.nodes[0].get_wallet_rpc("version3")
|
||||
|
||||
tx_data = wallet_rpc.send(outputs=[{wallet_v3.getnewaddress(): 25}], options={"change_position": 0})
|
||||
wallet_tx_data = wallet_rpc.gettransaction(tx_data["txid"])
|
||||
tx_current_version = tx_from_hex(wallet_tx_data["hex"])
|
||||
|
||||
# While v3 transactions are standard, the CURRENT_VERSION is 2.
|
||||
# While version=3 transactions are standard, the CURRENT_VERSION is 2.
|
||||
# This test can be removed if CURRENT_VERSION is changed, and replaced with tests that the
|
||||
# wallet handles v3 rules properly.
|
||||
# wallet handles TRUC rules properly.
|
||||
assert_equal(tx_current_version.version, 2)
|
||||
wallet_v3.unloadwallet()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user