mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
CheckPackageMempoolAcceptResult: Check package rbf invariants
This commit is contained in:
parent
316d7b63c9
commit
d3466e4cc5
1 changed files with 28 additions and 0 deletions
|
@ -7,6 +7,7 @@
|
|||
#include <chainparams.h>
|
||||
#include <node/context.h>
|
||||
#include <node/mempool_args.h>
|
||||
#include <policy/rbf.h>
|
||||
#include <policy/v3_policy.h>
|
||||
#include <txmempool.h>
|
||||
#include <util/check.h>
|
||||
|
@ -68,6 +69,28 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
|||
return strprintf("tx %s unexpectedly failed: %s", wtxid.ToString(), atmp_result.m_state.ToString());
|
||||
}
|
||||
|
||||
// Each subpackage is allowed MAX_REPLACEMENT_CANDIDATES replacements (only checking individually here)
|
||||
if (atmp_result.m_replaced_transactions.size() > MAX_REPLACEMENT_CANDIDATES) {
|
||||
return strprintf("tx %s result replaced too many transactions",
|
||||
wtxid.ToString());
|
||||
}
|
||||
|
||||
// Replacements can't happen for subpackages larger than 2
|
||||
if (!atmp_result.m_replaced_transactions.empty() &&
|
||||
atmp_result.m_wtxids_fee_calculations.has_value() && atmp_result.m_wtxids_fee_calculations.value().size() > 2) {
|
||||
return strprintf("tx %s was part of a too-large package RBF subpackage",
|
||||
wtxid.ToString());
|
||||
}
|
||||
|
||||
if (!atmp_result.m_replaced_transactions.empty() && mempool) {
|
||||
LOCK(mempool->cs);
|
||||
// If replacements occurred and it used 2 transactions, this is a package RBF and should result in a cluster of size 2
|
||||
if (atmp_result.m_wtxids_fee_calculations.has_value() && atmp_result.m_wtxids_fee_calculations.value().size() == 2) {
|
||||
const auto cluster = mempool->GatherClusters({tx->GetHash()});
|
||||
if (cluster.size() != 2) return strprintf("tx %s has too many ancestors or descendants for a package rbf", wtxid.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// m_vsize and m_base_fees should exist iff the result was VALID or MEMPOOL_ENTRY
|
||||
const bool mempool_entry{atmp_result.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY};
|
||||
if (atmp_result.m_base_fees.has_value() != (valid || mempool_entry)) {
|
||||
|
@ -108,6 +131,11 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
|||
return strprintf("wtxid %s should not be in mempool", wtxid.ToString());
|
||||
}
|
||||
}
|
||||
for (const auto& tx_ref : atmp_result.m_replaced_transactions) {
|
||||
if (mempool->exists(GenTxid::Txid(tx_ref->GetHash()))) {
|
||||
return strprintf("tx %s should not be in mempool as it was replaced", tx_ref->GetWitnessHash().ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
|
Loading…
Add table
Reference in a new issue