Only call TrimToSize once per reorg/blocks disconnect
This commit is contained in:
parent
794a8cec5d
commit
d355cf4420
5 changed files with 22 additions and 13 deletions
15
src/main.cpp
15
src/main.cpp
|
@ -776,7 +776,7 @@ static std::string FormatStateMessage(const CValidationState &state)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||||
bool* pfMissingInputs, bool fRejectAbsurdFee)
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
|
@ -956,6 +956,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||||
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
|
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
|
||||||
|
|
||||||
// trim mempool and check if tx was trimmed
|
// trim mempool and check if tx was trimmed
|
||||||
|
if (!fOverrideMempoolLimit) {
|
||||||
int expired = pool.Expire(GetTime() - GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
|
int expired = pool.Expire(GetTime() - GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
|
||||||
if (expired != 0)
|
if (expired != 0)
|
||||||
LogPrint("mempool", "Expired %i transactions from the memory pool\n", expired);
|
LogPrint("mempool", "Expired %i transactions from the memory pool\n", expired);
|
||||||
|
@ -964,6 +965,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||||
if (!pool.exists(tx.GetHash()))
|
if (!pool.exists(tx.GetHash()))
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SyncWithWallets(tx, NULL);
|
SyncWithWallets(tx, NULL);
|
||||||
|
|
||||||
|
@ -2029,7 +2031,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Disconnect chainActive's tip. */
|
/** Disconnect chainActive's tip. You want to manually re-limit mempool size after this */
|
||||||
bool static DisconnectTip(CValidationState &state) {
|
bool static DisconnectTip(CValidationState &state) {
|
||||||
CBlockIndex *pindexDelete = chainActive.Tip();
|
CBlockIndex *pindexDelete = chainActive.Tip();
|
||||||
assert(pindexDelete);
|
assert(pindexDelete);
|
||||||
|
@ -2056,7 +2058,7 @@ bool static DisconnectTip(CValidationState &state) {
|
||||||
// ignore validation errors in resurrected transactions
|
// ignore validation errors in resurrected transactions
|
||||||
list<CTransaction> removed;
|
list<CTransaction> removed;
|
||||||
CValidationState stateDummy;
|
CValidationState stateDummy;
|
||||||
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) {
|
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
|
||||||
mempool.remove(tx, removed, true);
|
mempool.remove(tx, removed, true);
|
||||||
} else if (mempool.exists(tx.GetHash())) {
|
} else if (mempool.exists(tx.GetHash())) {
|
||||||
vHashUpdate.push_back(tx.GetHash());
|
vHashUpdate.push_back(tx.GetHash());
|
||||||
|
@ -2229,9 +2231,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
|
||||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
|
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
|
||||||
|
|
||||||
// Disconnect active blocks which are no longer in the best chain.
|
// Disconnect active blocks which are no longer in the best chain.
|
||||||
|
bool fBlocksDisconnected = false;
|
||||||
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
|
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
|
||||||
if (!DisconnectTip(state))
|
if (!DisconnectTip(state))
|
||||||
return false;
|
return false;
|
||||||
|
fBlocksDisconnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build list of new blocks to connect.
|
// Build list of new blocks to connect.
|
||||||
|
@ -2277,6 +2281,9 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fBlocksDisconnected)
|
||||||
|
mempool.TrimToSize(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
|
||||||
|
|
||||||
// Callbacks/notifications for a new best chain.
|
// Callbacks/notifications for a new best chain.
|
||||||
if (fInvalidFound)
|
if (fInvalidFound)
|
||||||
CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
|
CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
|
||||||
|
@ -2363,6 +2370,8 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mempool.TrimToSize(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
|
||||||
|
|
||||||
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
|
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
|
||||||
// add it again.
|
// add it again.
|
||||||
BlockMap::iterator it = mapBlockIndex.begin();
|
BlockMap::iterator it = mapBlockIndex.begin();
|
||||||
|
|
|
@ -229,7 +229,7 @@ void PruneAndFlush();
|
||||||
|
|
||||||
/** (try to) add transaction to memory pool **/
|
/** (try to) add transaction to memory pool **/
|
||||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||||
bool* pfMissingInputs, bool fRejectAbsurdFee=false);
|
bool* pfMissingInputs, bool fOverrideMempoolLimit=false, bool fRejectAbsurdFee=false);
|
||||||
|
|
||||||
|
|
||||||
struct CNodeStateStats {
|
struct CNodeStateStats {
|
||||||
|
|
|
@ -809,7 +809,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
|
||||||
// push to local node and sync with wallets
|
// push to local node and sync with wallets
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
bool fMissingInputs;
|
bool fMissingInputs;
|
||||||
if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
|
if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, !fOverrideFees)) {
|
||||||
if (state.IsInvalid()) {
|
if (state.IsInvalid()) {
|
||||||
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
|
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx)
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
return AcceptToMemoryPool(mempool, state, tx, false, NULL, false);
|
return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
|
|
|
@ -2863,6 +2863,6 @@ int CMerkleTx::GetBlocksToMaturity() const
|
||||||
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
|
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
|
||||||
{
|
{
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
|
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, fRejectAbsurdFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue