mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-12 19:20:42 +02:00
Give separate reject reasons to each TRUC check
This commit is contained in:
parent
416646d1ca
commit
cf65351293
@ -56,6 +56,7 @@ struct ParentInfo {
|
||||
};
|
||||
|
||||
std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize,
|
||||
const std::string& reason_prefix, std::string& out_reason,
|
||||
const Package& package,
|
||||
const CTxMemPool::setEntries& mempool_ancestors)
|
||||
{
|
||||
@ -69,11 +70,13 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
if (ptx->version == TRUC_VERSION) {
|
||||
// SingleTRUCChecks should have checked this already.
|
||||
if (!Assume(vsize <= TRUC_MAX_VSIZE)) {
|
||||
out_reason = reason_prefix + "vsize-toobig";
|
||||
return strprintf("version=3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_MAX_VSIZE);
|
||||
}
|
||||
|
||||
if (mempool_ancestors.size() + in_package_parents.size() + 1 > TRUC_ANCESTOR_LIMIT) {
|
||||
out_reason = reason_prefix + "ancestors-toomany";
|
||||
return strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
|
||||
}
|
||||
@ -82,6 +85,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
if (has_parent) {
|
||||
// A TRUC child cannot be too large.
|
||||
if (vsize > TRUC_CHILD_MAX_VSIZE) {
|
||||
out_reason = reason_prefix + "child-toobig";
|
||||
return strprintf("version=3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
vsize, TRUC_CHILD_MAX_VSIZE);
|
||||
@ -107,6 +111,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
|
||||
// If there is a parent, it must have the right version.
|
||||
if (parent_info.m_version != TRUC_VERSION) {
|
||||
out_reason = reason_prefix + "spends-nontruc";
|
||||
return strprintf("version=3 tx %s (wtxid=%s) cannot spend from non-version=3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString());
|
||||
@ -121,6 +126,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
// sibling is to-be-replaced (done in SingleTRUCChecks) because these transactions
|
||||
// are within the same package.
|
||||
if (input.prevout.hash == parent_info.m_txid) {
|
||||
out_reason = reason_prefix + "sibling-known";
|
||||
return strprintf("tx %s (wtxid=%s) would exceed descendant count limit",
|
||||
parent_info.m_txid.ToString(),
|
||||
parent_info.m_wtxid.ToString());
|
||||
@ -128,6 +134,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
|
||||
// This tx can't have both a parent and an in-package child.
|
||||
if (input.prevout.hash == ptx->GetHash()) {
|
||||
out_reason = reason_prefix + "parent-and-child-both";
|
||||
return strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
||||
package_tx->GetHash().ToString(), package_tx->GetWitnessHash().ToString());
|
||||
}
|
||||
@ -135,6 +142,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
}
|
||||
|
||||
if (parent_info.m_has_mempool_descendant) {
|
||||
out_reason = reason_prefix + "descendant-toomany";
|
||||
return strprintf("tx %s (wtxid=%s) would exceed descendant count limit",
|
||||
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString());
|
||||
}
|
||||
@ -143,6 +151,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
// Non-TRUC transactions cannot have TRUC parents.
|
||||
for (auto it : mempool_ancestors) {
|
||||
if (it->GetTx().version == TRUC_VERSION) {
|
||||
out_reason = reason_prefix + "spent-by-nontruc";
|
||||
return strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
it->GetSharedTx()->GetHash().ToString(), it->GetSharedTx()->GetWitnessHash().ToString());
|
||||
@ -150,6 +159,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
}
|
||||
for (const auto& index: in_package_parents) {
|
||||
if (package.at(index)->version == TRUC_VERSION) {
|
||||
out_reason = reason_prefix + "spent-by-nontruc";
|
||||
return strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(),
|
||||
ptx->GetWitnessHash().ToString(),
|
||||
@ -162,6 +172,7 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx,
|
||||
const std::string& reason_prefix, std::string& out_reason,
|
||||
const CTxMemPool::setEntries& mempool_ancestors,
|
||||
const std::set<Txid>& direct_conflicts,
|
||||
int64_t vsize)
|
||||
@ -169,11 +180,13 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
// Check TRUC and non-TRUC inheritance.
|
||||
for (const auto& entry : mempool_ancestors) {
|
||||
if (ptx->version != TRUC_VERSION && entry->GetTx().version == TRUC_VERSION) {
|
||||
out_reason = reason_prefix + "spent-by-nontruc";
|
||||
return std::make_pair(strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
||||
nullptr);
|
||||
} else if (ptx->version == TRUC_VERSION && entry->GetTx().version != TRUC_VERSION) {
|
||||
out_reason = reason_prefix + "spends-nontruc";
|
||||
return std::make_pair(strprintf("version=3 tx %s (wtxid=%s) cannot spend from non-version=3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
||||
@ -189,6 +202,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
if (ptx->version != TRUC_VERSION) return std::nullopt;
|
||||
|
||||
if (vsize > TRUC_MAX_VSIZE) {
|
||||
out_reason = reason_prefix + "vsize-toobig";
|
||||
return std::make_pair(strprintf("version=3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_MAX_VSIZE),
|
||||
nullptr);
|
||||
@ -196,6 +210,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
|
||||
// Check that TRUC_ANCESTOR_LIMIT would not be violated.
|
||||
if (mempool_ancestors.size() + 1 > TRUC_ANCESTOR_LIMIT) {
|
||||
out_reason = reason_prefix + "ancestors-toomany";
|
||||
return std::make_pair(strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString()),
|
||||
nullptr);
|
||||
@ -205,6 +220,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
if (mempool_ancestors.size() > 0) {
|
||||
// If this transaction spends TRUC parents, it cannot be too large.
|
||||
if (vsize > TRUC_CHILD_MAX_VSIZE) {
|
||||
out_reason = reason_prefix + "child-toobig";
|
||||
return std::make_pair(strprintf("version=3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_CHILD_MAX_VSIZE),
|
||||
nullptr);
|
||||
@ -233,6 +249,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
|
||||
// Return the sibling if its eviction can be considered. Provide the "descendant count
|
||||
// limit" string either way, as the caller may decide not to do sibling eviction.
|
||||
out_reason = reason_prefix + "descendants-toomany";
|
||||
return std::make_pair(strprintf("tx %u (wtxid=%s) would exceed descendant count limit",
|
||||
parent_entry->GetSharedTx()->GetHash().ToString(),
|
||||
parent_entry->GetSharedTx()->GetWitnessHash().ToString()),
|
||||
|
@ -62,6 +62,7 @@ static_assert(TRUC_MAX_VSIZE + TRUC_CHILD_MAX_VSIZE <= DEFAULT_DESCENDANT_SIZE_L
|
||||
* applicable.
|
||||
*/
|
||||
std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx,
|
||||
const std::string& reason_prefix, std::string& out_reason,
|
||||
const CTxMemPool::setEntries& mempool_ancestors,
|
||||
const std::set<Txid>& direct_conflicts,
|
||||
int64_t vsize);
|
||||
@ -88,6 +89,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
||||
* @returns debug string if an error occurs, std::nullopt otherwise.
|
||||
* */
|
||||
std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize,
|
||||
const std::string& reason_prefix, std::string& out_reason,
|
||||
const Package& package,
|
||||
const CTxMemPool::setEntries& mempool_ancestors);
|
||||
|
||||
|
@ -20,6 +20,18 @@
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(txvalidation_tests)
|
||||
|
||||
std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx, const CTxMemPool::setEntries& mempool_ancestors, const std::set<Txid>& direct_conflicts, int64_t vsize)
|
||||
{
|
||||
std::string dummy;
|
||||
return SingleTRUCChecks(ptx, dummy, dummy, mempool_ancestors, direct_conflicts, vsize);
|
||||
}
|
||||
|
||||
std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize, const Package& package, const CTxMemPool::setEntries& mempool_ancestors)
|
||||
{
|
||||
std::string dummy;
|
||||
return PackageTRUCChecks(ptx, vsize, dummy, dummy, package, mempool_ancestors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the mempool won't accept coinbase transactions.
|
||||
*/
|
||||
|
@ -1063,7 +1063,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// Even though just checking direct mempool parents for inheritance would be sufficient, we
|
||||
// check using the full ancestor set here because it's more convenient to use what we have
|
||||
// already calculated.
|
||||
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
|
||||
if (const auto err{SingleTRUCChecks(ws.m_ptx, "truc-", reason, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
|
||||
// Single transaction contexts only.
|
||||
if (args.m_allow_sibling_eviction && err->second != nullptr) {
|
||||
// We should only be considering where replacement is considered valid as well.
|
||||
@ -1082,7 +1082,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// (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, "TRUC-violation", err->first);
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, reason, err->first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1588,9 +1588,10 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
||||
|
||||
// At this point we have all in-mempool ancestors, and we know every transaction's vsize.
|
||||
// Run the TRUC checks on the package.
|
||||
std::string reason;
|
||||
for (Workspace& ws : workspaces) {
|
||||
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, txns, ws.m_ancestors)}) {
|
||||
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());
|
||||
if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, "truc-", reason, txns, ws.m_ancestors)}) {
|
||||
package_state.Invalid(PackageValidationResult::PCKG_POLICY, reason, err.value());
|
||||
return PackageMempoolAcceptResult(package_state, {});
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
self.log.info("Test TRUC-specific maximum transaction vsize")
|
||||
tx_v3_heavy = self.wallet.create_self_transfer(target_weight=(TRUC_MAX_VSIZE + 1) * WITNESS_SCALE_FACTOR, version=3)
|
||||
assert_greater_than_or_equal(tx_v3_heavy["tx"].get_vsize(), TRUC_MAX_VSIZE)
|
||||
expected_error_heavy = f"TRUC-violation, version=3 tx {tx_v3_heavy['txid']} (wtxid={tx_v3_heavy['wtxid']}) is too big"
|
||||
expected_error_heavy = f"truc-vsize-toobig, version=3 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([])
|
||||
|
||||
@ -77,7 +77,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
version=3
|
||||
)
|
||||
assert_greater_than_or_equal(tx_v3_child_heavy["tx"].get_vsize(), 1000)
|
||||
expected_error_child_heavy = f"TRUC-violation, version=3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big"
|
||||
expected_error_child_heavy = f"truc-child-toobig, version=3 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
|
||||
@ -157,7 +157,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
utxo_to_spend=tx_v3_parent["new_utxo"],
|
||||
version=2
|
||||
)
|
||||
expected_error_v2_v3 = f"TRUC-violation, non-version=3 tx {tx_v3_child_rbf_v2['txid']} (wtxid={tx_v3_child_rbf_v2['wtxid']}) cannot spend from version=3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})"
|
||||
expected_error_v2_v3 = f"truc-spent-by-nontruc, non-version=3 tx {tx_v3_child_rbf_v2['txid']} (wtxid={tx_v3_child_rbf_v2['wtxid']}) cannot spend from version=3 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"]])
|
||||
|
||||
@ -289,20 +289,20 @@ class MempoolTRUC(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"TRUC-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-ancestors-toomany, 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"TRUC-violation, version=3 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-child-toobig, version=3 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"TRUC-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-parent-and-child-both, 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_truc_ancestors_package_and_mempool(self):
|
||||
@ -331,7 +331,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
|
||||
# submitpackage(B, C) should fail
|
||||
result = node.submitpackage([tx_0fee_parent["hex"], tx_child_violator["hex"]])
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, tx {tx_child_violator['txid']} (wtxid={tx_child_violator['wtxid']}) would have too many ancestors")
|
||||
assert_equal(result['package_msg'], f"truc-parent-and-child-both, 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)
|
||||
@ -384,17 +384,17 @@ class MempoolTRUC(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"], "TRUC-violation")
|
||||
assert_equal(result_test_unrelated[0]["reject-reason"], "truc-descendants-toomany")
|
||||
|
||||
# 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"], "TRUC-violation")
|
||||
assert_equal(result_test_1p1c[0]["reject-reason"], "truc-descendants-toomany")
|
||||
|
||||
# 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"TRUC-violation, tx {tx_has_mempool_uncle['txid']} (wtxid={tx_has_mempool_uncle['wtxid']}) would have too many ancestors"
|
||||
expected_error_gen3 = f"truc-ancestors-toomany, 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)
|
||||
|
||||
@ -405,7 +405,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
# 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"TRUC-violation, tx {tx_mempool_parent['txid']} (wtxid={tx_mempool_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_cpfp = f"truc-descendants-toomany, 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)
|
||||
|
||||
@ -426,7 +426,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
)
|
||||
self.check_mempool([])
|
||||
result = node.submitpackage([tx_v3_parent["hex"], tx_v2_child["hex"]])
|
||||
assert_equal(result['package_msg'], f"TRUC-violation, non-version=3 tx {tx_v2_child['txid']} (wtxid={tx_v2_child['wtxid']}) cannot spend from version=3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})")
|
||||
assert_equal(result['package_msg'], f"truc-spent-by-nontruc, non-version=3 tx {tx_v2_child['txid']} (wtxid={tx_v2_child['wtxid']}) cannot spend from version=3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})")
|
||||
self.check_mempool([])
|
||||
|
||||
@cleanup(extra_args=None)
|
||||
@ -447,11 +447,11 @@ class MempoolTRUC(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"TRUC-violation, version=3 tx {tx_v3_from_v2['txid']} (wtxid={tx_v3_from_v2['wtxid']}) cannot spend from non-version=3 tx {tx_v2['txid']} (wtxid={tx_v2['wtxid']})"
|
||||
expected_error_v3_from_v2 = f"truc-spends-nontruc, version=3 tx {tx_v3_from_v2['txid']} (wtxid={tx_v3_from_v2['wtxid']}) cannot spend from non-version=3 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"TRUC-violation, non-version=3 tx {tx_v2_from_v3['txid']} (wtxid={tx_v2_from_v3['wtxid']}) cannot spend from version=3 tx {tx_v3['txid']} (wtxid={tx_v3['wtxid']})"
|
||||
expected_error_v2_from_v3 = f"truc-spent-by-nontruc, non-version=3 tx {tx_v2_from_v3['txid']} (wtxid={tx_v2_from_v3['wtxid']}) cannot spend from version=3 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,7 +463,7 @@ class MempoolTRUC(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"TRUC-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_2children = f"truc-sibling-known, 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 TRUC transaction does not get incorrectly marked as extra descendant
|
||||
@ -472,7 +472,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
|
||||
# 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"TRUC-violation, tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_extra = f"truc-sibling-known, 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"])
|
||||
@ -609,7 +609,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
utxo_to_spend=tx_with_multi_children["new_utxos"][2],
|
||||
fee_rate=DEFAULT_FEE*50
|
||||
)
|
||||
expected_error_2siblings = f"TRUC-violation, tx {tx_with_multi_children['txid']} (wtxid={tx_with_multi_children['wtxid']}) would exceed descendant count limit"
|
||||
expected_error_2siblings = f"truc-descendants-toomany, 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
|
||||
|
Loading…
Reference in New Issue
Block a user