| 1321 | } |
| 1322 | |
| 1323 | MempoolAcceptResult MemPoolAccept::AcceptSingleTransactionInternal(const CTransactionRef& ptx, ATMPArgs& args) |
| 1324 | { |
| 1325 | AssertLockHeld(cs_main); |
| 1326 | AssertLockHeld(m_pool.cs); |
| 1327 | |
| 1328 | Workspace ws(ptx); |
| 1329 | const std::vector<Wtxid> single_wtxid{ws.m_ptx->GetWitnessHash()}; |
| 1330 | |
| 1331 | if (!PreChecks(args, ws)) { |
| 1332 | if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) { |
| 1333 | // Failed for fee reasons. Provide the effective feerate and which tx was included. |
| 1334 | return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid); |
| 1335 | } |
| 1336 | return MempoolAcceptResult::Failure(ws.m_state); |
| 1337 | } |
| 1338 | |
| 1339 | if (m_subpackage.m_rbf && !ReplacementChecks(ws)) { |
| 1340 | if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) { |
| 1341 | // Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included. |
| 1342 | return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid); |
| 1343 | } |
| 1344 | return MempoolAcceptResult::Failure(ws.m_state); |
| 1345 | } |
| 1346 | |
| 1347 | // Check if the transaction would exceed the cluster size limit. |
| 1348 | if (!m_subpackage.m_changeset->CheckMemPoolPolicyLimits()) { |
| 1349 | ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-large-cluster", ""); |
| 1350 | return MempoolAcceptResult::Failure(ws.m_state); |
| 1351 | } |
| 1352 | |
| 1353 | // Now that we've verified the cluster limit is respected, we can perform |
| 1354 | // calculations involving the full ancestors of the tx. |
| 1355 | if (ws.m_conflicts.size()) { |
| 1356 | auto ancestors = m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle); |
| 1357 | |
| 1358 | // A transaction that spends outputs that would be replaced by it is invalid. Now |
| 1359 | // that we have the set of all ancestors we can detect this |
| 1360 | // pathological case by making sure ws.m_conflicts and this tx's ancestors don't |
| 1361 | // intersect. |
| 1362 | if (const auto err_string{EntriesAndTxidsDisjoint(ancestors, ws.m_conflicts, ptx->GetHash())}) { |
| 1363 | // We classify this as a consensus error because a transaction depending on something it |
| 1364 | // conflicts with would be inconsistent. |
| 1365 | ws.m_state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string); |
| 1366 | return MempoolAcceptResult::Failure(ws.m_state); |
| 1367 | } |
| 1368 | } |
| 1369 | |
| 1370 | m_subpackage.m_total_vsize = ws.m_vsize; |
| 1371 | m_subpackage.m_total_modified_fees = ws.m_modified_fees; |
| 1372 | |
| 1373 | // Individual modified feerate exceeded caller-defined max; abort |
| 1374 | if (args.m_client_maxfeerate && CFeeRate(ws.m_modified_fees, ws.m_vsize) > args.m_client_maxfeerate.value()) { |
| 1375 | ws.m_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "max feerate exceeded", ""); |
| 1376 | return MempoolAcceptResult::Failure(ws.m_state); |
| 1377 | } |
| 1378 | |
| 1379 | if (!args.m_bypass_limits && m_pool.m_opts.require_standard) { |
| 1380 | Wtxid dummy_wtxid; |
nothing calls this directly
no test coverage detected