Change AcceptToMemoryPool function signature

Combine fLimitFree and fOverrideMempoolLimit into a single boolean:
bypass_limits.  This is used to indicate that mempool limiting based on feerate
should be bypassed.  It is used when readding transactions from a reorg and then
the mempool is trimmed to size after all transactions are added and they can be
evaluated in the context of their descendants. No changes to behavior.
This commit is contained in:
Alex Morcos 2017-09-12 12:30:26 -04:00
parent b9bceaf1c0
commit fd849e1b03
6 changed files with 27 additions and 21 deletions

View file

@ -1788,7 +1788,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::list<CTransactionRef> lRemovedTxn; std::list<CTransactionRef> lRemovedTxn;
if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs, &lRemovedTxn)) { if (!AlreadyHave(inv) &&
AcceptToMemoryPool(mempool, state, ptx, &fMissingInputs, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
mempool.check(pcoinsTip); mempool.check(pcoinsTip);
RelayTransaction(tx, connman); RelayTransaction(tx, connman);
for (unsigned int i = 0; i < tx.vout.size(); i++) { for (unsigned int i = 0; i < tx.vout.size(); i++) {
@ -1826,7 +1827,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (setMisbehaving.count(fromPeer)) if (setMisbehaving.count(fromPeer))
continue; continue;
if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, true, &fMissingInputs2, &lRemovedTxn)) { if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, &fMissingInputs2, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString()); LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx, connman); RelayTransaction(orphanTx, connman);
for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { for (unsigned int i = 0; i < orphanTx.vout.size(); i++) {

View file

@ -937,8 +937,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
// push to local node and sync with wallets // push to local node and sync with wallets
CValidationState state; CValidationState state;
bool fMissingInputs; bool fMissingInputs;
bool fLimitFree = true; if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, nullptr, false, nMaxRawTxFee)) { nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
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 {

View file

@ -29,7 +29,8 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main); LOCK(cs_main);
CValidationState state; CValidationState state;
return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), false, nullptr, nullptr, true, 0); return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */);
} }
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)

View file

@ -384,7 +384,9 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f
while (it != disconnectpool.queuedTx.get<insertion_order>().rend()) { while (it != disconnectpool.queuedTx.get<insertion_order>().rend()) {
// ignore validation errors in resurrected transactions // ignore validation errors in resurrected transactions
CValidationState stateDummy; CValidationState stateDummy;
if (!fAddToMempool || (*it)->IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, *it, false, nullptr, nullptr, true)) { if (!fAddToMempool || (*it)->IsCoinBase() ||
!AcceptToMemoryPool(mempool, stateDummy, *it, nullptr /* pfMissingInputs */,
nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */)) {
// If the transaction doesn't make it in to the mempool, remove any // If the transaction doesn't make it in to the mempool, remove any
// transactions that depend on it (which would now be orphans). // transactions that depend on it (which would now be orphans).
mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); mempool.removeRecursive(**it, MemPoolRemovalReason::REORG);
@ -443,9 +445,9 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, txdata); return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, txdata);
} }
static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced, bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache) bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache)
{ {
const CTransaction& tx = *ptx; const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash(); const uint256 hash = tx.GetHash();
@ -623,7 +625,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
} }
// No transactions are allowed below minRelayTxFee except from disconnected blocks // No transactions are allowed below minRelayTxFee except from disconnected blocks
if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) { if (!bypass_limits && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met"); return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
} }
@ -865,7 +867,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation); pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
// trim mempool and check if tx was trimmed // trim mempool and check if tx was trimmed
if (!fOverrideMempoolLimit) { if (!bypass_limits) {
LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
if (!pool.exists(hash)) if (!pool.exists(hash))
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full"); return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
@ -878,12 +880,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
} }
/** (try to) add transaction to memory pool with a specified acceptance time **/ /** (try to) add transaction to memory pool with a specified acceptance time **/
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced, bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee) bool bypass_limits, const CAmount nAbsurdFee)
{ {
std::vector<COutPoint> coins_to_uncache; std::vector<COutPoint> coins_to_uncache;
bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache); bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, pfMissingInputs, nAcceptTime, plTxnReplaced, bypass_limits, nAbsurdFee, coins_to_uncache);
if (!res) { if (!res) {
for (const COutPoint& hashTx : coins_to_uncache) for (const COutPoint& hashTx : coins_to_uncache)
pcoinsTip->Uncache(hashTx); pcoinsTip->Uncache(hashTx);
@ -894,12 +896,12 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo
return res; return res;
} }
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced, bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee) bool bypass_limits, const CAmount nAbsurdFee)
{ {
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee); return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, pfMissingInputs, GetTime(), plTxnReplaced, bypass_limits, nAbsurdFee);
} }
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */ /** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
@ -4306,7 +4308,8 @@ bool LoadMempool(void)
CValidationState state; CValidationState state;
if (nTime + nExpiryTimeout > nNow) { if (nTime + nExpiryTimeout > nNow) {
LOCK(cs_main); LOCK(cs_main);
AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, nullptr, nTime, nullptr, false, 0); AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, nullptr /* pfMissingInputs */, nTime,
nullptr /* plTxnReplaced */, false /* bypass_limits */, 0 /* nAbsurdFee */);
if (state.IsValid()) { if (state.IsValid()) {
++count; ++count;
} else { } else {

View file

@ -301,9 +301,9 @@ void PruneBlockFilesManual(int nManualPruneHeight);
/** (try to) add transaction to memory pool /** (try to) add transaction to memory pool
* plTxnReplaced will be appended to with all transactions replaced from mempool **/ * plTxnReplaced will be appended to with all transactions replaced from mempool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced = nullptr, bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0); bool bypass_limits, const CAmount nAbsurdFee);
/** Convert CValidationState to a human-readable message for logging */ /** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state); std::string FormatStateMessage(const CValidationState &state);

View file

@ -4014,5 +4014,6 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
{ {
return ::AcceptToMemoryPool(mempool, state, tx, true, nullptr, nullptr, false, nAbsurdFee); return ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */,
nullptr /* plTxnReplaced */, false /* bypass_limits */, nAbsurdFee);
} }