|
|
@ -835,8 +835,9 @@ std::string FormatStateMessage(const CValidationState &state) |
|
|
|
state.GetRejectCode()); |
|
|
|
state.GetRejectCode()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee) |
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, |
|
|
|
|
|
|
|
std::vector<uint256>& vHashTxnToUncache) |
|
|
|
{ |
|
|
|
{ |
|
|
|
AssertLockHeld(cs_main); |
|
|
|
AssertLockHeld(cs_main); |
|
|
|
if (pfMissingInputs) |
|
|
|
if (pfMissingInputs) |
|
|
@ -917,13 +918,19 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa |
|
|
|
view.SetBackend(viewMemPool); |
|
|
|
view.SetBackend(viewMemPool); |
|
|
|
|
|
|
|
|
|
|
|
// do we already have it?
|
|
|
|
// do we already have it?
|
|
|
|
if (view.HaveCoins(hash)) |
|
|
|
bool fHadTxInCache = pcoinsTip->HaveCoinsInCache(hash); |
|
|
|
|
|
|
|
if (view.HaveCoins(hash)) { |
|
|
|
|
|
|
|
if (!fHadTxInCache) |
|
|
|
|
|
|
|
vHashTxnToUncache.push_back(hash); |
|
|
|
return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-known"); |
|
|
|
return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-known"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// do all inputs exist?
|
|
|
|
// do all inputs exist?
|
|
|
|
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
|
|
|
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
|
|
|
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
|
|
|
|
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
|
|
|
|
BOOST_FOREACH(const CTxIn txin, tx.vin) { |
|
|
|
BOOST_FOREACH(const CTxIn txin, tx.vin) { |
|
|
|
|
|
|
|
if (!pcoinsTip->HaveCoinsInCache(txin.prevout.hash)) |
|
|
|
|
|
|
|
vHashTxnToUncache.push_back(txin.prevout.hash); |
|
|
|
if (!view.HaveCoins(txin.prevout.hash)) { |
|
|
|
if (!view.HaveCoins(txin.prevout.hash)) { |
|
|
|
if (pfMissingInputs) |
|
|
|
if (pfMissingInputs) |
|
|
|
*pfMissingInputs = true; |
|
|
|
*pfMissingInputs = true; |
|
|
@ -1232,6 +1239,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, |
|
|
|
|
|
|
|
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::vector<uint256> vHashTxToUncache; |
|
|
|
|
|
|
|
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, fRejectAbsurdFee, vHashTxToUncache); |
|
|
|
|
|
|
|
if (!res) { |
|
|
|
|
|
|
|
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache) |
|
|
|
|
|
|
|
pcoinsTip->Uncache(hashTx); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ |
|
|
|
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ |
|
|
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) |
|
|
|
bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) |
|
|
|
{ |
|
|
|
{ |
|
|
|