From f128d49d2fa8ff675bacb5d2da2db56113f76924 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Thu, 20 Dec 2018 19:56:00 +0800 Subject: [PATCH] fix mempool fix, to allow adding transactions out of order. --- src/main.cpp | 47 ++++++++++++++++++++++-------------------- src/rpc/blockchain.cpp | 4 ---- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0a9efe6ea..98ed24c3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1645,6 +1645,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 ) tiptime = (uint32_t)time(NULL); else tiptime = (uint32_t)chainActive.LastTip()->nTime; + + // is it already in the memory pool? + uint256 hash = tx.GetHash(); + if (pool.exists(hash)) + { + //fprintf(stderr,"already in mempool\n"); + return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); + } + // Node operator can choose to reject tx by number of transparent inputs static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "size_t too small"); size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0); @@ -1683,7 +1692,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) + if (!fSkipExpiry && Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { // //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); @@ -1692,21 +1701,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Only accept nLockTime-using transactions that can be mined in the next // block; we don't want our mempool filled up with transactions that can't // be mined yet. - if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) + if (!fSkipExpiry && !CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } - // is it already in the memory pool? - uint256 hash = tx.GetHash(); - if (pool.exists(hash)) - { - //fprintf(stderr,"already in mempool\n"); - return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); - } - // Check for conflicts with in-memory transactions + if (!fSkipExpiry) { LOCK(pool.cs); // protect pool.mapNextTx for (unsigned int i = 0; i < tx.vin.size(); i++) @@ -1756,7 +1758,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (ExistsImportTombstone(tx, view)) return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists"); } - else + else if (!fSkipExpiry) { // do all inputs exist? // Note that this does not check for the presence of actual outputs (see the next check for that), @@ -1768,10 +1770,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pfMissingInputs) *pfMissingInputs = true; //fprintf(stderr,"missing inputs\n"); - if (!fSkipExpiry) - return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing"); - else - return(false); + return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing"); } } @@ -1779,10 +1778,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveInputs(tx)) { //fprintf(stderr,"accept failure.1\n"); - if (!fSkipExpiry) - return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); - else - return(false); + return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } // are the joinsplit's requirements met? @@ -1826,7 +1822,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. bool fSpendsCoinbase = false; - if (!tx.IsCoinImport()) { + if (!fSkipExpiry && !tx.IsCoinImport()) { BOOST_FOREACH(const CTxIn &txin, tx.vin) { const CCoins *coins = view.AccessCoins(txin.prevout.hash); if (coins->IsCoinBase()) { @@ -1901,7 +1897,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. PrecomputedTransactionData txdata(tx); - if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { //fprintf(stderr,"accept failure.9\n"); return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString()); @@ -1922,7 +1918,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa flag = 1; KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1; } - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { if ( flag != 0 ) KOMODO_CONNECTING = -1; @@ -4719,6 +4715,9 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // Check transactions CTransaction sTx; CTransaction *ptx = NULL; + if ( ASSETCHAINS_CC != 0 && !fCheckPOW ) + return true; + if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order { int32_t i,j,rejects=0,lastrejects=0; @@ -4788,6 +4787,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C if (!CheckTransaction(tiptime,tx, state, verifier)) return error("CheckBlock: CheckTransaction failed"); } + unsigned int nSigOps = 0; BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -7018,6 +7018,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == "tx") { + if (IsInitialBlockDownload()) + return true; + vector vWorkQueue; vector vEraseQueue; CTransaction tx; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 849391e18..c5da4ed40 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -639,10 +639,6 @@ UniValue getlastsegidstakes(const UniValue& params, bool fHelp) for (int64_t i = chainActive.Height(); i > chainActive.Height()-depth; i--) { CBlockIndex* pblockindex = chainActive[i]; - - //if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - // throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if ( pblockindex->segid >= 0 ) segids[pblockindex->segid] += 1; }