Skip to content

Commit

Permalink
refactor: create PackageReplacementChecks
Browse files Browse the repository at this point in the history
  • Loading branch information
instagibbs committed Nov 14, 2023
1 parent b917850 commit 1b3ac98
Showing 1 changed file with 47 additions and 26 deletions.
73 changes: 47 additions & 26 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,12 @@ class MemPoolAccept
// Run checks for mempool replace-by-fee, only used in AcceptSingleTransaction.
bool ReplacementChecks(Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);

// Run checks for mempool replace-by-fee, only used in AcceptMultipleTransactions.
bool PackageReplacementChecks(std::vector<Workspace>& workspaces,
PackageValidationState& package_state,
CTxMemPool::setEntries& collective_ancestors,
std::string& err_string) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);

// Enforce package mempool ancestor/descendant limits (distinct from individual
// ancestor/descendant limits done in PreChecks) and run Package RBF checks.
bool PackageMempoolChecks(const ATMPArgs& args,
Expand Down Expand Up @@ -1061,31 +1067,12 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
return true;
}

bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args,
const std::vector<CTransactionRef>& txns,
std::vector<Workspace>& workspaces,
const int64_t total_vsize,
PackageValidationState& package_state)
{
AssertLockHeld(cs_main);
AssertLockHeld(m_pool.cs);

// CheckPackageLimits expects the package transactions to not already be in the mempool.
assert(std::all_of(txns.cbegin(), txns.cend(), [this](const auto& tx)
{ return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));

// Populate with the union of all transactions' ancestors.
CTxMemPool::setEntries m_collective_ancestors;
for (const auto& ws : workspaces) {
for (const auto& it : ws.m_ancestors) m_collective_ancestors.insert(it);
}

std::string err_string;
if (!m_pool.CheckPackageLimits(txns, total_vsize, err_string)) {
// This is a package-wide error, separate from an individual transaction error.
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", err_string);
}

bool MemPoolAccept::PackageReplacementChecks(std::vector<Workspace>& workspaces,
PackageValidationState& package_state,
CTxMemPool::setEntries& collective_ancestors,
std::string &err_string)
{
// Further checks are all RBF-only.
m_rbf = std::any_of(workspaces.cbegin(), workspaces.cend(), [](const auto& ws){return !ws.m_conflicts.empty();});
if (!m_rbf) return true;
Expand Down Expand Up @@ -1123,7 +1110,7 @@ bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args,
std::transform(m_all_conflicts.cbegin(), m_all_conflicts.cend(),
std::inserter(all_conflicting_txids, all_conflicting_txids.end()),
[](const auto& entry) { return entry->GetTx().GetHash(); });
if (const auto err_string{EntriesAndTxidsDisjoint(m_collective_ancestors, all_conflicting_txids, hash)}) {
if (const auto err_string{EntriesAndTxidsDisjoint(collective_ancestors, all_conflicting_txids, hash)}) {
// Note that we handle this differently in individual transaction validation (a transaction
// that conflicts with its own dependency is inconsistent, but this could just be
// conflicting transactions in a package).
Expand All @@ -1132,7 +1119,7 @@ bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args,
}

// Check if it's economically rational to mine this package rather than the ones it replaces.
if (const auto err_string{CheckMinerScores(m_total_modified_fees, m_total_vsize, m_collective_ancestors,
if (const auto err_string{CheckMinerScores(m_total_modified_fees, m_total_vsize, collective_ancestors,
direct_conflict_iters, m_all_conflicts)}) {
return package_state.Invalid(PackageValidationResult::PCKG_POLICY,
"package RBF failed: insufficient fees", *err_string);
Expand All @@ -1152,6 +1139,40 @@ bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args,
return true;
}


bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args,
const std::vector<CTransactionRef>& txns,
std::vector<Workspace>& workspaces,
const int64_t total_vsize,
PackageValidationState& package_state)
{
AssertLockHeld(cs_main);
AssertLockHeld(m_pool.cs);

// CheckPackageLimits expects the package transactions to not already be in the mempool.
assert(std::all_of(txns.cbegin(), txns.cend(), [this](const auto& tx)
{ return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));

// Populate with the union of all transactions' ancestors.
CTxMemPool::setEntries collective_ancestors;
for (const auto& ws : workspaces) {
for (const auto& it : ws.m_ancestors) collective_ancestors.insert(it);
}

std::string err_string;
if (!m_pool.CheckPackageLimits(txns, total_vsize, err_string)) {
// This is a package-wide error, separate from an individual transaction error.
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", err_string);
}

if (!PackageReplacementChecks(workspaces, package_state, collective_ancestors, err_string)) {
// package_state set by PackageReplacementChecks()
return false;
}

return true;
}

bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
{
AssertLockHeld(cs_main);
Expand Down

0 comments on commit 1b3ac98

Please sign in to comment.