mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-05-05 09:21:01 +02:00
mempool: log/halt when CalculateMemPoolAncestors fails unexpectedly
When CalculateMemPoolAncestors fails unexpectedly (e.g. it exceeds ancestor/descendant limits even though we expect no limits to be applied), add an error log entry for increased visibility. For debug builds, the application will even halt completely since this is not supposed to happen.
This commit is contained in:
parent
5481f65849
commit
47c4b1f52a
@ -394,8 +394,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ancestors_result{mempool.CalculateMemPoolAncestors(*iter, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
|
auto ancestors{mempool.AssumeCalculateMemPoolAncestors(__func__, *iter, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(CTxMemPool::setEntries{})};
|
|
||||||
|
|
||||||
onlyUnconfirmed(ancestors);
|
onlyUnconfirmed(ancestors);
|
||||||
ancestors.insert(iter);
|
ancestors.insert(iter);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <util/rbf.h>
|
#include <util/rbf.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
||||||
@ -36,9 +35,9 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
|||||||
|
|
||||||
// If all the inputs have nSequence >= maxint-1, it still might be
|
// If all the inputs have nSequence >= maxint-1, it still might be
|
||||||
// signaled for RBF if any unconfirmed parents have signaled.
|
// signaled for RBF if any unconfirmed parents have signaled.
|
||||||
CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
|
const CTxMemPoolEntry entry{*pool.mapTx.find(tx.GetHash())};
|
||||||
auto ancestors_result{pool.CalculateMemPoolAncestors(entry, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
|
auto ancestors{pool.AssumeCalculateMemPoolAncestors(__func__, entry, CTxMemPool::Limits::NoLimits(),
|
||||||
auto ancestors{std::move(ancestors_result).value_or(CTxMemPool::setEntries{})};
|
/*fSearchForParents=*/false)};
|
||||||
|
|
||||||
for (CTxMemPool::txiter it : ancestors) {
|
for (CTxMemPool::txiter it : ancestors) {
|
||||||
if (SignalsOptInRBF(it->GetTx())) {
|
if (SignalsOptInRBF(it->GetTx())) {
|
||||||
|
@ -451,8 +451,7 @@ static RPCHelpMan getmempoolancestors()
|
|||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ancestors_result{mempool.CalculateMemPoolAncestors(*it, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
|
auto ancestors{mempool.AssumeCalculateMemPoolAncestors(__func__, *it, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(CTxMemPool::setEntries{})};
|
|
||||||
|
|
||||||
if (!fVerbose) {
|
if (!fVerbose) {
|
||||||
UniValue o(UniValue::VARR);
|
UniValue o(UniValue::VARR);
|
||||||
|
@ -349,8 +349,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
|
|||||||
// mempool parents we'd calculate by searching, and it's important that
|
// mempool parents we'd calculate by searching, and it's important that
|
||||||
// we use the cached notion of ancestor transactions as the set of
|
// we use the cached notion of ancestor transactions as the set of
|
||||||
// things to update for removal.
|
// things to update for removal.
|
||||||
auto ancestors_result{CalculateMemPoolAncestors(entry, Limits::NoLimits(), /*fSearchForParents=*/false)};
|
auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits(), /*fSearchForParents=*/false)};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(setEntries{})};
|
|
||||||
// Note that UpdateAncestorsOf severs the child links that point to
|
// Note that UpdateAncestorsOf severs the child links that point to
|
||||||
// removeIt in the entries for the parents of removeIt.
|
// removeIt in the entries for the parents of removeIt.
|
||||||
UpdateAncestorsOf(false, removeIt, ancestors);
|
UpdateAncestorsOf(false, removeIt, ancestors);
|
||||||
@ -703,8 +702,7 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
|
|||||||
assert(setParentCheck.size() == it->GetMemPoolParentsConst().size());
|
assert(setParentCheck.size() == it->GetMemPoolParentsConst().size());
|
||||||
assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
|
assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
|
||||||
// Verify ancestor state is correct.
|
// Verify ancestor state is correct.
|
||||||
auto ancestors_result{CalculateMemPoolAncestors(*it, Limits::NoLimits())};
|
auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits())};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(setEntries{})};
|
|
||||||
uint64_t nCountCheck = ancestors.size() + 1;
|
uint64_t nCountCheck = ancestors.size() + 1;
|
||||||
uint64_t nSizeCheck = it->GetTxSize();
|
uint64_t nSizeCheck = it->GetTxSize();
|
||||||
CAmount nFeesCheck = it->GetModifiedFee();
|
CAmount nFeesCheck = it->GetModifiedFee();
|
||||||
@ -865,8 +863,7 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD
|
|||||||
if (it != mapTx.end()) {
|
if (it != mapTx.end()) {
|
||||||
mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
|
mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
|
||||||
// Now update all ancestors' modified fees with descendants
|
// Now update all ancestors' modified fees with descendants
|
||||||
auto ancestors_result{CalculateMemPoolAncestors(*it, Limits::NoLimits(), /*fSearchForParents=*/false)};
|
auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits(), /*fSearchForParents=*/false)};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(setEntries{})};
|
|
||||||
for (txiter ancestorIt : ancestors) {
|
for (txiter ancestorIt : ancestors) {
|
||||||
mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
|
mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
|
||||||
}
|
}
|
||||||
@ -1004,8 +1001,7 @@ int CTxMemPool::Expire(std::chrono::seconds time)
|
|||||||
|
|
||||||
void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
|
void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
|
||||||
{
|
{
|
||||||
auto ancestors_result{CalculateMemPoolAncestors(entry, Limits::NoLimits())};
|
auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits())};
|
||||||
auto ancestors{std::move(ancestors_result).value_or(CTxMemPool::setEntries{})};
|
|
||||||
return addUnchecked(entry, ancestors, validFeeEstimate);
|
return addUnchecked(entry, ancestors, validFeeEstimate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user