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:
parent
b9bceaf1c0
commit
fd849e1b03
6 changed files with 27 additions and 21 deletions
|
@ -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++) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue